nexo-brain 1.5.4 → 1.7.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.
- package/README.md +99 -77
- package/bin/nexo-brain.js +82 -3
- package/bin/postinstall.js +46 -0
- package/package.json +11 -2
- package/scripts/migrate-v1.5-to-v1.6.py +778 -0
- package/src/__pycache__/auto_close_sessions.cpython-314.pyc +0 -0
- package/src/__pycache__/claim_graph.cpython-314.pyc +0 -0
- package/src/__pycache__/evolution_cycle.cpython-314.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-314.pyc +0 -0
- package/src/__pycache__/kg_populate.cpython-314.pyc +0 -0
- package/src/__pycache__/knowledge_graph.cpython-314.pyc +0 -0
- package/src/__pycache__/maintenance.cpython-314.pyc +0 -0
- package/src/__pycache__/migrate_embeddings.cpython-314.pyc +0 -0
- package/src/__pycache__/plugin_loader.cpython-314.pyc +0 -0
- package/src/__pycache__/server.cpython-314.pyc +0 -0
- package/src/__pycache__/storage_router.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_coordination.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_credentials.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_learnings.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_menu.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_reminders.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_reminders_crud.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_sessions.cpython-314.pyc +0 -0
- package/src/__pycache__/tools_task_history.cpython-314.pyc +0 -0
- package/src/auto_close_sessions.py +4 -2
- package/src/cognitive/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-314.pyc +0 -0
- package/src/cognitive/_core.py +1 -1
- package/src/cognitive/_memory.py +7 -3
- package/src/cognitive/_search.py +11 -10
- package/src/cognitive/_trust.py +2 -2
- package/src/dashboard/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/dashboard/__pycache__/app.cpython-314.pyc +0 -0
- package/src/dashboard/app.py +497 -5
- package/src/dashboard/static/favicon.svg +32 -0
- package/src/dashboard/static/nexo-logo.png +0 -0
- package/src/dashboard/static/nexo-logo.svg +40 -0
- package/src/dashboard/static/style.css +2458 -0
- package/src/dashboard/templates/adaptive.html +214 -65
- package/src/dashboard/templates/calendar.html +720 -0
- package/src/dashboard/templates/dashboard.html +621 -0
- package/src/dashboard/templates/graph.html +176 -95
- package/src/dashboard/templates/inbox.html +367 -0
- package/src/dashboard/templates/memory.html +185 -48
- package/src/dashboard/templates/operations.html +725 -0
- package/src/dashboard/templates/sessions.html +163 -41
- package/src/dashboard/templates/somatic.html +168 -48
- package/src/db/__init__.py +2 -1
- package/src/db/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-314.pyc +0 -0
- package/src/db/_core.py +2 -2
- package/src/db/_episodic.py +71 -1
- package/src/db/_fts.py +12 -12
- package/src/db/_reminders.py +53 -14
- package/src/db/_schema.py +10 -0
- package/src/hooks/__pycache__/auto_capture.cpython-314.pyc +0 -0
- package/src/hooks/capture-tool-logs.sh +50 -0
- package/src/hooks/daily-briefing-check.sh +33 -0
- package/src/hooks/inbox-hook.sh +74 -0
- package/src/hooks/session-start.sh +97 -5
- package/src/hooks/session-stop.sh +17 -31
- package/src/plugins/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/agents.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/artifact_registry.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/backup.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/cognitive_memory.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/core_rules.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/cortex.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/entities.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/episodic_memory.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/evolution.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/guard.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/knowledge_graph_tools.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/preferences.cpython-314.pyc +0 -0
- package/src/plugins/agents.py +8 -8
- package/src/plugins/backup.py +2 -2
- package/src/plugins/cognitive_memory.py +1 -1
- package/src/plugins/episodic_memory.py +73 -55
- package/src/plugins/evolution.py +2 -1
- package/src/plugins/guard.py +25 -6
- package/src/rules/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/rules/__pycache__/migrate.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/check-context.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-auto-update.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-catchup.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-cognitive-decay.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-daily-self-audit.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-evolution-run.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-followup-hygiene.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-github-monitor.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-immune.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-install.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-learning-housekeep.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-learning-validator.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-migrate.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-postmortem-consolidator.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-pre-commit.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-proactive-dashboard.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-reflection.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-runtime-preflight.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-send-email.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-send-reply.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-sleep.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-synthesis.cpython-314.pyc +0 -0
- package/src/scripts/__pycache__/nexo-watchdog-smoke.cpython-314.pyc +0 -0
- package/src/scripts/check-context.py +4 -2
- package/src/scripts/deep-sleep/__pycache__/analyze_session.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/__pycache__/apply_findings.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/__pycache__/collect_transcripts.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/analyze_session.py +3 -1
- package/src/scripts/deep-sleep/apply_findings.py +7 -4
- package/src/scripts/deep-sleep/collect_transcripts.py +3 -1
- package/src/scripts/deep-sleep/prompt.md +13 -13
- package/src/scripts/nexo-auto-update.py +0 -0
- package/src/scripts/nexo-backup.sh +33 -0
- package/src/scripts/nexo-catchup.py +4 -4
- package/src/scripts/nexo-cognitive-decay.py +8 -5
- package/src/scripts/nexo-daily-self-audit.py +19 -16
- package/src/scripts/nexo-deep-sleep.sh +4 -3
- package/src/scripts/nexo-evolution-run.py +12 -9
- package/src/scripts/nexo-followup-hygiene.py +7 -4
- package/src/scripts/nexo-github-monitor.py +252 -0
- package/src/scripts/nexo-immune.py +67 -29
- package/src/scripts/nexo-inbox-hook.sh +1 -1
- package/src/scripts/nexo-install.py +227 -0
- package/src/scripts/nexo-learning-housekeep.py +241 -0
- package/src/scripts/nexo-learning-validator.py +2 -0
- package/src/scripts/nexo-migrate.py +226 -0
- package/src/scripts/nexo-postmortem-consolidator.py +49 -46
- package/src/scripts/nexo-pre-commit.py +1 -1
- package/src/scripts/nexo-proactive-dashboard.py +23 -21
- package/src/scripts/nexo-reflection.py +0 -0
- package/src/scripts/nexo-runtime-preflight.py +1 -1
- package/src/scripts/nexo-send-email.py +1 -1
- package/src/scripts/nexo-send-reply.py +1 -1
- package/src/scripts/nexo-sleep.py +2 -0
- package/src/scripts/nexo-synthesis.py +3 -3
- package/src/scripts/nexo-watchdog.sh +275 -131
- package/src/server.py +34 -20
- package/src/tools_coordination.py +15 -15
- package/src/tools_credentials.py +13 -13
- package/src/tools_learnings.py +36 -27
- package/src/tools_menu.py +51 -50
- package/src/tools_reminders.py +12 -6
- package/src/tools_reminders_crud.py +19 -19
- package/src/tools_sessions.py +56 -186
- package/src/tools_task_history.py +10 -10
- package/templates/CLAUDE.md.template +92 -446
- package/templates/launchagents/README.md +133 -0
- package/templates/launchagents/com.nexo.auto-close-sessions.plist +35 -0
- package/templates/launchagents/com.nexo.catchup.plist +34 -0
- package/templates/launchagents/com.nexo.cognitive-decay.plist +33 -0
- package/templates/launchagents/com.nexo.dashboard.plist +39 -0
- package/templates/launchagents/com.nexo.deep-sleep.plist +39 -0
- package/templates/launchagents/com.nexo.evolution.plist +41 -0
- package/templates/launchagents/com.nexo.followup-hygiene.plist +41 -0
- package/templates/launchagents/com.nexo.github-monitor.plist +43 -0
- package/templates/launchagents/com.nexo.immune.plist +37 -0
- package/templates/launchagents/com.nexo.postmortem.plist +41 -0
- package/templates/launchagents/com.nexo.self-audit.plist +43 -0
- package/templates/launchagents/com.nexo.synthesis.plist +41 -0
- package/templates/launchagents/com.nexo.watchdog.plist +33 -0
- package/tests/test_migrations.py +3 -3
- package/src/dashboard/templates/overview.html +0 -75
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -21,8 +21,9 @@ from db import (
|
|
|
21
21
|
SESSION_STALE_SECONDS,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
NEXO_HOME = os.environ.get("NEXO_HOME", os.path.expanduser("~/.nexo"))
|
|
25
|
+
LOG_DIR = os.path.join(NEXO_HOME, "operations", "tool-logs")
|
|
26
|
+
AUTO_CLOSE_LOG = os.path.join(NEXO_HOME, "coordination", "auto-close.log")
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def get_tool_log_summary(sid: str) -> str:
|
|
@@ -120,6 +121,7 @@ def main():
|
|
|
120
121
|
|
|
121
122
|
orphans = get_orphan_sessions(SESSION_STALE_SECONDS)
|
|
122
123
|
if not orphans:
|
|
124
|
+
print(f"[{datetime.datetime.now().isoformat(timespec='seconds')}] No stale sessions")
|
|
123
125
|
return
|
|
124
126
|
|
|
125
127
|
for session in orphans:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/cognitive/_core.py
CHANGED
|
@@ -11,7 +11,7 @@ from datetime import datetime, timedelta
|
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from typing import Optional
|
|
13
13
|
|
|
14
|
-
COGNITIVE_DB = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cognitive.db")
|
|
14
|
+
COGNITIVE_DB = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "cognitive.db")
|
|
15
15
|
EMBEDDING_DIM = 768
|
|
16
16
|
LAMBDA_STM = 0.1 # half-life ~7 days
|
|
17
17
|
LAMBDA_LTM = 0.012 # half-life ~60 days
|
package/src/cognitive/_memory.py
CHANGED
|
@@ -398,18 +398,20 @@ def get_stats() -> dict:
|
|
|
398
398
|
"""Return statistics about the cognitive memory system."""
|
|
399
399
|
db = _get_db()
|
|
400
400
|
|
|
401
|
-
stm_active = db.execute("SELECT COUNT(*) FROM stm_memories WHERE promoted_to_ltm = 0").fetchone()[0]
|
|
401
|
+
stm_active = db.execute("SELECT COUNT(*) FROM stm_memories WHERE lifecycle_state = 'active' AND promoted_to_ltm = 0").fetchone()[0]
|
|
402
|
+
stm_promoted = db.execute("SELECT COUNT(*) FROM stm_memories WHERE promoted_to_ltm = 1").fetchone()[0]
|
|
403
|
+
stm_total = db.execute("SELECT COUNT(*) FROM stm_memories WHERE lifecycle_state = 'active'").fetchone()[0]
|
|
402
404
|
ltm_active = db.execute("SELECT COUNT(*) FROM ltm_memories WHERE is_dormant = 0").fetchone()[0]
|
|
403
405
|
ltm_dormant = db.execute("SELECT COUNT(*) FROM ltm_memories WHERE is_dormant = 1").fetchone()[0]
|
|
404
406
|
|
|
405
|
-
avg_stm = db.execute("SELECT AVG(strength) FROM stm_memories WHERE promoted_to_ltm = 0").fetchone()[0] or 0.0
|
|
407
|
+
avg_stm = db.execute("SELECT AVG(strength) FROM stm_memories WHERE lifecycle_state = 'active' AND promoted_to_ltm = 0").fetchone()[0] or 0.0
|
|
406
408
|
avg_ltm = db.execute("SELECT AVG(strength) FROM ltm_memories WHERE is_dormant = 0").fetchone()[0] or 0.0
|
|
407
409
|
|
|
408
410
|
total_retrievals = db.execute("SELECT COUNT(*) FROM retrieval_log").fetchone()[0]
|
|
409
411
|
avg_retrieval_score = db.execute("SELECT AVG(top_score) FROM retrieval_log").fetchone()[0] or 0.0
|
|
410
412
|
|
|
411
413
|
top_domains_stm = db.execute(
|
|
412
|
-
"SELECT domain, COUNT(*) as cnt FROM stm_memories WHERE promoted_to_ltm = 0 AND domain != '' GROUP BY domain ORDER BY cnt DESC LIMIT 5"
|
|
414
|
+
"SELECT domain, COUNT(*) as cnt FROM stm_memories WHERE lifecycle_state = 'active' AND promoted_to_ltm = 0 AND domain != '' GROUP BY domain ORDER BY cnt DESC LIMIT 5"
|
|
413
415
|
).fetchall()
|
|
414
416
|
top_domains_ltm = db.execute(
|
|
415
417
|
"SELECT domain, COUNT(*) as cnt FROM ltm_memories WHERE is_dormant = 0 AND domain != '' GROUP BY domain ORDER BY cnt DESC LIMIT 5"
|
|
@@ -420,6 +422,8 @@ def get_stats() -> dict:
|
|
|
420
422
|
|
|
421
423
|
return {
|
|
422
424
|
"stm_active": stm_active,
|
|
425
|
+
"stm_promoted": stm_promoted,
|
|
426
|
+
"stm_total": stm_total,
|
|
423
427
|
"ltm_active": ltm_active,
|
|
424
428
|
"ltm_dormant": ltm_dormant,
|
|
425
429
|
"avg_stm_strength": round(avg_stm, 3),
|
package/src/cognitive/_search.py
CHANGED
|
@@ -112,11 +112,12 @@ def _rrf_fuse(vector_results: list[dict], bm25_results: list[dict],
|
|
|
112
112
|
|
|
113
113
|
# If we have the original cosine score, blend it in to preserve semantic confidence
|
|
114
114
|
if vec_result and "score" in vec_result:
|
|
115
|
-
# Weighted blend:
|
|
116
|
-
|
|
115
|
+
# Weighted blend: cosine for confidence + RRF for ranking boost
|
|
116
|
+
rrf_normalized = min(1.0, rrf_score * k) # normalize to 0-1 range
|
|
117
|
+
result["score"] = 0.7 * vec_result["score"] + 0.3 * rrf_normalized
|
|
117
118
|
else:
|
|
118
|
-
# BM25-only result: use RRF score scaled to ~0.
|
|
119
|
-
result["score"] = min(0.
|
|
119
|
+
# BM25-only result: use RRF score scaled to ~0.3-0.7 range
|
|
120
|
+
result["score"] = min(0.75, rrf_score * k)
|
|
120
121
|
|
|
121
122
|
result["bm25_boosted"] = key in bm25_lookup
|
|
122
123
|
result["bm25_only"] = key not in vec_lookup
|
|
@@ -199,8 +200,8 @@ def _apply_temporal_boost(results: list[dict], query_text: str) -> list[dict]:
|
|
|
199
200
|
# Bounded exponential decay boost
|
|
200
201
|
boost = alpha * math.exp(-ln2 * age_days / half_life_days)
|
|
201
202
|
|
|
202
|
-
# Apply boost (capped at 1.0)
|
|
203
|
-
r["score"] = min(
|
|
203
|
+
# Apply boost (capped at 0.95 — reserve 1.0 for exact matches only)
|
|
204
|
+
r["score"] = min(0.95, r["score"] + boost)
|
|
204
205
|
if boost > 0.001:
|
|
205
206
|
r["temporal_boost"] = round(boost, 4)
|
|
206
207
|
|
|
@@ -282,7 +283,7 @@ def _kg_boost_results(results: list[dict], max_boost: float = 0.08) -> list[dict
|
|
|
282
283
|
for idx in ref_map.get(node_ref, []):
|
|
283
284
|
r = results[idx]
|
|
284
285
|
if r.get("score", 0) >= 0.45: # Same relevance gate as temporal
|
|
285
|
-
r["score"] = min(
|
|
286
|
+
r["score"] = min(0.95, r["score"] + boost)
|
|
286
287
|
r["kg_boost"] = round(boost, 4)
|
|
287
288
|
r["kg_connections"] = connections
|
|
288
289
|
|
|
@@ -613,7 +614,7 @@ def _rehearse_results(results: list[dict], skip_ids: set = None):
|
|
|
613
614
|
continue
|
|
614
615
|
table = "stm_memories" if r["store"] == "stm" else "ltm_memories"
|
|
615
616
|
db.execute(
|
|
616
|
-
f"UPDATE {table} SET strength = 1.0, access_count = access_count + 1, last_accessed = ? WHERE id = ?",
|
|
617
|
+
f"UPDATE {table} SET strength = MIN(1.0, strength + 0.08), access_count = access_count + 1, last_accessed = ? WHERE id = ?",
|
|
617
618
|
(now, r["id"])
|
|
618
619
|
)
|
|
619
620
|
db.commit()
|
|
@@ -834,7 +835,7 @@ def search(
|
|
|
834
835
|
if is_temporal_query:
|
|
835
836
|
for r in results:
|
|
836
837
|
if r.get("temporal_date"):
|
|
837
|
-
r["score"] = min(
|
|
838
|
+
r["score"] = min(0.95, r["score"] + 0.05)
|
|
838
839
|
|
|
839
840
|
# Recency temporal boost: recent memories get additive bonus (query-adaptive)
|
|
840
841
|
results = _apply_temporal_boost(results, query_text)
|
|
@@ -866,7 +867,7 @@ def search(
|
|
|
866
867
|
existing_hashes.add(co_hash)
|
|
867
868
|
if co_hash in neighbor_boosts:
|
|
868
869
|
boost = neighbor_boosts[co_hash]
|
|
869
|
-
r["score"] = min(
|
|
870
|
+
r["score"] = min(0.95, r["score"] + boost)
|
|
870
871
|
r["co_activation_boost"] = boost
|
|
871
872
|
|
|
872
873
|
# Add neighbor memories not already in results
|
package/src/cognitive/_trust.py
CHANGED
|
@@ -316,7 +316,7 @@ def detect_sentiment(text: str) -> dict:
|
|
|
316
316
|
if intensity > 0.7:
|
|
317
317
|
guidance = "MODE: Ultra-conciso. Cero explicaciones. Resolver y mostrar resultado."
|
|
318
318
|
else:
|
|
319
|
-
guidance = "MODE:
|
|
319
|
+
guidance = "MODE: Concise. Less context, more direct action."
|
|
320
320
|
elif pos_score > neg_score and pos_score >= 1:
|
|
321
321
|
sentiment = "positive"
|
|
322
322
|
intensity = min(1.0, 0.3 + pos_score * 0.15)
|
|
@@ -324,7 +324,7 @@ def detect_sentiment(text: str) -> dict:
|
|
|
324
324
|
elif urgency_hits:
|
|
325
325
|
sentiment = "urgent"
|
|
326
326
|
intensity = 0.8
|
|
327
|
-
guidance = "MODE:
|
|
327
|
+
guidance = "MODE: Immediate action. No preambles."
|
|
328
328
|
else:
|
|
329
329
|
sentiment = "neutral"
|
|
330
330
|
intensity = 0.5
|
|
Binary file
|
|
Binary file
|