nexo-brain 2.3.0 → 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/README.md +1 -1
- package/bin/nexo-brain.js +92 -9
- package/bin/postinstall.js +22 -15
- package/package.json +7 -4
- package/src/auto_update.py +194 -5
- package/src/crons/sync.py +6 -2
- package/src/db/_core.py +1 -0
- package/src/db/_entities.py +1 -0
- package/src/db/_episodic.py +1 -0
- package/src/db/_learnings.py +1 -0
- package/src/db/_reminders.py +1 -0
- package/src/db/_schema.py +11 -1
- package/src/db/_sessions.py +1 -0
- package/src/db/_skills.py +1 -0
- package/src/hooks/capture-tool-logs.sh +23 -6
- package/src/hooks/session-start.sh +4 -3
- package/src/plugin_loader.py +1 -0
- package/src/plugins/update.py +377 -26
- package/src/scripts/deep-sleep/apply_findings.py +1 -0
- package/src/scripts/deep-sleep/collect.py +1 -0
- package/src/scripts/deep-sleep/extract.py +1 -0
- package/src/scripts/deep-sleep/synthesize.py +1 -0
- 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-learning-housekeep.py +1 -0
- 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 +122 -58
- package/src/server.py +66 -1
- package/src/tools_coordination.py +1 -0
- package/src/tools_sessions.py +1 -0
- package/scripts/migrate-to-unified 2.sh +0 -813
- package/scripts/migrate-to-unified.sh +0 -813
- package/scripts/migrate-v1.5-to-v1.6 2.py +0 -778
- package/scripts/migrate-v1.5-to-v1.6.py +0 -778
- package/scripts/migrate-v1.7-to-v1.8 2.py +0 -214
- package/scripts/migrate-v1.7-to-v1.8.py +0 -214
- package/scripts/nexo-preflight.sh +0 -236
- package/scripts/pre-commit-check 2.sh +0 -55
- package/scripts/pre-commit-check.sh +0 -55
- package/src/__pycache__/auto_close_sessions.cpython-314.pyc +0 -0
- 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__/plugin_loader.cpython-314.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 2.py +0 -159
- package/src/auto_update 2.py +0 -634
- package/src/claim_graph 2.py +0 -323
- package/src/cognitive/__init__ 2.py +0 -62
- 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 2.py +0 -567
- package/src/cognitive/_decay 2.py +0 -382
- package/src/cognitive/_ingest 2.py +0 -892
- package/src/cognitive/_memory 2.py +0 -912
- package/src/cognitive/_search 2.py +0 -949
- package/src/cognitive/_trust 2.py +0 -464
- package/src/crons/__pycache__/sync.cpython-314.pyc +0 -0
- package/src/crons/manifest 2.json +0 -106
- package/src/crons/sync 2.py +0 -217
- package/src/dashboard/__init__ 2.py +0 -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 2.py +0 -789
- package/src/db/__init__ 2.py +0 -89
- 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__/_cron_runs.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_cron_runs.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__/_skills.cpython-310.pyc +0 -0
- package/src/db/__pycache__/_skills.cpython-312.pyc +0 -0
- package/src/db/__pycache__/_skills.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 2.py +0 -417
- package/src/db/_credentials 2.py +0 -124
- package/src/db/_entities 2.py +0 -178
- package/src/db/_episodic 2.py +0 -738
- package/src/db/_evolution 2.py +0 -54
- package/src/db/_fts 2.py +0 -406
- package/src/db/_learnings 2.py +0 -168
- package/src/db/_reminders 2.py +0 -338
- package/src/db/_schema 2.py +0 -364
- package/src/db/_sessions 2.py +0 -300
- package/src/db/_tasks 2.py +0 -91
- package/src/evolution_cycle 2.py +0 -266
- package/src/hnsw_index 2.py +0 -254
- package/src/hooks/auto_capture 2.py +0 -208
- package/src/hooks/caffeinate-guard 2.sh +0 -8
- package/src/hooks/capture-session 2.sh +0 -21
- package/src/hooks/capture-tool-logs 2.sh +0 -127
- package/src/hooks/daily-briefing-check 2.sh +0 -33
- package/src/hooks/inbox-hook 2.sh +0 -76
- package/src/hooks/post-compact 2.sh +0 -148
- package/src/hooks/pre-compact 2.sh +0 -151
- package/src/hooks/session-start 2.sh +0 -268
- package/src/hooks/session-stop 2.sh +0 -140
- package/src/kg_populate 2.py +0 -290
- package/src/knowledge_graph 2.py +0 -257
- package/src/maintenance 2.py +0 -59
- package/src/migrate_embeddings 2.py +0 -122
- package/src/plugin_loader 2.py +0 -202
- package/src/plugins/__init__ 2.py +0 -0
- package/src/plugins/__pycache__/__init__ 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/__init__.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/__init__.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/adaptive_mode 2.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 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/agents.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/artifact_registry 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/artifact_registry.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/backup 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/backup.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cognitive_memory 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cognitive_memory.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/core_rules 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/core_rules.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cortex 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/cortex.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/entities 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/entities.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/episodic_memory 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/episodic_memory.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/evolution 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/evolution.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/guard 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/guard.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/knowledge_graph_tools 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/knowledge_graph_tools.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/preferences 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/preferences.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/schedule.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/schedule.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/skills.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/skills.cpython-314.pyc +0 -0
- package/src/plugins/__pycache__/update 2.cpython-310.pyc +0 -0
- package/src/plugins/__pycache__/update.cpython-310.pyc +0 -0
- package/src/plugins/adaptive_mode 2.py +0 -805
- package/src/plugins/agents 2.py +0 -52
- package/src/plugins/artifact_registry 2.py +0 -450
- package/src/plugins/backup 2.py +0 -104
- package/src/plugins/cognitive_memory 2.py +0 -564
- package/src/plugins/core_rules 2.py +0 -252
- package/src/plugins/cortex 2.py +0 -299
- package/src/plugins/entities 2.py +0 -67
- package/src/plugins/episodic_memory 2.py +0 -533
- package/src/plugins/evolution 2.py +0 -115
- package/src/plugins/guard 2.py +0 -746
- package/src/plugins/knowledge_graph_tools 2.py +0 -105
- package/src/plugins/preferences 2.py +0 -47
- package/src/plugins/update 2.py +0 -256
- package/src/requirements 2.txt +0 -12
- package/src/rules/__init__ 2.py +0 -0
- package/src/rules/core-rules 2.json +0 -331
- package/src/rules/migrate 2.py +0 -207
- 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-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 2.py +0 -264
- package/src/scripts/nexo-auto-update 2.py +0 -6
- package/src/scripts/nexo-backup 2.sh +0 -25
- package/src/scripts/nexo-brain-activation 2.sh +0 -140
- package/src/scripts/nexo-catchup 2.py +0 -242
- package/src/scripts/nexo-cognitive-decay 2.py +0 -182
- package/src/scripts/nexo-daily-self-audit 2.py +0 -552
- package/src/scripts/nexo-deep-sleep 2.sh +0 -97
- package/src/scripts/nexo-evolution-run 2.py +0 -597
- package/src/scripts/nexo-followup-hygiene 2.py +0 -112
- package/src/scripts/nexo-github-monitor 2.py +0 -256
- package/src/scripts/nexo-immune 2.py +0 -927
- package/src/scripts/nexo-inbox-hook 2.sh +0 -74
- package/src/scripts/nexo-install 2.py +0 -6
- package/src/scripts/nexo-learning-housekeep 2.py +0 -245
- package/src/scripts/nexo-learning-validator 2.py +0 -207
- package/src/scripts/nexo-migrate 2.py +0 -232
- package/src/scripts/nexo-postmortem-consolidator 2.py +0 -421
- package/src/scripts/nexo-pre-commit 2.py +0 -120
- package/src/scripts/nexo-prevent-sleep 2.sh +0 -29
- package/src/scripts/nexo-proactive-dashboard 2.py +0 -345
- package/src/scripts/nexo-reflection 2.py +0 -253
- package/src/scripts/nexo-runtime-preflight 2.py +0 -274
- package/src/scripts/nexo-send-email 2.py +0 -25
- package/src/scripts/nexo-send-email.py +0 -25
- package/src/scripts/nexo-send-reply 2.py +0 -178
- package/src/scripts/nexo-send-reply.py +0 -178
- package/src/scripts/nexo-sleep 2.py +0 -592
- package/src/scripts/nexo-snapshot-restore 2.sh +0 -35
- package/src/scripts/nexo-synthesis 2.py +0 -253
- package/src/scripts/nexo-tcc-approve 2.sh +0 -79
- package/src/scripts/nexo-update 2.sh +0 -161
- package/src/scripts/nexo-watchdog 2.sh +0 -878
- package/src/scripts/nexo-watchdog-smoke 2.py +0 -119
- package/src/server 2.py +0 -733
- package/src/storage_router 2.py +0 -32
- package/src/tools_coordination 2.py +0 -102
- package/src/tools_credentials 2.py +0 -68
- package/src/tools_learnings 2.py +0 -220
- package/src/tools_menu 2.py +0 -227
- package/src/tools_reminders 2.py +0 -86
- package/src/tools_reminders_crud 2.py +0 -159
- package/src/tools_sessions 2.py +0 -476
- package/src/tools_task_history 2.py +0 -57
- package/templates/CLAUDE.md 2.template +0 -63
- package/templates/openclaw 2.json +0 -13
- package/tests/__init__ 2.py +0 -0
- package/tests/__init__.py +0 -0
- package/tests/conftest 2.py +0 -71
- package/tests/conftest.py +0 -71
- package/tests/test_cognitive 2.py +0 -205
- package/tests/test_cognitive.py +0 -205
- package/tests/test_knowledge_graph 2.py +0 -140
- package/tests/test_knowledge_graph.py +0 -140
- package/tests/test_migrations 2.py +0 -137
- package/tests/test_migrations.py +0 -137
|
@@ -1,564 +0,0 @@
|
|
|
1
|
-
"""Cognitive Memory plugin — RAG retrieval over NEXO's Atkinson-Shiffrin memory stores."""
|
|
2
|
-
|
|
3
|
-
import sys
|
|
4
|
-
import os
|
|
5
|
-
|
|
6
|
-
# Ensure site-packages is in path for numpy/fastembed
|
|
7
|
-
_site = "/opt/homebrew/lib/python{}.{}/site-packages".format(sys.version_info.major, sys.version_info.minor)
|
|
8
|
-
if os.path.isdir(_site) and _site not in sys.path:
|
|
9
|
-
sys.path.insert(0, _site)
|
|
10
|
-
|
|
11
|
-
import cognitive
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def handle_cognitive_retrieve(
|
|
15
|
-
query: str,
|
|
16
|
-
top_k: int = 10,
|
|
17
|
-
min_score: float = 0.5,
|
|
18
|
-
stores: str = "both",
|
|
19
|
-
source_type: str = "",
|
|
20
|
-
domain: str = "",
|
|
21
|
-
include_archived: bool = False,
|
|
22
|
-
use_hyde: bool = False,
|
|
23
|
-
spreading_depth: int = 0,
|
|
24
|
-
) -> str:
|
|
25
|
-
"""RAG query over cognitive memory (STM + LTM). Triggers rehearsal on retrieved memories.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
query: Natural language query to search for
|
|
29
|
-
top_k: Maximum number of results to return (default 10)
|
|
30
|
-
min_score: Minimum cosine similarity score (default 0.5)
|
|
31
|
-
stores: Which store to search — "both", "stm", or "ltm" (default "both")
|
|
32
|
-
source_type: Filter by source type e.g. "change", "learning", "diary" (default: all)
|
|
33
|
-
domain: Filter by domain e.g. "project-a", "shopify" (default: all)
|
|
34
|
-
include_archived: If True, also search archived memories (default False)
|
|
35
|
-
use_hyde: If True, use HyDE query expansion — embeds 3-5 query variants and searches with centroid. Better recall for conceptual queries. (default False)
|
|
36
|
-
spreading_depth: If >0, boost co-activated neighbors (memories frequently retrieved together). 1=direct neighbors only. (default 0)
|
|
37
|
-
"""
|
|
38
|
-
if not query or not query.strip():
|
|
39
|
-
return "ERROR: query is required."
|
|
40
|
-
|
|
41
|
-
results = cognitive.search(
|
|
42
|
-
query_text=query,
|
|
43
|
-
top_k=top_k,
|
|
44
|
-
min_score=min_score,
|
|
45
|
-
stores=stores,
|
|
46
|
-
exclude_dormant=True,
|
|
47
|
-
rehearse=True,
|
|
48
|
-
source_type_filter=source_type,
|
|
49
|
-
include_archived=include_archived,
|
|
50
|
-
use_hyde=use_hyde,
|
|
51
|
-
spreading_depth=spreading_depth,
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
# Apply domain filter post-search (cognitive.search doesn't filter by domain natively)
|
|
55
|
-
if domain:
|
|
56
|
-
results = [r for r in results if r.get("domain", "") == domain]
|
|
57
|
-
|
|
58
|
-
formatted = cognitive.format_results(results)
|
|
59
|
-
mode_parts = [f"stores={stores}", f"min_score={min_score}"]
|
|
60
|
-
if use_hyde:
|
|
61
|
-
mode_parts.append("hyde=ON")
|
|
62
|
-
if spreading_depth > 0:
|
|
63
|
-
mode_parts.append(f"spreading={spreading_depth}")
|
|
64
|
-
header = f"COGNITIVE RETRIEVE — query: '{query}' | {len(results)} results ({', '.join(mode_parts)})\n\n"
|
|
65
|
-
return header + formatted
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def handle_cognitive_stats() -> str:
|
|
69
|
-
"""Return cognitive memory system metrics: STM/LTM counts, strengths, retrieval stats, top domains."""
|
|
70
|
-
stats = cognitive.get_stats()
|
|
71
|
-
|
|
72
|
-
lines = [
|
|
73
|
-
"COGNITIVE MEMORY STATS",
|
|
74
|
-
f" STM active: {stats['stm_active']} (+ {stats.get('stm_promoted', 0)} promoted to LTM, {stats.get('stm_total', 0)} total)",
|
|
75
|
-
f" LTM active: {stats['ltm_active']}",
|
|
76
|
-
f" LTM dormant: {stats['ltm_dormant']}",
|
|
77
|
-
f" Avg STM strength: {stats['avg_stm_strength']:.3f}",
|
|
78
|
-
f" Avg LTM strength: {stats['avg_ltm_strength']:.3f}",
|
|
79
|
-
f" Total retrievals: {stats['total_retrievals']}",
|
|
80
|
-
f" Avg retrieval score: {stats['avg_retrieval_score']:.3f}",
|
|
81
|
-
]
|
|
82
|
-
|
|
83
|
-
if stats["top_domains_stm"]:
|
|
84
|
-
lines.append(" Top STM domains:")
|
|
85
|
-
for domain, cnt in stats["top_domains_stm"]:
|
|
86
|
-
lines.append(f" {domain}: {cnt}")
|
|
87
|
-
|
|
88
|
-
if stats["top_domains_ltm"]:
|
|
89
|
-
lines.append(" Top LTM domains:")
|
|
90
|
-
for domain, cnt in stats["top_domains_ltm"]:
|
|
91
|
-
lines.append(f" {domain}: {cnt}")
|
|
92
|
-
|
|
93
|
-
if "quarantine" in stats:
|
|
94
|
-
q = stats["quarantine"]
|
|
95
|
-
lines.append(f" Quarantine pending: {q.get('pending', 0)}")
|
|
96
|
-
lines.append(f" Quarantine promoted: {q.get('promoted', 0)}")
|
|
97
|
-
lines.append(f" Quarantine rejected: {q.get('rejected', 0)}")
|
|
98
|
-
lines.append(f" Quarantine expired: {q.get('expired', 0)}")
|
|
99
|
-
|
|
100
|
-
if "prediction_error_gate" in stats:
|
|
101
|
-
g = stats["prediction_error_gate"]
|
|
102
|
-
lines.append(" PE Gate (session):")
|
|
103
|
-
lines.append(f" Accepted (novel): {g['accepted_novel']}")
|
|
104
|
-
lines.append(f" Accepted (refine): {g['accepted_refinement']}")
|
|
105
|
-
lines.append(f" Rejected (redundant): {g['rejected']}")
|
|
106
|
-
lines.append(f" Rejection rate: {g['rejection_rate_pct']}%")
|
|
107
|
-
|
|
108
|
-
return "\n".join(lines)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def handle_cognitive_inspect(memory_id: int, store: str = "ltm") -> str:
|
|
112
|
-
"""Inspect a specific memory by ID without triggering rehearsal.
|
|
113
|
-
|
|
114
|
-
Args:
|
|
115
|
-
memory_id: Integer ID of the memory to inspect
|
|
116
|
-
store: Which store to read from — "stm" or "ltm" (default "ltm")
|
|
117
|
-
"""
|
|
118
|
-
if store not in ("stm", "ltm"):
|
|
119
|
-
return "ERROR: store must be 'stm' or 'ltm'."
|
|
120
|
-
|
|
121
|
-
db = cognitive._get_db()
|
|
122
|
-
table = "stm_memories" if store == "stm" else "ltm_memories"
|
|
123
|
-
|
|
124
|
-
row = db.execute(f"SELECT * FROM {table} WHERE id = ?", (memory_id,)).fetchone()
|
|
125
|
-
if row is None:
|
|
126
|
-
return f"ERROR: Memory #{memory_id} not found in {store.upper()}."
|
|
127
|
-
|
|
128
|
-
content_preview = row["content"][:500]
|
|
129
|
-
if len(row["content"]) > 500:
|
|
130
|
-
content_preview += "..."
|
|
131
|
-
|
|
132
|
-
lines = [
|
|
133
|
-
f"COGNITIVE INSPECT — {store.upper()} #{memory_id}",
|
|
134
|
-
f" source_type: {row['source_type']}",
|
|
135
|
-
f" source_id: {row['source_id']}",
|
|
136
|
-
f" source_title: {row['source_title']}",
|
|
137
|
-
f" domain: {row['domain']}",
|
|
138
|
-
f" strength: {row['strength']:.4f}",
|
|
139
|
-
f" access_count: {row['access_count']}",
|
|
140
|
-
f" created_at: {row['created_at']}",
|
|
141
|
-
f" last_accessed: {row['last_accessed']}",
|
|
142
|
-
]
|
|
143
|
-
|
|
144
|
-
# Lifecycle state
|
|
145
|
-
lifecycle = row["lifecycle_state"] or "active"
|
|
146
|
-
lines.append(f" lifecycle: {lifecycle}")
|
|
147
|
-
if row["snooze_until"]:
|
|
148
|
-
lines.append(f" snooze_until: {row['snooze_until']}")
|
|
149
|
-
|
|
150
|
-
if store == "ltm":
|
|
151
|
-
dormant_label = "YES" if row["is_dormant"] else "no"
|
|
152
|
-
lines.append(f" dormant: {dormant_label}")
|
|
153
|
-
if row["tags"]:
|
|
154
|
-
lines.append(f" tags: {row['tags']}")
|
|
155
|
-
|
|
156
|
-
if store == "stm":
|
|
157
|
-
promoted_label = "YES" if row["promoted_to_ltm"] else "no"
|
|
158
|
-
lines.append(f" promoted: {promoted_label}")
|
|
159
|
-
|
|
160
|
-
lines.append(f" content:\n {content_preview}")
|
|
161
|
-
|
|
162
|
-
return "\n".join(lines)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def handle_cognitive_metrics(days: int = 7) -> str:
|
|
166
|
-
"""Cognitive memory performance metrics (spec section 9).
|
|
167
|
-
|
|
168
|
-
Returns retrieval relevance %, repeat error rate, score distribution,
|
|
169
|
-
and whether multilingual model switch is recommended.
|
|
170
|
-
|
|
171
|
-
Args:
|
|
172
|
-
days: Period to analyze in days (default 7)
|
|
173
|
-
"""
|
|
174
|
-
metrics = cognitive.get_metrics(days=days)
|
|
175
|
-
repeats = cognitive.check_repeat_errors()
|
|
176
|
-
|
|
177
|
-
lines = [
|
|
178
|
-
f"COGNITIVE METRICS — last {days} days",
|
|
179
|
-
"",
|
|
180
|
-
"Retrieval Performance:",
|
|
181
|
-
f" Total retrievals: {metrics['total_retrievals']}",
|
|
182
|
-
f" Retrievals/day: {metrics['retrievals_per_day']}",
|
|
183
|
-
f" Relevance (>=0.6): {metrics['retrieval_relevance_pct']}% (target: >60%)",
|
|
184
|
-
f" Avg top score: {metrics['avg_top_score']}",
|
|
185
|
-
"",
|
|
186
|
-
"Score Distribution:",
|
|
187
|
-
f" >0.8 (excellent): {metrics['score_distribution']['above_80']}",
|
|
188
|
-
f" 0.7-0.8 (good): {metrics['score_distribution']['70_80']}",
|
|
189
|
-
f" 0.6-0.7 (ok): {metrics['score_distribution']['60_70']}",
|
|
190
|
-
f" 0.5-0.6 (weak): {metrics['score_distribution']['50_60']}",
|
|
191
|
-
f" <0.5 (irrelevant): {metrics['score_distribution']['below_50']}",
|
|
192
|
-
"",
|
|
193
|
-
"Repeat Error Rate:",
|
|
194
|
-
f" New learnings (7d): {repeats['new_count']}",
|
|
195
|
-
f" Duplicates found: {repeats['duplicate_count']}",
|
|
196
|
-
f" Repeat rate: {repeats['repeat_rate_pct']}% (target: <10%)",
|
|
197
|
-
]
|
|
198
|
-
|
|
199
|
-
if metrics["needs_multilingual"]:
|
|
200
|
-
lines.append("")
|
|
201
|
-
lines.append("⚠ RECOMMENDATION: Switch to multilingual model (intfloat/multilingual-e5-small)")
|
|
202
|
-
lines.append(f" Reason: relevance {metrics['retrieval_relevance_pct']}% < 70% with {metrics['total_retrievals']}+ retrievals")
|
|
203
|
-
|
|
204
|
-
if repeats["duplicates"]:
|
|
205
|
-
lines.append("")
|
|
206
|
-
lines.append("Top duplicates:")
|
|
207
|
-
for d in repeats["duplicates"][:5]:
|
|
208
|
-
lines.append(f" [{d['score']}] STM#{d['new_stm_id']}: {d['new_content'][:60]}...")
|
|
209
|
-
lines.append(f" ≈ LTM#{d['ltm_id']}: {d['ltm_content'][:60]}...")
|
|
210
|
-
|
|
211
|
-
# Prediction Error Gate stats
|
|
212
|
-
gate = cognitive.get_gate_stats()
|
|
213
|
-
if gate["total_evaluated"] > 0:
|
|
214
|
-
lines.append("")
|
|
215
|
-
lines.append("Prediction Error Gate (session):")
|
|
216
|
-
lines.append(f" Novel accepted: {gate['accepted_novel']}")
|
|
217
|
-
lines.append(f" Refinements: {gate['accepted_refinement']}")
|
|
218
|
-
lines.append(f" Rejected redundant: {gate['rejected']}")
|
|
219
|
-
lines.append(f" Rejection rate: {gate['rejection_rate_pct']}%")
|
|
220
|
-
|
|
221
|
-
return "\n".join(lines)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def handle_cognitive_sentiment(text: str) -> str:
|
|
225
|
-
"""Detect user's sentiment from his text. Returns mood, intensity, and guidance.
|
|
226
|
-
|
|
227
|
-
Call this with user's recent message to adapt NEXO's tone and behavior.
|
|
228
|
-
Also logs the sentiment for historical tracking.
|
|
229
|
-
|
|
230
|
-
Args:
|
|
231
|
-
text: user's recent message or instruction
|
|
232
|
-
"""
|
|
233
|
-
result = cognitive.log_sentiment(text)
|
|
234
|
-
trust = cognitive.get_trust_score()
|
|
235
|
-
|
|
236
|
-
lines = [
|
|
237
|
-
f"SENTIMENT: {result['sentiment'].upper()} (intensity: {result['intensity']})",
|
|
238
|
-
f"Trust Score: {trust:.0f}/100",
|
|
239
|
-
]
|
|
240
|
-
if result["signals"]:
|
|
241
|
-
lines.append(f"Signals: {', '.join(result['signals'])}")
|
|
242
|
-
if result["guidance"]:
|
|
243
|
-
lines.append(f"Guidance: {result['guidance']}")
|
|
244
|
-
|
|
245
|
-
return "\n".join(lines)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
def handle_cognitive_trust(event: str = '', context: str = '', delta: float = None) -> str:
|
|
249
|
-
"""View or adjust the trust score (alignment index 0-100).
|
|
250
|
-
|
|
251
|
-
Without arguments: shows current score and recent history.
|
|
252
|
-
With event: adjusts score based on event type.
|
|
253
|
-
|
|
254
|
-
Args:
|
|
255
|
-
event: Event type — explicit_thanks, delegation, paradigm_shift, sibling_detected,
|
|
256
|
-
proactive_action, correction, repeated_error, override, correction_fatigue,
|
|
257
|
-
forgot_followup. Or empty to just view.
|
|
258
|
-
context: Description of what happened
|
|
259
|
-
delta: Custom point value (overrides default for the event type)
|
|
260
|
-
"""
|
|
261
|
-
if not event:
|
|
262
|
-
# View mode
|
|
263
|
-
trust = cognitive.get_trust_score()
|
|
264
|
-
history = cognitive.get_trust_history(days=7)
|
|
265
|
-
|
|
266
|
-
lines = [
|
|
267
|
-
f"TRUST SCORE: {trust:.0f}/100",
|
|
268
|
-
f"7-day change: {history['net_change']:+.0f} (from {history['period_start_score']:.0f})",
|
|
269
|
-
"",
|
|
270
|
-
]
|
|
271
|
-
|
|
272
|
-
if history["sentiment_distribution"]:
|
|
273
|
-
lines.append("Sentiment (7d):")
|
|
274
|
-
for sent, data in history["sentiment_distribution"].items():
|
|
275
|
-
lines.append(f" {sent}: {data['count']}x (avg intensity {data['avg_intensity']})")
|
|
276
|
-
lines.append("")
|
|
277
|
-
|
|
278
|
-
if history["events"]:
|
|
279
|
-
lines.append("Recent events:")
|
|
280
|
-
for e in history["events"][-10:]:
|
|
281
|
-
lines.append(f" [{e['delta']:+.0f}] {e['event']}: {e['context'][:60]} ({e['at'][:16]})")
|
|
282
|
-
|
|
283
|
-
return "\n".join(lines)
|
|
284
|
-
|
|
285
|
-
# Adjust mode
|
|
286
|
-
result = cognitive.adjust_trust(event, context, delta)
|
|
287
|
-
if "error" in result:
|
|
288
|
-
valid = ", ".join(sorted(cognitive.TRUST_EVENTS.keys()))
|
|
289
|
-
return f"Unknown event '{event}'. Valid: {valid}"
|
|
290
|
-
|
|
291
|
-
return f"Trust: {result['old_score']:.0f} → {result['new_score']:.0f} ({result['delta']:+.0f}) [{event}]"
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
def handle_cognitive_dissonance(instruction: str, force: bool = False) -> str:
|
|
295
|
-
"""Detect cognitive dissonance: find established memories that conflict with a new instruction.
|
|
296
|
-
|
|
297
|
-
Use BEFORE applying a new preference or rule from user that might contradict
|
|
298
|
-
existing knowledge. If conflicts found, verbalize them and ask user to resolve.
|
|
299
|
-
|
|
300
|
-
Args:
|
|
301
|
-
instruction: The new instruction or preference to check against LTM
|
|
302
|
-
force: If True, skip discussion — execute instruction, auto-resolve all conflicts as
|
|
303
|
-
'exception', and flag for review in the nocturnal process (23:30).
|
|
304
|
-
"""
|
|
305
|
-
conflicts = cognitive.detect_dissonance(instruction)
|
|
306
|
-
if not conflicts:
|
|
307
|
-
return f"No dissonance detected. Instruction '{instruction[:80]}' is consistent with existing LTM."
|
|
308
|
-
|
|
309
|
-
if force:
|
|
310
|
-
# Auto-resolve all as exceptions, log for nocturnal review
|
|
311
|
-
for c in conflicts:
|
|
312
|
-
cognitive.resolve_dissonance(
|
|
313
|
-
c["memory_id"], "exception",
|
|
314
|
-
f"[FORCE] {instruction[:200]} — auto-exception, pending nocturnal review"
|
|
315
|
-
)
|
|
316
|
-
return (f"FORCE: {len(conflicts)} conflicts auto-resolved as exceptions. "
|
|
317
|
-
f"Instruction executed. Flagged for review at 23:30.")
|
|
318
|
-
|
|
319
|
-
lines = [
|
|
320
|
-
f"COGNITIVE DISSONANCE DETECTED — {len(conflicts)} conflicting memories:",
|
|
321
|
-
f"New instruction: \"{instruction[:200]}\"",
|
|
322
|
-
"",
|
|
323
|
-
]
|
|
324
|
-
for c in conflicts:
|
|
325
|
-
lines.append(f" LTM #{c['memory_id']} [{c['source_type']}] (strength={c['strength']:.2f}, {c['access_count']} accesses)")
|
|
326
|
-
lines.append(f" Similarity: {c['similarity']}")
|
|
327
|
-
lines.append(f" Content: {c['content'][:200]}")
|
|
328
|
-
lines.append("")
|
|
329
|
-
|
|
330
|
-
lines.append("RESOLVE with nexo_cognitive_resolve, or use force=True to skip:")
|
|
331
|
-
lines.append(" - 'paradigm_shift': user changed his mind permanently.")
|
|
332
|
-
lines.append(" - 'exception': One-time override. Old memory stays.")
|
|
333
|
-
lines.append(" - 'override': Old memory was wrong.")
|
|
334
|
-
|
|
335
|
-
return "\n".join(lines)
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
def handle_cognitive_resolve(memory_id: int, resolution: str, context: str = '') -> str:
|
|
339
|
-
"""Resolve a cognitive dissonance by applying user's decision.
|
|
340
|
-
|
|
341
|
-
Args:
|
|
342
|
-
memory_id: The LTM memory ID from the dissonance detection
|
|
343
|
-
resolution: 'paradigm_shift' (permanent change), 'exception' (one-time), or 'override' (old was wrong)
|
|
344
|
-
context: Optional context about why this resolution was chosen
|
|
345
|
-
"""
|
|
346
|
-
return cognitive.resolve_dissonance(memory_id, resolution, context)
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
def handle_cognitive_pin(memory_id: int, store: str = "auto") -> str:
|
|
350
|
-
"""Pin a memory so it NEVER decays and gets boosted in search results (+0.2 similarity).
|
|
351
|
-
|
|
352
|
-
Args:
|
|
353
|
-
memory_id: Integer ID of the memory to pin
|
|
354
|
-
store: Which store — "stm", "ltm", or "auto" (tries both, default "auto")
|
|
355
|
-
"""
|
|
356
|
-
return cognitive.set_lifecycle(memory_id, "pinned", store)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
def handle_cognitive_snooze(memory_id: int, until_date: str, store: str = "auto") -> str:
|
|
360
|
-
"""Snooze a memory — hidden from searches until the given date, then auto-restores to active.
|
|
361
|
-
|
|
362
|
-
Args:
|
|
363
|
-
memory_id: Integer ID of the memory to snooze
|
|
364
|
-
until_date: Date to restore the memory (YYYY-MM-DD format)
|
|
365
|
-
store: Which store — "stm", "ltm", or "auto" (tries both, default "auto")
|
|
366
|
-
"""
|
|
367
|
-
return cognitive.set_lifecycle(memory_id, "snoozed", store, snooze_until=until_date)
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
def handle_cognitive_archive(memory_id: int, store: str = "auto") -> str:
|
|
371
|
-
"""Archive a memory — stored but excluded from normal searches. Can be restored later.
|
|
372
|
-
|
|
373
|
-
Args:
|
|
374
|
-
memory_id: Integer ID of the memory to archive
|
|
375
|
-
store: Which store — "stm", "ltm", or "auto" (tries both, default "auto")
|
|
376
|
-
"""
|
|
377
|
-
return cognitive.set_lifecycle(memory_id, "archived", store)
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
def handle_cognitive_restore(memory_id: int, store: str = "auto") -> str:
|
|
381
|
-
"""Restore a memory to active state (from pinned, snoozed, or archived).
|
|
382
|
-
|
|
383
|
-
Args:
|
|
384
|
-
memory_id: Integer ID of the memory to restore
|
|
385
|
-
store: Which store — "stm", "ltm", or "auto" (tries both, default "auto")
|
|
386
|
-
"""
|
|
387
|
-
return cognitive.set_lifecycle(memory_id, "active", store)
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
def handle_cognitive_quarantine_list(status: str = "pending", limit: int = 20) -> str:
|
|
391
|
-
"""List quarantine queue items. Shows memories awaiting promotion to STM.
|
|
392
|
-
|
|
393
|
-
Args:
|
|
394
|
-
status: Filter — 'pending', 'promoted', 'rejected', 'expired', or 'all' (default 'pending')
|
|
395
|
-
limit: Max items to return (default 20)
|
|
396
|
-
"""
|
|
397
|
-
items = cognitive.quarantine_list(status=status, limit=limit)
|
|
398
|
-
stats = cognitive.quarantine_stats()
|
|
399
|
-
|
|
400
|
-
lines = [
|
|
401
|
-
f"QUARANTINE QUEUE — {stats['pending']} pending | {stats['promoted']} promoted | {stats['rejected']} rejected | {stats['expired']} expired",
|
|
402
|
-
f"Showing: {status} (limit {limit})",
|
|
403
|
-
"",
|
|
404
|
-
]
|
|
405
|
-
|
|
406
|
-
if not items:
|
|
407
|
-
lines.append("No items found.")
|
|
408
|
-
else:
|
|
409
|
-
for item in items:
|
|
410
|
-
lines.append(f" #{item['id']} [{item['status']}] source={item['source']} type={item['source_type']} domain={item['domain'] or '-'}")
|
|
411
|
-
lines.append(f" confidence={item['confidence']:.1f} checks={item['promotion_checks']} created={item['created_at'][:16]}")
|
|
412
|
-
if item['promoted_at']:
|
|
413
|
-
lines.append(f" promoted_at={item['promoted_at'][:16]}")
|
|
414
|
-
lines.append(f" {item['content']}")
|
|
415
|
-
lines.append("")
|
|
416
|
-
|
|
417
|
-
return "\n".join(lines)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
def handle_cognitive_quarantine_promote(quarantine_id: int) -> str:
|
|
421
|
-
"""Manually promote a quarantine item to STM, bypassing the automatic promotion policy.
|
|
422
|
-
|
|
423
|
-
Args:
|
|
424
|
-
quarantine_id: ID of the quarantine entry to promote
|
|
425
|
-
"""
|
|
426
|
-
return cognitive.quarantine_promote(quarantine_id)
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
def handle_cognitive_quarantine_reject(quarantine_id: int, reason: str = "") -> str:
|
|
430
|
-
"""Manually reject a quarantine item.
|
|
431
|
-
|
|
432
|
-
Args:
|
|
433
|
-
quarantine_id: ID of the quarantine entry to reject
|
|
434
|
-
reason: Optional reason for rejection
|
|
435
|
-
"""
|
|
436
|
-
return cognitive.quarantine_reject(quarantine_id, reason)
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
def handle_cognitive_quarantine_process() -> str:
|
|
440
|
-
"""Run the quarantine promotion cycle. Evaluates all pending items against the promotion policy.
|
|
441
|
-
|
|
442
|
-
Promotion rules:
|
|
443
|
-
- source='user_direct' → already promoted at ingest
|
|
444
|
-
- source='inferred' + second occurrence found → promote
|
|
445
|
-
- source='agent_observation' + >24h old + no LTM contradiction → promote
|
|
446
|
-
- Contradicts LTM (cosine >0.8) → reject
|
|
447
|
-
- >7 days old → expire
|
|
448
|
-
"""
|
|
449
|
-
result = cognitive.process_quarantine()
|
|
450
|
-
lines = [
|
|
451
|
-
"QUARANTINE PROCESSING COMPLETE",
|
|
452
|
-
f" Promoted: {result['promoted']}",
|
|
453
|
-
f" Rejected: {result['rejected']}",
|
|
454
|
-
f" Expired: {result['expired']}",
|
|
455
|
-
f" Still pending: {result['still_pending']}",
|
|
456
|
-
f" Total: {result['total_processed']}",
|
|
457
|
-
]
|
|
458
|
-
return "\n".join(lines)
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
# ============================================================================
|
|
462
|
-
# Prospective Memory trigger handlers (Feature 3)
|
|
463
|
-
# ============================================================================
|
|
464
|
-
|
|
465
|
-
def handle_cognitive_trigger_create(pattern: str, action: str, context: str = "") -> str:
|
|
466
|
-
"""Create a prospective memory trigger — fires when text matches pattern.
|
|
467
|
-
|
|
468
|
-
Args:
|
|
469
|
-
pattern: Keywords to match (case-insensitive, comma-separated for OR matching)
|
|
470
|
-
action: What to do / remind about when the trigger fires
|
|
471
|
-
context: Optional context about why this trigger was created
|
|
472
|
-
"""
|
|
473
|
-
trigger_id = cognitive.create_trigger(pattern, action, context)
|
|
474
|
-
return f"Trigger #{trigger_id} created — armed. Pattern: '{pattern}' | Action: '{action}'"
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
def handle_cognitive_trigger_list(status: str = "armed") -> str:
|
|
478
|
-
"""List prospective memory triggers.
|
|
479
|
-
|
|
480
|
-
Args:
|
|
481
|
-
status: Filter — 'armed' (active, waiting), 'fired' (already triggered), 'all'
|
|
482
|
-
"""
|
|
483
|
-
triggers = cognitive.list_triggers(status)
|
|
484
|
-
if not triggers:
|
|
485
|
-
return f"No {status} triggers found."
|
|
486
|
-
|
|
487
|
-
lines = [f"PROSPECTIVE TRIGGERS ({status}) — {len(triggers)} total", ""]
|
|
488
|
-
for t in triggers:
|
|
489
|
-
status_icon = "+" if t["status"] == "armed" else "x"
|
|
490
|
-
lines.append(f" [{status_icon}] #{t['id']} pattern='{t['trigger_pattern']}'")
|
|
491
|
-
lines.append(f" action: {t['action']}")
|
|
492
|
-
if t.get("context"):
|
|
493
|
-
lines.append(f" context: {t['context']}")
|
|
494
|
-
lines.append(f" created: {t['created_at'][:16]}")
|
|
495
|
-
if t.get("fired_at"):
|
|
496
|
-
lines.append(f" fired: {t['fired_at'][:16]}")
|
|
497
|
-
lines.append("")
|
|
498
|
-
|
|
499
|
-
return "\n".join(lines)
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
def handle_cognitive_trigger_check(text: str, use_semantic: bool = False) -> str:
|
|
503
|
-
"""Check text against all armed triggers and fire matching ones.
|
|
504
|
-
|
|
505
|
-
Args:
|
|
506
|
-
text: Text to check against triggers (e.g. user message, heartbeat context)
|
|
507
|
-
use_semantic: Also use embedding similarity (slower but catches conceptual matches)
|
|
508
|
-
"""
|
|
509
|
-
fired = cognitive.check_triggers(text, use_semantic=use_semantic)
|
|
510
|
-
if not fired:
|
|
511
|
-
return "No triggers fired."
|
|
512
|
-
|
|
513
|
-
lines = [f"TRIGGERS FIRED: {len(fired)}", ""]
|
|
514
|
-
for t in fired:
|
|
515
|
-
lines.append(f" #{t['id']} [{t['match_type']}] pattern='{t['pattern']}'")
|
|
516
|
-
lines.append(f" ACTION: {t['action']}")
|
|
517
|
-
if t.get("context"):
|
|
518
|
-
lines.append(f" context: {t['context']}")
|
|
519
|
-
lines.append("")
|
|
520
|
-
|
|
521
|
-
return "\n".join(lines)
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
def handle_cognitive_trigger_delete(trigger_id: int) -> str:
|
|
525
|
-
"""Delete a prospective memory trigger.
|
|
526
|
-
|
|
527
|
-
Args:
|
|
528
|
-
trigger_id: ID of the trigger to delete
|
|
529
|
-
"""
|
|
530
|
-
return cognitive.delete_trigger(trigger_id)
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
def handle_cognitive_trigger_rearm(trigger_id: int) -> str:
|
|
534
|
-
"""Re-arm a fired trigger so it can fire again.
|
|
535
|
-
|
|
536
|
-
Args:
|
|
537
|
-
trigger_id: ID of the trigger to re-arm
|
|
538
|
-
"""
|
|
539
|
-
return cognitive.rearm_trigger(trigger_id)
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
TOOLS = [
|
|
543
|
-
(handle_cognitive_retrieve, "nexo_cognitive_retrieve", "RAG query over cognitive memory (STM+LTM). Triggers rehearsal on retrieved results."),
|
|
544
|
-
(handle_cognitive_stats, "nexo_cognitive_stats", "Cognitive memory system metrics: STM/LTM counts, strengths, retrieval stats, quarantine counts"),
|
|
545
|
-
(handle_cognitive_inspect, "nexo_cognitive_inspect", "Inspect a specific memory by ID (debug). Does NOT trigger rehearsal."),
|
|
546
|
-
(handle_cognitive_metrics, "nexo_cognitive_metrics", "Performance metrics: retrieval relevance %, repeat error rate, multilingual recommendation (spec section 9)"),
|
|
547
|
-
(handle_cognitive_dissonance, "nexo_cognitive_dissonance", "Detect conflicts between a new instruction and established LTM memories. force=True to skip discussion."),
|
|
548
|
-
(handle_cognitive_resolve, "nexo_cognitive_resolve", "Resolve a cognitive dissonance: paradigm_shift, exception, or override."),
|
|
549
|
-
(handle_cognitive_sentiment, "nexo_cognitive_sentiment", "Detect user's sentiment and get tone guidance. Also logs for tracking."),
|
|
550
|
-
(handle_cognitive_trust, "nexo_cognitive_trust", "View or adjust trust score (0-100). Without args: view. With event: adjust."),
|
|
551
|
-
(handle_cognitive_pin, "nexo_cognitive_pin", "Pin a memory — never decays, boosted +0.2 in search results."),
|
|
552
|
-
(handle_cognitive_snooze, "nexo_cognitive_snooze", "Snooze a memory — hidden from searches until a date, then auto-restores."),
|
|
553
|
-
(handle_cognitive_archive, "nexo_cognitive_archive", "Archive a memory — excluded from searches, can be restored."),
|
|
554
|
-
(handle_cognitive_restore, "nexo_cognitive_restore", "Restore a memory to active state (from pinned/snoozed/archived)."),
|
|
555
|
-
(handle_cognitive_quarantine_list, "nexo_cognitive_quarantine_list", "List quarantine queue items awaiting promotion to STM."),
|
|
556
|
-
(handle_cognitive_quarantine_promote, "nexo_cognitive_quarantine_promote", "Manually promote a quarantine item to STM."),
|
|
557
|
-
(handle_cognitive_quarantine_reject, "nexo_cognitive_quarantine_reject", "Manually reject a quarantine item."),
|
|
558
|
-
(handle_cognitive_quarantine_process, "nexo_cognitive_quarantine_process", "Run quarantine promotion cycle — evaluate pending items against policy."),
|
|
559
|
-
(handle_cognitive_trigger_create, "nexo_cognitive_trigger_create", "Create a prospective memory trigger — 'when X is mentioned, remind about Y'."),
|
|
560
|
-
(handle_cognitive_trigger_list, "nexo_cognitive_trigger_list", "List prospective triggers by status (armed/fired/all)."),
|
|
561
|
-
(handle_cognitive_trigger_check, "nexo_cognitive_trigger_check", "Check text against armed triggers. Returns fired triggers with actions."),
|
|
562
|
-
(handle_cognitive_trigger_delete, "nexo_cognitive_trigger_delete", "Delete a prospective trigger by ID."),
|
|
563
|
-
(handle_cognitive_trigger_rearm, "nexo_cognitive_trigger_rearm", "Re-arm a fired trigger so it can fire again."),
|
|
564
|
-
]
|