nexo-brain 1.7.0 → 2.1.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 +160 -60
- package/bin/nexo-brain.js +680 -381
- package/package.json +18 -3
- package/scripts/migrate-to-unified.sh +813 -0
- package/scripts/migrate-v1.7-to-v1.8.py +214 -0
- package/scripts/pre-commit-check.sh +1 -1
- package/src/__pycache__/auto_update.cpython-310.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-310.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-314.pyc +0 -0
- package/src/__pycache__/kg_populate.cpython-310.pyc +0 -0
- package/src/__pycache__/knowledge_graph.cpython-310.pyc +0 -0
- package/src/__pycache__/plugin_loader.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_coordination.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_credentials.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_learnings.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_menu.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_reminders.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_reminders_crud.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_sessions.cpython-310.pyc +0 -0
- package/src/__pycache__/tools_task_history.cpython-310.pyc +0 -0
- package/src/auto_close_sessions.py +1 -1
- package/src/auto_update.py +634 -0
- package/src/cognitive/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_core.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_decay.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_ingest.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_memory.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_search.cpython-314.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-310.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-312.pyc +0 -0
- package/src/cognitive/__pycache__/_trust.cpython-314.pyc +0 -0
- package/src/cognitive/_core.py +7 -3
- package/src/cognitive/_decay.py +1 -1
- package/src/cognitive/_search.py +1 -0
- package/src/cognitive/_trust.py +3 -3
- package/src/crons/manifest.json +106 -0
- package/src/crons/sync.py +217 -0
- package/src/dashboard/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/dashboard/__pycache__/app.cpython-310.pyc +0 -0
- package/src/dashboard/app.py +24 -4
- package/src/dashboard/templates/dashboard.html +3 -2
- package/src/db/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/db/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/db/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_core.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_credentials.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_entities.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_episodic.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_evolution.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_fts.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_learnings.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_reminders.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_schema.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_sessions.cpython-314.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_tasks.cpython-314.pyc +0 -0
- package/src/db/_core.py +5 -1
- package/src/db/_episodic.py +2 -4
- package/src/db/_reminders.py +45 -6
- package/src/db/_schema.py +31 -0
- package/src/evolution_cycle.py +33 -11
- package/src/hooks/auto_capture.py +1 -1
- package/src/hooks/capture-tool-logs.sh +76 -0
- package/src/hooks/inbox-hook.sh +2 -1
- package/src/hooks/post-compact.sh +2 -1
- package/src/hooks/pre-compact.sh +104 -2
- package/src/hooks/session-start.sh +6 -2
- package/src/hooks/session-stop.sh +4 -2
- package/src/kg_populate.py +4 -1
- package/src/migrate_embeddings.py +4 -1
- package/src/plugin_loader.py +100 -34
- package/src/plugins/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/agents.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/artifact_registry.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/backup.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cognitive_memory.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/core_rules.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cortex.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/entities.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/episodic_memory.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/evolution.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/guard.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/knowledge_graph_tools.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/preferences.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/update.cpython-310.pyc +0 -0
- package/src/plugins/agents.py +2 -2
- package/src/plugins/backup.py +5 -4
- package/src/plugins/core_rules.py +37 -16
- package/src/plugins/episodic_memory.py +14 -5
- package/src/plugins/evolution.py +6 -2
- package/src/plugins/guard.py +20 -11
- package/src/plugins/update.py +256 -0
- package/src/requirements.txt +12 -0
- package/src/scripts/check-context.py +8 -3
- package/src/scripts/deep-sleep/__pycache__/extract.cpython-314.pyc +0 -0
- package/src/scripts/deep-sleep/apply_findings.py +514 -169
- package/src/scripts/deep-sleep/collect.py +480 -0
- package/src/scripts/deep-sleep/extract-prompt.md +233 -0
- package/src/scripts/deep-sleep/extract.py +249 -0
- package/src/scripts/deep-sleep/synthesize-prompt.md +168 -0
- package/src/scripts/deep-sleep/synthesize.py +191 -0
- package/src/scripts/nexo-auto-update.py +4 -211
- package/src/scripts/nexo-backup.sh +5 -13
- package/src/scripts/nexo-brain-activation.sh +26 -26
- package/src/scripts/nexo-catchup.py +36 -25
- package/src/scripts/nexo-cognitive-decay.py +7 -3
- package/src/scripts/nexo-daily-self-audit.py +44 -15
- package/src/scripts/nexo-deep-sleep.sh +31 -16
- package/src/scripts/nexo-evolution-run.py +21 -11
- package/src/scripts/nexo-followup-hygiene.py +6 -4
- package/src/scripts/nexo-github-monitor.py +12 -8
- package/src/scripts/nexo-immune.py +6 -4
- package/src/scripts/nexo-inbox-hook.sh +2 -1
- package/src/scripts/nexo-install.py +4 -225
- package/src/scripts/nexo-learning-housekeep.py +7 -3
- package/src/scripts/nexo-learning-validator.py +1 -22
- package/src/scripts/nexo-migrate.py +9 -3
- package/src/scripts/nexo-postmortem-consolidator.py +17 -10
- package/src/scripts/nexo-pre-commit.py +3 -1
- package/src/scripts/nexo-prevent-sleep.sh +29 -0
- package/src/scripts/nexo-proactive-dashboard.py +5 -4
- package/src/scripts/nexo-runtime-preflight.py +59 -55
- package/src/scripts/nexo-send-email.py +1 -1
- package/src/scripts/nexo-send-reply.py +3 -1
- package/src/scripts/nexo-sleep.py +13 -9
- package/src/scripts/nexo-snapshot-restore.sh +2 -1
- package/src/scripts/nexo-synthesis.py +11 -7
- package/src/scripts/nexo-tcc-approve.sh +79 -0
- package/src/scripts/nexo-update.sh +161 -0
- package/src/scripts/nexo-watchdog-smoke.py +18 -13
- package/src/scripts/nexo-watchdog.sh +22 -13
- package/src/server.py +77 -28
- package/src/storage_router.py +6 -2
- package/src/tools_learnings.py +6 -6
- package/src/tools_menu.py +1 -1
- package/src/tools_reminders_crud.py +10 -8
- package/src/tools_sessions.py +76 -4
- package/templates/CLAUDE.md.template +14 -80
- package/templates/launchagents/README.md +7 -7
- package/templates/launchagents/com.nexo.auto-close-sessions.plist +5 -1
- package/templates/launchagents/com.nexo.catchup.plist +4 -0
- package/templates/launchagents/com.nexo.cognitive-decay.plist +7 -0
- package/templates/launchagents/com.nexo.dashboard.plist +5 -1
- package/templates/launchagents/com.nexo.deep-sleep.plist +4 -0
- package/templates/launchagents/com.nexo.evolution.plist +4 -0
- package/templates/launchagents/com.nexo.followup-hygiene.plist +4 -0
- package/templates/launchagents/com.nexo.github-monitor.plist +3 -1
- package/templates/launchagents/com.nexo.immune.plist +4 -0
- package/templates/launchagents/com.nexo.postmortem.plist +4 -0
- package/templates/launchagents/com.nexo.self-audit.plist +4 -0
- package/templates/launchagents/com.nexo.synthesis.plist +4 -0
- package/templates/launchagents/com.nexo.watchdog.plist +4 -0
- package/templates/openclaw.json +1 -1
- package/tests/conftest.py +2 -2
- package/tests/test_cognitive.py +7 -6
- package/tests/test_migrations.py +26 -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__/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/dashboard/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/dashboard/__pycache__/app.cpython-314.pyc +0 -0
- package/src/hooks/__pycache__/auto_capture.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/__init__.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/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/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 +0 -217
- package/src/scripts/deep-sleep/collect_transcripts.py +0 -145
- package/src/scripts/deep-sleep/prompt.md +0 -109
- package/tests/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
- package/tests/__pycache__/test_cognitive.cpython-314-pytest-9.0.2.pyc +0 -0
- package/tests/__pycache__/test_knowledge_graph.cpython-314-pytest-9.0.2.pyc +0 -0
- package/tests/__pycache__/test_migrations.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
35
35
|
<key>HOME</key>
|
|
36
36
|
<string>{{HOME}}</string>
|
|
37
|
+
<key>NEXO_HOME</key>
|
|
38
|
+
<string>{{NEXO_HOME}}</string>
|
|
39
|
+
<key>NEXO_CODE</key>
|
|
40
|
+
<string>{{NEXO_CODE}}</string>
|
|
37
41
|
</dict>
|
|
38
42
|
</dict>
|
|
39
43
|
</plist>
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
<string>{{HOME}}</string>
|
|
37
37
|
<key>PATH</key>
|
|
38
38
|
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
39
|
+
<key>NEXO_HOME</key>
|
|
40
|
+
<string>{{NEXO_HOME}}</string>
|
|
41
|
+
<key>NEXO_CODE</key>
|
|
42
|
+
<string>{{NEXO_CODE}}</string>
|
|
39
43
|
</dict>
|
|
40
44
|
</dict>
|
|
41
45
|
</plist>
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
<string>{{HOME}}</string>
|
|
37
37
|
<key>PATH</key>
|
|
38
38
|
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
39
|
+
<key>NEXO_HOME</key>
|
|
40
|
+
<string>{{NEXO_HOME}}</string>
|
|
41
|
+
<key>NEXO_CODE</key>
|
|
42
|
+
<string>{{NEXO_CODE}}</string>
|
|
39
43
|
</dict>
|
|
40
44
|
</dict>
|
|
41
45
|
</plist>
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
<key>HOME</key>
|
|
34
34
|
<string>{{HOME}}</string>
|
|
35
35
|
<key>NEXO_HOME</key>
|
|
36
|
-
<string>{{
|
|
36
|
+
<string>{{NEXO_HOME}}</string>
|
|
37
|
+
<key>NEXO_CODE</key>
|
|
38
|
+
<string>{{NEXO_CODE}}</string>
|
|
37
39
|
<key>PATH</key>
|
|
38
40
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
|
39
41
|
</dict>
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
<string>{{HOME}}</string>
|
|
33
33
|
<key>PATH</key>
|
|
34
34
|
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
35
|
+
<key>NEXO_HOME</key>
|
|
36
|
+
<string>{{NEXO_HOME}}</string>
|
|
37
|
+
<key>NEXO_CODE</key>
|
|
38
|
+
<string>{{NEXO_CODE}}</string>
|
|
35
39
|
</dict>
|
|
36
40
|
</dict>
|
|
37
41
|
</plist>
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
<string>{{HOME}}</string>
|
|
37
37
|
<key>PATH</key>
|
|
38
38
|
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
39
|
+
<key>NEXO_HOME</key>
|
|
40
|
+
<string>{{NEXO_HOME}}</string>
|
|
41
|
+
<key>NEXO_CODE</key>
|
|
42
|
+
<string>{{NEXO_CODE}}</string>
|
|
39
43
|
</dict>
|
|
40
44
|
</dict>
|
|
41
45
|
</plist>
|
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
<string>{{HOME}}</string>
|
|
39
39
|
<key>PATH</key>
|
|
40
40
|
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
41
|
+
<key>NEXO_HOME</key>
|
|
42
|
+
<string>{{NEXO_HOME}}</string>
|
|
43
|
+
<key>NEXO_CODE</key>
|
|
44
|
+
<string>{{NEXO_CODE}}</string>
|
|
41
45
|
</dict>
|
|
42
46
|
</dict>
|
|
43
47
|
</plist>
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
<string>{{HOME}}</string>
|
|
37
37
|
<key>PATH</key>
|
|
38
38
|
<string>/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin</string>
|
|
39
|
+
<key>NEXO_HOME</key>
|
|
40
|
+
<string>{{NEXO_HOME}}</string>
|
|
41
|
+
<key>NEXO_CODE</key>
|
|
42
|
+
<string>{{NEXO_CODE}}</string>
|
|
39
43
|
</dict>
|
|
40
44
|
</dict>
|
|
41
45
|
</plist>
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
<dict>
|
|
29
29
|
<key>PATH</key>
|
|
30
30
|
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
31
|
+
<key>NEXO_HOME</key>
|
|
32
|
+
<string>{{NEXO_HOME}}</string>
|
|
33
|
+
<key>NEXO_CODE</key>
|
|
34
|
+
<string>{{NEXO_CODE}}</string>
|
|
31
35
|
</dict>
|
|
32
36
|
</dict>
|
|
33
37
|
</plist>
|
package/templates/openclaw.json
CHANGED
package/tests/conftest.py
CHANGED
|
@@ -9,8 +9,8 @@ import sqlite3
|
|
|
9
9
|
|
|
10
10
|
import pytest
|
|
11
11
|
|
|
12
|
-
# Add
|
|
13
|
-
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
12
|
+
# Add src/ to path so we can import nexo modules
|
|
13
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@pytest.fixture(autouse=True)
|
package/tests/test_cognitive.py
CHANGED
|
@@ -165,16 +165,17 @@ def test_kg_boost_relevance_gate():
|
|
|
165
165
|
|
|
166
166
|
|
|
167
167
|
def test_decay_formula():
|
|
168
|
-
"""Ebbinghaus decay should reduce strength over time."""
|
|
168
|
+
"""Ebbinghaus decay should reduce strength over time (lambda operates on HOURS)."""
|
|
169
169
|
import cognitive
|
|
170
|
-
# STM decay: lambda=0.
|
|
170
|
+
# STM decay: lambda=0.004126, after 7 days (168h) strength should be ~0.5
|
|
171
171
|
initial = 1.0
|
|
172
|
-
|
|
173
|
-
decayed = initial * math.exp(-cognitive.LAMBDA_STM *
|
|
172
|
+
hours_7d = 7 * 24
|
|
173
|
+
decayed = initial * math.exp(-cognitive.LAMBDA_STM * hours_7d)
|
|
174
174
|
assert 0.45 < decayed < 0.55
|
|
175
175
|
|
|
176
|
-
# LTM decay: lambda=0.
|
|
177
|
-
|
|
176
|
+
# LTM decay: lambda=0.000481, after 60 days (1440h) strength should be ~0.5
|
|
177
|
+
hours_60d = 60 * 24
|
|
178
|
+
decayed_ltm = initial * math.exp(-cognitive.LAMBDA_LTM * hours_60d)
|
|
178
179
|
assert 0.45 < decayed_ltm < 0.55
|
|
179
180
|
|
|
180
181
|
|
package/tests/test_migrations.py
CHANGED
|
@@ -87,6 +87,32 @@ def test_reminder_followup_crud():
|
|
|
87
87
|
assert followup2["status"] == "COMPLETED"
|
|
88
88
|
|
|
89
89
|
|
|
90
|
+
def test_recurring_followup():
|
|
91
|
+
"""Recurring followup: complete archives with date suffix, creates new pending, returns correct IDs."""
|
|
92
|
+
db_mod.create_followup("NF-REC1", "Recurring test", date="2026-03-31", recurrence="weekly:monday")
|
|
93
|
+
followup = db_mod.get_followup("NF-REC1")
|
|
94
|
+
assert followup is not None
|
|
95
|
+
assert followup["recurrence"] == "weekly:monday"
|
|
96
|
+
|
|
97
|
+
result = db_mod.complete_followup("NF-REC1", result="done weekly")
|
|
98
|
+
|
|
99
|
+
# Result should reference the archived ID, not the recycled NF-REC1
|
|
100
|
+
assert result["status"] == "COMPLETED"
|
|
101
|
+
assert result["id"].startswith("NF-REC1-") # archived with date suffix
|
|
102
|
+
assert result["next_id"] == "NF-REC1"
|
|
103
|
+
assert result["next_date"] is not None
|
|
104
|
+
|
|
105
|
+
# The new NF-REC1 should be PENDING (not the completed one)
|
|
106
|
+
new_followup = db_mod.get_followup("NF-REC1")
|
|
107
|
+
assert new_followup is not None
|
|
108
|
+
assert new_followup["status"] == "PENDING"
|
|
109
|
+
|
|
110
|
+
# The archived one should exist with date suffix
|
|
111
|
+
archived = db_mod.get_followup(result["id"])
|
|
112
|
+
assert archived is not None
|
|
113
|
+
assert archived["status"] == "COMPLETED"
|
|
114
|
+
|
|
115
|
+
|
|
90
116
|
def test_credential_crud():
|
|
91
117
|
"""Create, get, and delete credentials."""
|
|
92
118
|
db_mod.create_credential("test-service", "api_key", "secret123", notes="test")
|
|
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
|
|
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
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Deep Sleep — Step 2: Analyze transcripts with Claude CLI (bare mode).
|
|
4
|
-
Sends each session to Claude opus for analysis, then consolidates findings.
|
|
5
|
-
"""
|
|
6
|
-
import json
|
|
7
|
-
import os
|
|
8
|
-
import subprocess
|
|
9
|
-
import sys
|
|
10
|
-
from datetime import datetime
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
|
|
13
|
-
NEXO_HOME = Path(os.environ.get("NEXO_HOME", str(Path.home() / ".nexo")))
|
|
14
|
-
|
|
15
|
-
PROMPT_FILE = Path(__file__).parent / "prompt.md"
|
|
16
|
-
DEEP_SLEEP_DIR = NEXO_HOME / "operations" / "deep-sleep"
|
|
17
|
-
MAX_TRANSCRIPT_CHARS = 150_000
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def build_transcript_text(session: dict) -> str:
|
|
21
|
-
"""Build a readable transcript from a session."""
|
|
22
|
-
lines = [
|
|
23
|
-
f"## Session: {session['session_file']}",
|
|
24
|
-
f"Modified: {session['modified']}",
|
|
25
|
-
f"Messages: {session['message_count']}, Tool uses: {session['tool_use_count']}",
|
|
26
|
-
"",
|
|
27
|
-
"### Conversation"
|
|
28
|
-
]
|
|
29
|
-
for msg in session["messages"]:
|
|
30
|
-
role = "USER" if msg["role"] == "user" else "NEXO"
|
|
31
|
-
lines.append(f"\n**{role}:**")
|
|
32
|
-
lines.append(msg["text"])
|
|
33
|
-
|
|
34
|
-
if session["tool_uses"]:
|
|
35
|
-
lines.append("\n### Tool Usage Log")
|
|
36
|
-
for tu in session["tool_uses"]:
|
|
37
|
-
file_info = f" [{tu['file'][:80]}]" if tu.get("file") else ""
|
|
38
|
-
lines.append(f"- {tu['tool']}{file_info}")
|
|
39
|
-
|
|
40
|
-
return "\n".join(lines)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def find_api_key() -> str | None:
|
|
44
|
-
"""Find Anthropic API key from common locations."""
|
|
45
|
-
# Environment variable
|
|
46
|
-
key = os.environ.get("ANTHROPIC_API_KEY", "")
|
|
47
|
-
if key:
|
|
48
|
-
return key
|
|
49
|
-
|
|
50
|
-
# Common file locations
|
|
51
|
-
for path in [
|
|
52
|
-
Path.home() / ".claude" / "anthropic-api-key.txt",
|
|
53
|
-
Path.home() / ".anthropic" / "api_key",
|
|
54
|
-
Path.home() / ".config" / "anthropic" / "api_key",
|
|
55
|
-
]:
|
|
56
|
-
if path.exists():
|
|
57
|
-
return path.read_text().strip()
|
|
58
|
-
|
|
59
|
-
return None
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def analyze_with_claude(transcript: str, prompt: str) -> dict | None:
|
|
63
|
-
"""Send transcript to Claude CLI for analysis."""
|
|
64
|
-
full_prompt = (
|
|
65
|
-
f"{prompt}\n\n---\n\n# TODAY'S TRANSCRIPT\n\n{transcript}\n\n---\n\n"
|
|
66
|
-
"Analyze this transcript and return the JSON output as specified. "
|
|
67
|
-
"Return ONLY the JSON, no markdown code fences."
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
api_key = find_api_key()
|
|
71
|
-
env = os.environ.copy()
|
|
72
|
-
if api_key:
|
|
73
|
-
env["ANTHROPIC_API_KEY"] = api_key
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
result = subprocess.run(
|
|
77
|
-
["claude", "-p", full_prompt, "--model", "opus", "--output-format", "text", "--bare"],
|
|
78
|
-
capture_output=True, text=True, timeout=300, env=env
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
if result.returncode != 0:
|
|
82
|
-
print(f"Claude CLI error: {result.stderr[:500]}", file=sys.stderr)
|
|
83
|
-
return None
|
|
84
|
-
|
|
85
|
-
response_text = result.stdout.strip()
|
|
86
|
-
|
|
87
|
-
# Strip markdown code fences if present
|
|
88
|
-
if response_text.startswith("```"):
|
|
89
|
-
lines = response_text.split("\n")
|
|
90
|
-
response_text = "\n".join(lines[1:-1] if lines[-1].strip() == "```" else lines[1:])
|
|
91
|
-
response_text = response_text.strip()
|
|
92
|
-
|
|
93
|
-
# Find JSON object in response
|
|
94
|
-
json_start = response_text.find("{")
|
|
95
|
-
json_end = response_text.rfind("}") + 1
|
|
96
|
-
if json_start >= 0 and json_end > json_start:
|
|
97
|
-
response_text = response_text[json_start:json_end]
|
|
98
|
-
|
|
99
|
-
return json.loads(response_text)
|
|
100
|
-
|
|
101
|
-
except subprocess.TimeoutExpired:
|
|
102
|
-
print("Claude CLI timeout (300s)", file=sys.stderr)
|
|
103
|
-
return None
|
|
104
|
-
except json.JSONDecodeError as e:
|
|
105
|
-
print(f"Failed to parse Claude response: {e}", file=sys.stderr)
|
|
106
|
-
return None
|
|
107
|
-
except FileNotFoundError:
|
|
108
|
-
print("Claude CLI not found. Install: npm install -g @anthropic-ai/claude-code", file=sys.stderr)
|
|
109
|
-
return None
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def consolidate_findings(results: list[dict]) -> dict:
|
|
113
|
-
"""Merge findings from multiple sessions into one report."""
|
|
114
|
-
consolidated = {
|
|
115
|
-
"uncaptured_corrections": [],
|
|
116
|
-
"uncaptured_ideas": [],
|
|
117
|
-
"missed_commitments": [],
|
|
118
|
-
"protocol_compliance": {
|
|
119
|
-
"guard_check": {"required": 0, "executed": 0},
|
|
120
|
-
"heartbeat_quality": {"total": 0, "with_good_context": 0},
|
|
121
|
-
"trust_adjustments": {"corrections_detected": 0, "adjusted": 0},
|
|
122
|
-
"learning_capture": {"errors_resolved": 0, "captured": 0},
|
|
123
|
-
"change_log": {"production_edits": 0, "logged": 0},
|
|
124
|
-
"feedback_capture": {"corrections": 0, "captured": 0},
|
|
125
|
-
},
|
|
126
|
-
"protocol_violations": [],
|
|
127
|
-
"quality_issues": [],
|
|
128
|
-
"auto_reinforcements": [],
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
for r in results:
|
|
132
|
-
if not r:
|
|
133
|
-
continue
|
|
134
|
-
for key in ["uncaptured_corrections", "uncaptured_ideas", "missed_commitments",
|
|
135
|
-
"protocol_violations", "quality_issues", "auto_reinforcements"]:
|
|
136
|
-
consolidated[key].extend(r.get(key, []))
|
|
137
|
-
|
|
138
|
-
pc = r.get("protocol_compliance", {})
|
|
139
|
-
for key in consolidated["protocol_compliance"]:
|
|
140
|
-
if key in pc and isinstance(pc[key], dict):
|
|
141
|
-
for subkey in consolidated["protocol_compliance"][key]:
|
|
142
|
-
consolidated["protocol_compliance"][key][subkey] += pc[key].get(subkey, 0)
|
|
143
|
-
|
|
144
|
-
# Calculate rates
|
|
145
|
-
for key, vals in consolidated["protocol_compliance"].items():
|
|
146
|
-
keys = list(vals.keys())
|
|
147
|
-
if len(keys) == 2:
|
|
148
|
-
denominator = vals[keys[0]]
|
|
149
|
-
numerator = vals[keys[1]]
|
|
150
|
-
vals["rate"] = round(numerator / denominator, 2) if denominator > 0 else 1.0
|
|
151
|
-
|
|
152
|
-
rates = [v.get("rate", 1.0) for v in consolidated["protocol_compliance"].values()]
|
|
153
|
-
consolidated["protocol_compliance"]["overall_compliance"] = round(sum(rates) / len(rates), 2) if rates else 1.0
|
|
154
|
-
consolidated["auto_reinforcements"] = list(set(consolidated["auto_reinforcements"]))
|
|
155
|
-
|
|
156
|
-
return consolidated
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def main():
|
|
160
|
-
date = sys.argv[1] if len(sys.argv) > 1 else datetime.now().strftime("%Y-%m-%d")
|
|
161
|
-
|
|
162
|
-
transcripts_file = DEEP_SLEEP_DIR / f"{date}-transcripts.json"
|
|
163
|
-
if not transcripts_file.exists():
|
|
164
|
-
print(f"No transcripts found for {date}. Run collect_transcripts.py first.")
|
|
165
|
-
sys.exit(1)
|
|
166
|
-
|
|
167
|
-
with open(transcripts_file) as f:
|
|
168
|
-
data = json.load(f)
|
|
169
|
-
|
|
170
|
-
sessions = data["sessions"]
|
|
171
|
-
print(f"Analyzing {len(sessions)} sessions from {date}...")
|
|
172
|
-
|
|
173
|
-
prompt = PROMPT_FILE.read_text()
|
|
174
|
-
|
|
175
|
-
results = []
|
|
176
|
-
for i, session in enumerate(sessions):
|
|
177
|
-
transcript = build_transcript_text(session)
|
|
178
|
-
|
|
179
|
-
if len(transcript) < 500:
|
|
180
|
-
print(f" Session {i+1}/{len(sessions)}: skipped (too short)")
|
|
181
|
-
continue
|
|
182
|
-
|
|
183
|
-
if len(transcript) > MAX_TRANSCRIPT_CHARS:
|
|
184
|
-
transcript = transcript[:MAX_TRANSCRIPT_CHARS] + "\n\n[TRUNCATED]"
|
|
185
|
-
|
|
186
|
-
print(f" Session {i+1}/{len(sessions)}: {session['session_file'][:12]}... ({len(transcript)} chars)")
|
|
187
|
-
result = analyze_with_claude(transcript, prompt)
|
|
188
|
-
if result:
|
|
189
|
-
results.append(result)
|
|
190
|
-
print(f" → {len(result.get('uncaptured_corrections', []))} corrections, "
|
|
191
|
-
f"{len(result.get('protocol_violations', []))} violations")
|
|
192
|
-
else:
|
|
193
|
-
print(f" → Analysis failed")
|
|
194
|
-
|
|
195
|
-
consolidated = consolidate_findings(results)
|
|
196
|
-
consolidated["date"] = date
|
|
197
|
-
consolidated["sessions_analyzed"] = len(results)
|
|
198
|
-
|
|
199
|
-
n_corrections = len(consolidated["uncaptured_corrections"])
|
|
200
|
-
n_violations = len(consolidated["protocol_violations"])
|
|
201
|
-
compliance = consolidated["protocol_compliance"]["overall_compliance"]
|
|
202
|
-
consolidated["summary"] = (
|
|
203
|
-
f"Analyzed {len(results)} sessions. "
|
|
204
|
-
f"Found {n_corrections} uncaptured corrections, {n_violations} protocol violations. "
|
|
205
|
-
f"Overall compliance: {compliance:.0%}."
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
output_file = DEEP_SLEEP_DIR / f"{date}-analysis.json"
|
|
209
|
-
with open(output_file, "w") as f:
|
|
210
|
-
json.dump(consolidated, f, indent=2, ensure_ascii=False)
|
|
211
|
-
|
|
212
|
-
print(f"\nResults: {output_file}")
|
|
213
|
-
print(consolidated["summary"])
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if __name__ == "__main__":
|
|
217
|
-
main()
|