nexo-brain 2.1.0 → 2.2.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.
Files changed (235) hide show
  1. package/README.md +3 -3
  2. package/bin/nexo-brain.js +53 -26
  3. package/package.json +1 -1
  4. package/scripts/migrate-to-unified 2.sh +813 -0
  5. package/scripts/migrate-v1.5-to-v1.6 2.py +778 -0
  6. package/scripts/migrate-v1.7-to-v1.8 2.py +214 -0
  7. package/scripts/pre-commit-check 2.sh +55 -0
  8. package/src/__pycache__/auto_update.cpython-310.pyc +0 -0
  9. package/src/__pycache__/hnsw_index.cpython-310.pyc +0 -0
  10. package/src/__pycache__/kg_populate.cpython-310.pyc +0 -0
  11. package/src/__pycache__/knowledge_graph.cpython-310.pyc +0 -0
  12. package/src/__pycache__/plugin_loader.cpython-310.pyc +0 -0
  13. package/src/__pycache__/tools_coordination.cpython-310.pyc +0 -0
  14. package/src/__pycache__/tools_credentials.cpython-310.pyc +0 -0
  15. package/src/__pycache__/tools_learnings.cpython-310.pyc +0 -0
  16. package/src/__pycache__/tools_menu.cpython-310.pyc +0 -0
  17. package/src/__pycache__/tools_reminders.cpython-310.pyc +0 -0
  18. package/src/__pycache__/tools_reminders_crud.cpython-310.pyc +0 -0
  19. package/src/__pycache__/tools_sessions.cpython-310.pyc +0 -0
  20. package/src/__pycache__/tools_task_history.cpython-310.pyc +0 -0
  21. package/src/auto_close_sessions 2.py +159 -0
  22. package/src/auto_update 2.py +634 -0
  23. package/src/claim_graph 2.py +323 -0
  24. package/src/cognitive/__init__ 2.py +62 -0
  25. package/src/cognitive/__pycache__/__init__.cpython-310.pyc +0 -0
  26. package/src/cognitive/__pycache__/_core.cpython-310.pyc +0 -0
  27. package/src/cognitive/__pycache__/_decay.cpython-310.pyc +0 -0
  28. package/src/cognitive/__pycache__/_ingest.cpython-310.pyc +0 -0
  29. package/src/cognitive/__pycache__/_memory.cpython-310.pyc +0 -0
  30. package/src/cognitive/__pycache__/_search.cpython-310.pyc +0 -0
  31. package/src/cognitive/__pycache__/_trust.cpython-310.pyc +0 -0
  32. package/src/cognitive/_core 2.py +567 -0
  33. package/src/cognitive/_decay 2.py +382 -0
  34. package/src/cognitive/_ingest 2.py +892 -0
  35. package/src/cognitive/_memory 2.py +912 -0
  36. package/src/cognitive/_search 2.py +949 -0
  37. package/src/cognitive/_trust 2.py +464 -0
  38. package/src/cognitive/_trust.py +10 -36
  39. package/src/crons/manifest 2.json +106 -0
  40. package/src/crons/sync 2.py +217 -0
  41. package/src/dashboard/__init__ 2.py +0 -0
  42. package/src/dashboard/__pycache__/__init__.cpython-310.pyc +0 -0
  43. package/src/dashboard/__pycache__/app.cpython-310.pyc +0 -0
  44. package/src/dashboard/app 2.py +789 -0
  45. package/src/db/__init__ 2.py +89 -0
  46. package/src/db/__pycache__/__init__.cpython-310.pyc +0 -0
  47. package/src/db/__pycache__/__init__.cpython-312.pyc +0 -0
  48. package/src/db/__pycache__/__init__.cpython-314.pyc +0 -0
  49. package/src/db/__pycache__/_core.cpython-310.pyc +0 -0
  50. package/src/db/__pycache__/_core.cpython-312.pyc +0 -0
  51. package/src/db/__pycache__/_core.cpython-314.pyc +0 -0
  52. package/src/db/__pycache__/_credentials.cpython-310.pyc +0 -0
  53. package/src/db/__pycache__/_credentials.cpython-312.pyc +0 -0
  54. package/src/db/__pycache__/_credentials.cpython-314.pyc +0 -0
  55. package/src/db/__pycache__/_entities.cpython-310.pyc +0 -0
  56. package/src/db/__pycache__/_entities.cpython-312.pyc +0 -0
  57. package/src/db/__pycache__/_entities.cpython-314.pyc +0 -0
  58. package/src/db/__pycache__/_episodic.cpython-310.pyc +0 -0
  59. package/src/db/__pycache__/_episodic.cpython-312.pyc +0 -0
  60. package/src/db/__pycache__/_episodic.cpython-314.pyc +0 -0
  61. package/src/db/__pycache__/_evolution.cpython-310.pyc +0 -0
  62. package/src/db/__pycache__/_evolution.cpython-312.pyc +0 -0
  63. package/src/db/__pycache__/_evolution.cpython-314.pyc +0 -0
  64. package/src/db/__pycache__/_fts.cpython-310.pyc +0 -0
  65. package/src/db/__pycache__/_fts.cpython-312.pyc +0 -0
  66. package/src/db/__pycache__/_fts.cpython-314.pyc +0 -0
  67. package/src/db/__pycache__/_learnings.cpython-310.pyc +0 -0
  68. package/src/db/__pycache__/_learnings.cpython-312.pyc +0 -0
  69. package/src/db/__pycache__/_learnings.cpython-314.pyc +0 -0
  70. package/src/db/__pycache__/_reminders.cpython-310.pyc +0 -0
  71. package/src/db/__pycache__/_reminders.cpython-312.pyc +0 -0
  72. package/src/db/__pycache__/_reminders.cpython-314.pyc +0 -0
  73. package/src/db/__pycache__/_schema.cpython-310.pyc +0 -0
  74. package/src/db/__pycache__/_schema.cpython-312.pyc +0 -0
  75. package/src/db/__pycache__/_schema.cpython-314.pyc +0 -0
  76. package/src/db/__pycache__/_sessions.cpython-310.pyc +0 -0
  77. package/src/db/__pycache__/_sessions.cpython-312.pyc +0 -0
  78. package/src/db/__pycache__/_sessions.cpython-314.pyc +0 -0
  79. package/src/db/__pycache__/_tasks.cpython-310.pyc +0 -0
  80. package/src/db/__pycache__/_tasks.cpython-312.pyc +0 -0
  81. package/src/db/__pycache__/_tasks.cpython-314.pyc +0 -0
  82. package/src/db/_core 2.py +417 -0
  83. package/src/db/_credentials 2.py +124 -0
  84. package/src/db/_entities 2.py +178 -0
  85. package/src/db/_episodic 2.py +738 -0
  86. package/src/db/_evolution 2.py +54 -0
  87. package/src/db/_fts 2.py +406 -0
  88. package/src/db/_learnings 2.py +168 -0
  89. package/src/db/_reminders 2.py +338 -0
  90. package/src/db/_schema 2.py +364 -0
  91. package/src/db/_sessions 2.py +300 -0
  92. package/src/db/_tasks 2.py +91 -0
  93. package/src/evolution_cycle 2.py +266 -0
  94. package/src/hnsw_index 2.py +254 -0
  95. package/src/hooks/auto_capture 2.py +208 -0
  96. package/src/hooks/caffeinate-guard 2.sh +8 -0
  97. package/src/hooks/capture-session 2.sh +21 -0
  98. package/src/hooks/capture-session.sh +2 -0
  99. package/src/hooks/capture-tool-logs 2.sh +127 -0
  100. package/src/hooks/capture-tool-logs.sh +3 -2
  101. package/src/hooks/daily-briefing-check 2.sh +33 -0
  102. package/src/hooks/inbox-hook 2.sh +76 -0
  103. package/src/hooks/inbox-hook.sh +3 -2
  104. package/src/hooks/post-compact 2.sh +148 -0
  105. package/src/hooks/post-compact.sh +1 -1
  106. package/src/hooks/pre-compact 2.sh +151 -0
  107. package/src/hooks/pre-compact.sh +1 -1
  108. package/src/hooks/session-start 2.sh +268 -0
  109. package/src/hooks/session-start.sh +6 -3
  110. package/src/hooks/session-stop 2.sh +140 -0
  111. package/src/hooks/session-stop.sh +1 -1
  112. package/src/kg_populate 2.py +290 -0
  113. package/src/knowledge_graph 2.py +257 -0
  114. package/src/maintenance 2.py +59 -0
  115. package/src/migrate_embeddings 2.py +122 -0
  116. package/src/plugin_loader 2.py +202 -0
  117. package/src/plugins/__init__ 2.py +0 -0
  118. package/src/plugins/__pycache__/__init__ 2.cpython-310.pyc +0 -0
  119. package/src/plugins/__pycache__/__init__.cpython-310.pyc +0 -0
  120. package/src/plugins/__pycache__/adaptive_mode 2.cpython-310.pyc +0 -0
  121. package/src/plugins/__pycache__/adaptive_mode.cpython-310.pyc +0 -0
  122. package/src/plugins/__pycache__/agents 2.cpython-310.pyc +0 -0
  123. package/src/plugins/__pycache__/agents.cpython-310.pyc +0 -0
  124. package/src/plugins/__pycache__/artifact_registry 2.cpython-310.pyc +0 -0
  125. package/src/plugins/__pycache__/artifact_registry.cpython-310.pyc +0 -0
  126. package/src/plugins/__pycache__/backup 2.cpython-310.pyc +0 -0
  127. package/src/plugins/__pycache__/backup.cpython-310.pyc +0 -0
  128. package/src/plugins/__pycache__/cognitive_memory 2.cpython-310.pyc +0 -0
  129. package/src/plugins/__pycache__/cognitive_memory.cpython-310.pyc +0 -0
  130. package/src/plugins/__pycache__/core_rules 2.cpython-310.pyc +0 -0
  131. package/src/plugins/__pycache__/core_rules.cpython-310.pyc +0 -0
  132. package/src/plugins/__pycache__/cortex 2.cpython-310.pyc +0 -0
  133. package/src/plugins/__pycache__/cortex.cpython-310.pyc +0 -0
  134. package/src/plugins/__pycache__/entities 2.cpython-310.pyc +0 -0
  135. package/src/plugins/__pycache__/entities.cpython-310.pyc +0 -0
  136. package/src/plugins/__pycache__/episodic_memory 2.cpython-310.pyc +0 -0
  137. package/src/plugins/__pycache__/episodic_memory.cpython-310.pyc +0 -0
  138. package/src/plugins/__pycache__/evolution 2.cpython-310.pyc +0 -0
  139. package/src/plugins/__pycache__/evolution.cpython-310.pyc +0 -0
  140. package/src/plugins/__pycache__/guard 2.cpython-310.pyc +0 -0
  141. package/src/plugins/__pycache__/guard.cpython-310.pyc +0 -0
  142. package/src/plugins/__pycache__/knowledge_graph_tools 2.cpython-310.pyc +0 -0
  143. package/src/plugins/__pycache__/knowledge_graph_tools.cpython-310.pyc +0 -0
  144. package/src/plugins/__pycache__/preferences 2.cpython-310.pyc +0 -0
  145. package/src/plugins/__pycache__/preferences.cpython-310.pyc +0 -0
  146. package/src/plugins/__pycache__/update 2.cpython-310.pyc +0 -0
  147. package/src/plugins/__pycache__/update.cpython-310.pyc +0 -0
  148. package/src/plugins/adaptive_mode 2.py +805 -0
  149. package/src/plugins/agents 2.py +52 -0
  150. package/src/plugins/artifact_registry 2.py +450 -0
  151. package/src/plugins/backup 2.py +104 -0
  152. package/src/plugins/cognitive_memory 2.py +564 -0
  153. package/src/plugins/core_rules 2.py +252 -0
  154. package/src/plugins/cortex 2.py +299 -0
  155. package/src/plugins/entities 2.py +67 -0
  156. package/src/plugins/episodic_memory 2.py +533 -0
  157. package/src/plugins/evolution 2.py +115 -0
  158. package/src/plugins/guard 2.py +746 -0
  159. package/src/plugins/knowledge_graph_tools 2.py +105 -0
  160. package/src/plugins/preferences 2.py +47 -0
  161. package/src/plugins/update 2.py +256 -0
  162. package/src/requirements 2.txt +12 -0
  163. package/src/rules/__init__ 2.py +0 -0
  164. package/src/rules/core-rules 2.json +331 -0
  165. package/src/rules/migrate 2.py +207 -0
  166. package/src/scripts/check-context 2.py +264 -0
  167. package/src/scripts/deep-sleep/apply_findings.py +58 -0
  168. package/src/scripts/deep-sleep/synthesize-prompt.md +30 -1
  169. package/src/scripts/nexo-auto-update 2.py +6 -0
  170. package/src/scripts/nexo-backup 2.sh +25 -0
  171. package/src/scripts/nexo-brain-activation 2.sh +140 -0
  172. package/src/scripts/nexo-catchup 2.py +242 -0
  173. package/src/scripts/nexo-cognitive-decay 2.py +182 -0
  174. package/src/scripts/nexo-daily-self-audit 2.py +552 -0
  175. package/src/scripts/nexo-deep-sleep 2.sh +97 -0
  176. package/src/scripts/nexo-evolution-run 2.py +597 -0
  177. package/src/scripts/nexo-followup-hygiene 2.py +112 -0
  178. package/src/scripts/nexo-github-monitor 2.py +256 -0
  179. package/src/scripts/nexo-immune 2.py +927 -0
  180. package/src/scripts/nexo-inbox-hook 2.sh +74 -0
  181. package/src/scripts/nexo-install 2.py +6 -0
  182. package/src/scripts/nexo-learning-housekeep 2.py +245 -0
  183. package/src/scripts/nexo-learning-validator 2.py +207 -0
  184. package/src/scripts/nexo-migrate 2.py +232 -0
  185. package/src/scripts/nexo-postmortem-consolidator 2.py +421 -0
  186. package/src/scripts/nexo-pre-commit 2.py +120 -0
  187. package/src/scripts/nexo-prevent-sleep 2.sh +29 -0
  188. package/src/scripts/nexo-proactive-dashboard 2.py +345 -0
  189. package/src/scripts/nexo-reflection 2.py +253 -0
  190. package/src/scripts/nexo-runtime-preflight 2.py +274 -0
  191. package/src/scripts/nexo-send-email 2.py +25 -0
  192. package/src/scripts/nexo-send-reply 2.py +178 -0
  193. package/src/scripts/nexo-sleep 2.py +592 -0
  194. package/src/scripts/nexo-snapshot-restore 2.sh +35 -0
  195. package/src/scripts/nexo-synthesis 2.py +253 -0
  196. package/src/scripts/nexo-tcc-approve 2.sh +79 -0
  197. package/src/scripts/nexo-update 2.sh +161 -0
  198. package/src/scripts/nexo-watchdog 2.sh +878 -0
  199. package/src/scripts/nexo-watchdog-smoke 2.py +119 -0
  200. package/src/server 2.py +733 -0
  201. package/src/server.py +6 -1
  202. package/src/storage_router 2.py +32 -0
  203. package/src/tools_coordination 2.py +102 -0
  204. package/src/tools_credentials 2.py +68 -0
  205. package/src/tools_learnings 2.py +220 -0
  206. package/src/tools_menu 2.py +227 -0
  207. package/src/tools_reminders 2.py +86 -0
  208. package/src/tools_reminders_crud 2.py +159 -0
  209. package/src/tools_reminders_crud.py +7 -0
  210. package/src/tools_sessions 2.py +476 -0
  211. package/src/tools_task_history 2.py +57 -0
  212. package/templates/CLAUDE.md 2.template +63 -0
  213. package/templates/openclaw 2.json +13 -0
  214. package/tests/__init__ 2.py +0 -0
  215. package/tests/conftest 2.py +71 -0
  216. package/tests/test_cognitive 2.py +205 -0
  217. package/tests/test_knowledge_graph 2.py +140 -0
  218. package/tests/test_migrations 2.py +137 -0
  219. package/src/__pycache__/hnsw_index.cpython-314.pyc +0 -0
  220. package/src/cognitive/__pycache__/__init__.cpython-312.pyc +0 -0
  221. package/src/cognitive/__pycache__/__init__.cpython-314.pyc +0 -0
  222. package/src/cognitive/__pycache__/_core.cpython-312.pyc +0 -0
  223. package/src/cognitive/__pycache__/_core.cpython-314.pyc +0 -0
  224. package/src/cognitive/__pycache__/_decay.cpython-312.pyc +0 -0
  225. package/src/cognitive/__pycache__/_decay.cpython-314.pyc +0 -0
  226. package/src/cognitive/__pycache__/_ingest.cpython-312.pyc +0 -0
  227. package/src/cognitive/__pycache__/_ingest.cpython-314.pyc +0 -0
  228. package/src/cognitive/__pycache__/_memory.cpython-312.pyc +0 -0
  229. package/src/cognitive/__pycache__/_memory.cpython-314.pyc +0 -0
  230. package/src/cognitive/__pycache__/_search.cpython-312.pyc +0 -0
  231. package/src/cognitive/__pycache__/_search.cpython-314.pyc +0 -0
  232. package/src/cognitive/__pycache__/_trust.cpython-312.pyc +0 -0
  233. package/src/cognitive/__pycache__/_trust.cpython-314.pyc +0 -0
  234. package/src/plugins/__pycache__/adaptive_mode.cpython-314.pyc +0 -0
  235. package/src/scripts/deep-sleep/__pycache__/extract.cpython-314.pyc +0 -0
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ NEXO Watchdog Smoke
4
+
5
+ Runs the same health checks as the shell watchdog, but never restores files,
6
+ restarts services, disables evolution or notifies the user.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import os
14
+ import sqlite3
15
+ import subprocess
16
+ from datetime import datetime
17
+ from pathlib import Path
18
+
19
+ HOME = Path.home()
20
+ NEXO_HOME = Path(os.environ.get("NEXO_HOME", str(HOME / ".nexo")))
21
+ NEXO_CODE = Path(os.environ.get("NEXO_CODE", str(NEXO_HOME)))
22
+ BRAIN_DIR = NEXO_HOME / "brain"
23
+ LOG_DIR = NEXO_HOME / "logs"
24
+ SUMMARY_FILE = LOG_DIR / "watchdog-smoke-summary.json"
25
+ HASH_REGISTRY = NEXO_HOME / "scripts" / ".watchdog-hashes"
26
+ RESTORE_LOG = LOG_DIR / "snapshot-restores.log"
27
+
28
+
29
+ def _read_restore_count_for_current_hour() -> int:
30
+ if not RESTORE_LOG.exists():
31
+ return 0
32
+ needle = datetime.now().strftime("%Y-%m-%d %H")
33
+ return sum(1 for line in RESTORE_LOG.read_text(errors="ignore").splitlines()
34
+ if needle in line and "/.codex/memories/nexo-" not in line)
35
+
36
+
37
+ def _sha256(path: Path) -> str:
38
+ return hashlib.sha256(path.read_bytes()).hexdigest()
39
+
40
+
41
+ def main() -> int:
42
+ LOG_DIR.mkdir(parents=True, exist_ok=True)
43
+ findings = []
44
+
45
+ db_path = NEXO_HOME / "data" / "nexo.db"
46
+ integrity = "missing"
47
+ if db_path.exists():
48
+ try:
49
+ conn = sqlite3.connect(str(db_path), timeout=10)
50
+ integrity = conn.execute("PRAGMA integrity_check").fetchone()[0]
51
+ conn.close()
52
+ except Exception as exc:
53
+ integrity = f"error:{exc}"
54
+ if integrity != "ok":
55
+ findings.append({"severity": "ERROR", "area": "sqlite", "msg": f"integrity={integrity}"})
56
+
57
+ # Check if the NEXO MCP server process is alive (replaces legacy cortex process check)
58
+ nexo_server_running = subprocess.run(
59
+ ["pgrep", "-f", "nexo-brain"],
60
+ capture_output=True,
61
+ text=True,
62
+ ).returncode == 0
63
+ if not nexo_server_running:
64
+ findings.append({"severity": "INFO", "area": "server", "msg": "nexo-brain not running (normal if no active session)"})
65
+
66
+ backups = sorted((NEXO_HOME / "backups").glob("nexo-*.db"), key=lambda p: p.stat().st_mtime, reverse=True)
67
+ if backups:
68
+ age_seconds = int(datetime.now().timestamp() - backups[0].stat().st_mtime)
69
+ if age_seconds > 7200:
70
+ findings.append({"severity": "WARN", "area": "backup", "msg": f"latest backup age={age_seconds}s"})
71
+ else:
72
+ findings.append({"severity": "WARN", "area": "backup", "msg": "no backups found"})
73
+
74
+ if HASH_REGISTRY.exists():
75
+ for line in HASH_REGISTRY.read_text().splitlines():
76
+ if not line.strip():
77
+ continue
78
+ filepath, expected_hash = line.split("|", 1)
79
+ path = Path(filepath)
80
+ if path.exists() and _sha256(path) != expected_hash:
81
+ findings.append({"severity": "ERROR", "area": "immutable", "msg": f"hash mismatch: {filepath}"})
82
+
83
+ restore_count = _read_restore_count_for_current_hour()
84
+ if restore_count > 2:
85
+ findings.append({"severity": "ERROR", "area": "restore_loop", "msg": f"{restore_count} restores this hour"})
86
+ elif restore_count > 0:
87
+ findings.append({"severity": "INFO", "area": "restore_activity", "msg": f"{restore_count} restores this hour"})
88
+
89
+ # Check brain/ (canonical) first, fall back to cortex/ (legacy)
90
+ objective = BRAIN_DIR / "evolution-objective.json"
91
+ if not objective.exists():
92
+ objective = NEXO_HOME / "cortex" / "evolution-objective.json"
93
+ evolution_enabled = None
94
+ if objective.exists():
95
+ obj = json.loads(objective.read_text())
96
+ evolution_enabled = obj.get("evolution_enabled", True)
97
+ if not evolution_enabled:
98
+ findings.append({
99
+ "severity": "WARN",
100
+ "area": "evolution",
101
+ "msg": f"disabled: {obj.get('disabled_reason', 'unknown')}",
102
+ })
103
+
104
+ summary = {
105
+ "timestamp": datetime.now().isoformat(),
106
+ "ok": not any(f["severity"] == "ERROR" for f in findings),
107
+ "integrity": integrity,
108
+ "server_running": nexo_server_running,
109
+ "evolution_enabled": evolution_enabled,
110
+ "restore_count_current_hour": restore_count,
111
+ "findings": findings,
112
+ }
113
+ SUMMARY_FILE.write_text(json.dumps(summary, indent=2, ensure_ascii=False))
114
+ print(json.dumps(summary, ensure_ascii=False))
115
+ return 1 if any(f["severity"] == "ERROR" for f in findings) else 0
116
+
117
+
118
+ if __name__ == "__main__":
119
+ raise SystemExit(main())