nexo-brain 7.9.19 → 7.9.20

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": "7.9.19",
3
+ "version": "7.9.20",
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.9.19` is the current packaged-runtime line. Patch release over `7.9.18`: runtime doctor now distinguishes real install breakage from tracked in-progress work, interactive Desktop sessions no longer poison automation telemetry scoring, stale filesystem skill rows are pruned during sync, stale protocol debt draining marks rows resolved, and watchdog treats LaunchAgent SIGTERM reloads as supervisor interruptions instead of failures. It includes the v7.9.18 client-sync bootstrap fix.
21
+ Version `7.9.20` is the current packaged-runtime line. Patch release over `7.9.19`: packaged update/doctor repair now finds `runtime/crons/sync.py`, LaunchAgent PATH includes the managed Claude runtime installed under `~/.nexo/runtime/bootstrap/npm-global/bin`, root runtime backfill includes `claude_cli.py`, and Immune no longer treats the legacy optional `~/.claude-mem/claude-mem.db` as a required database.
22
+
23
+ Previously in `7.9.19`: runtime doctor now distinguishes real install breakage from tracked in-progress work, interactive Desktop sessions no longer poison automation telemetry scoring, stale filesystem skill rows are pruned during sync, stale protocol debt draining marks rows resolved, and watchdog treats LaunchAgent SIGTERM reloads as supervisor interruptions instead of failures.
22
24
 
23
25
  Previously in `7.9.18`: packaged client-sync imports now work when `NEXO_HOME` is unset, so `nexo clients sync`, `nexo update`, and runtime doctor bootstrap checks no longer hit the `_user_home` import-order crash.
24
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "7.9.19",
3
+ "version": "7.9.20",
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",
@@ -3816,7 +3816,7 @@ def _auto_update_check_locked() -> dict:
3816
3816
 
3817
3817
  # Backfill runtime CLI modules for existing installs
3818
3818
  try:
3819
- for fname in ("cli.py", "script_registry.py", "skills_runtime.py", "cron_recovery.py", "client_preferences.py", "agent_runner.py", "bootstrap_docs.py"):
3819
+ for fname in ("cli.py", "script_registry.py", "skills_runtime.py", "cron_recovery.py", "client_preferences.py", "claude_cli.py", "agent_runner.py", "bootstrap_docs.py"):
3820
3820
  src_file = SRC_DIR / fname
3821
3821
  dest_file = NEXO_HOME / fname
3822
3822
  if src_file.is_file() and (not dest_file.exists() or src_file.stat().st_mtime > dest_file.stat().st_mtime):
package/src/crons/sync.py CHANGED
@@ -39,8 +39,15 @@ except ImportError:
39
39
  def resolve_launchagent_path() -> str:
40
40
  """Fallback when runtime_power is not importable."""
41
41
  home = Path.home()
42
- parts = ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin",
43
- str(home / ".local/bin"), str(home / ".nexo/bin")]
42
+ parts = [
43
+ str(home / ".nexo/runtime/bootstrap/npm-global/bin"),
44
+ "/opt/homebrew/bin",
45
+ "/usr/local/bin",
46
+ "/usr/bin",
47
+ "/bin",
48
+ str(home / ".local/bin"),
49
+ str(home / ".nexo/bin"),
50
+ ]
44
51
  nvm_dir = home / ".nvm/versions/node"
45
52
  if nvm_dir.is_dir():
46
53
  versions = sorted(nvm_dir.iterdir(), key=lambda p: p.stat().st_mtime, reverse=True)
@@ -1131,17 +1131,20 @@ def _repair_special_launchagent_plists(items: list[tuple[str, Path]]) -> tuple[b
1131
1131
 
1132
1132
 
1133
1133
  def _sync_launchagents_from_manifest() -> tuple[bool, list[str]]:
1134
- sync_path = NEXO_CODE / "crons" / "sync.py"
1134
+ sync_path = paths.crons_dir() / "sync.py"
1135
+ if not sync_path.is_file():
1136
+ sync_path = NEXO_CODE / "crons" / "sync.py"
1135
1137
  if not sync_path.is_file():
1136
1138
  return False, [f"cron sync script not found at {sync_path}"]
1137
1139
 
1138
1140
  try:
1141
+ runtime_code = paths.core_dir()
1139
1142
  result = subprocess.run(
1140
1143
  [sys.executable, str(sync_path)],
1141
1144
  capture_output=True,
1142
1145
  text=True,
1143
1146
  timeout=30,
1144
- env={**os.environ, "NEXO_HOME": str(NEXO_HOME), "NEXO_CODE": str(NEXO_CODE)},
1147
+ env={**os.environ, "NEXO_HOME": str(NEXO_HOME), "NEXO_CODE": str(runtime_code)},
1145
1148
  )
1146
1149
  except Exception as e:
1147
1150
  return False, [f"cron sync failed: {e}"]
@@ -80,8 +80,15 @@ DEFAULT_CODEX_REASONING_EFFORT = _CODEX_DEFAULTS["reasoning_effort"]
80
80
  def resolve_launchagent_path() -> str:
81
81
  """Build a PATH string for LaunchAgent plists that includes nvm node if present."""
82
82
  home = Path.home()
83
- parts = ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin",
84
- str(home / ".local/bin"), str(home / ".nexo/bin")]
83
+ parts = [
84
+ str(home / ".nexo/runtime/bootstrap/npm-global/bin"),
85
+ "/opt/homebrew/bin",
86
+ "/usr/local/bin",
87
+ "/usr/bin",
88
+ "/bin",
89
+ str(home / ".local/bin"),
90
+ str(home / ".nexo/bin"),
91
+ ]
85
92
  # Detect nvm node
86
93
  nvm_dir = home / ".nvm/versions/node"
87
94
  if nvm_dir.is_dir():
@@ -367,8 +367,9 @@ def check_databases():
367
367
  dbs = [
368
368
  ("nexo.db", paths.db_path()),
369
369
  ("cognitive.db", paths.data_dir() / "cognitive.db"),
370
- ("claude-mem.db", CLAUDE_MEM_DB),
371
370
  ]
371
+ if CLAUDE_MEM_DB.exists():
372
+ dbs.append(("claude-mem.db", CLAUDE_MEM_DB))
372
373
 
373
374
  for name, path in dbs:
374
375
  result = {"name": name, "status": "OK", "detail": ""}