nexo-brain 2.3.1 → 2.3.2
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/bin/nexo-brain.js +92 -9
- package/bin/postinstall.js +22 -15
- package/package.json +2 -2
- package/src/auto_update.py +193 -5
- package/src/crons/sync.py +5 -0
- package/src/db/_schema.py +11 -1
- package/src/hooks/capture-tool-logs.sh +23 -6
- package/src/hooks/session-start.sh +4 -3
- package/src/plugins/update.py +376 -26
- package/src/scripts/nexo-catchup.py +29 -4
- package/src/scripts/nexo-daily-self-audit.py +21 -1
- package/src/scripts/nexo-evolution-run.py +21 -1
- package/src/scripts/nexo-postmortem-consolidator.py +34 -9
- package/src/scripts/nexo-sleep.py +32 -10
- package/src/scripts/nexo-synthesis.py +29 -9
- package/src/scripts/nexo-update.sh +109 -7
- package/src/scripts/nexo-watchdog.sh +103 -47
- package/src/server.py +65 -1
package/src/server.py
CHANGED
|
@@ -55,7 +55,71 @@ def _server_init():
|
|
|
55
55
|
with open(_pid_file, "w") as f:
|
|
56
56
|
f.write(str(os.getpid()))
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
# ── Database initialization with recovery ─────────────────────
|
|
59
|
+
import sqlite3
|
|
60
|
+
try:
|
|
61
|
+
init_db()
|
|
62
|
+
except sqlite3.DatabaseError as exc:
|
|
63
|
+
# Corruption or unreadable DB — attempt restore from backup
|
|
64
|
+
print(f"[NEXO] DB init failed: {exc}", file=sys.stderr)
|
|
65
|
+
_recovered = False
|
|
66
|
+
try:
|
|
67
|
+
from db._core import DB_PATH as _db_path
|
|
68
|
+
import glob as _glob
|
|
69
|
+
_backup_dir = os.path.join(
|
|
70
|
+
os.environ.get("NEXO_HOME", os.path.join(os.path.expanduser("~"), ".nexo")),
|
|
71
|
+
"backups",
|
|
72
|
+
)
|
|
73
|
+
_backups = sorted(_glob.glob(os.path.join(_backup_dir, "nexo-*.db")), reverse=True)
|
|
74
|
+
for _bk in _backups:
|
|
75
|
+
try:
|
|
76
|
+
_test = sqlite3.connect(_bk)
|
|
77
|
+
_result = _test.execute("PRAGMA integrity_check").fetchone()
|
|
78
|
+
_test.close()
|
|
79
|
+
if _result and _result[0] == "ok":
|
|
80
|
+
# Valid backup found — replace corrupt DB
|
|
81
|
+
import shutil
|
|
82
|
+
# Close any open connection before replacing
|
|
83
|
+
try:
|
|
84
|
+
close_db()
|
|
85
|
+
except Exception:
|
|
86
|
+
pass
|
|
87
|
+
shutil.copy2(_bk, _db_path)
|
|
88
|
+
print(f"[NEXO] Restored DB from backup: {os.path.basename(_bk)}", file=sys.stderr)
|
|
89
|
+
init_db()
|
|
90
|
+
_recovered = True
|
|
91
|
+
break
|
|
92
|
+
except Exception:
|
|
93
|
+
continue
|
|
94
|
+
except Exception as restore_exc:
|
|
95
|
+
print(f"[NEXO] Backup restore failed: {restore_exc}", file=sys.stderr)
|
|
96
|
+
|
|
97
|
+
if not _recovered:
|
|
98
|
+
# No valid backup — nuke corrupt file and start fresh
|
|
99
|
+
try:
|
|
100
|
+
close_db()
|
|
101
|
+
except Exception:
|
|
102
|
+
pass
|
|
103
|
+
try:
|
|
104
|
+
from db._core import DB_PATH as _db_path
|
|
105
|
+
if os.path.exists(_db_path):
|
|
106
|
+
_corrupt_path = _db_path + ".corrupt"
|
|
107
|
+
os.rename(_db_path, _corrupt_path)
|
|
108
|
+
print(f"[NEXO] Corrupt DB moved to {os.path.basename(_corrupt_path)}", file=sys.stderr)
|
|
109
|
+
# Remove WAL/SHM files too
|
|
110
|
+
for _ext in (".db-wal", ".db-shm"):
|
|
111
|
+
_wal = _db_path.replace(".db", _ext)
|
|
112
|
+
if os.path.exists(_wal):
|
|
113
|
+
os.remove(_wal)
|
|
114
|
+
except Exception:
|
|
115
|
+
pass
|
|
116
|
+
try:
|
|
117
|
+
init_db()
|
|
118
|
+
print("[NEXO] Fresh database created.", file=sys.stderr)
|
|
119
|
+
except Exception as fresh_exc:
|
|
120
|
+
print(f"[NEXO] FATAL: Cannot initialize database: {fresh_exc}", file=sys.stderr)
|
|
121
|
+
print("[NEXO] Check permissions on NEXO_HOME/data/ and disk space.", file=sys.stderr)
|
|
122
|
+
sys.exit(1)
|
|
59
123
|
|
|
60
124
|
# ── Auto-update check (non-blocking, max 5s) ──────────────────
|
|
61
125
|
try:
|