nexo-brain 0.8.2 → 0.8.3
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/package.json +1 -1
- package/src/cognitive.py +1 -1
- package/src/plugins/backup.py +2 -2
- package/src/plugins/entities.py +3 -3
- package/src/server.py +7 -7
- package/src/tools_credentials.py +6 -6
- package/src/tools_learnings.py +3 -3
- package/src/tools_menu.py +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
5
|
"description": "NEXO — Cognitive co-operator for Claude Code. Atkinson-Shiffrin memory, semantic RAG, trust scoring, and metacognitive error prevention.",
|
|
6
6
|
"bin": {
|
package/src/cognitive.py
CHANGED
|
@@ -2737,7 +2737,7 @@ def detect_sentiment(text: str) -> dict:
|
|
|
2737
2737
|
elif urgency_hits:
|
|
2738
2738
|
sentiment = "urgent"
|
|
2739
2739
|
intensity = 0.8
|
|
2740
|
-
guidance = "MODE:
|
|
2740
|
+
guidance = "MODE: Immediate action. No preamble."
|
|
2741
2741
|
else:
|
|
2742
2742
|
sentiment = "neutral"
|
|
2743
2743
|
intensity = 0.5
|
package/src/plugins/backup.py
CHANGED
|
@@ -33,10 +33,10 @@ def handle_backup_now() -> str:
|
|
|
33
33
|
def handle_backup_list() -> str:
|
|
34
34
|
"""List available backups with dates and sizes."""
|
|
35
35
|
if not os.path.isdir(BACKUP_DIR):
|
|
36
|
-
return "
|
|
36
|
+
return "No backups found."
|
|
37
37
|
files = sorted(glob.glob(os.path.join(BACKUP_DIR, "nexo-*.db")), reverse=True)
|
|
38
38
|
if not files:
|
|
39
|
-
return "
|
|
39
|
+
return "No backups found."
|
|
40
40
|
lines = [f"BACKUPS ({len(files)}):"]
|
|
41
41
|
total_size = 0
|
|
42
42
|
for f in files:
|
package/src/plugins/entities.py
CHANGED
|
@@ -5,7 +5,7 @@ def handle_entity_search(query: str, type: str = "") -> str:
|
|
|
5
5
|
"""Search entities by name or value. Optional type filter."""
|
|
6
6
|
results = search_entities(query, type)
|
|
7
7
|
if not results:
|
|
8
|
-
return "
|
|
8
|
+
return "No results."
|
|
9
9
|
lines = []
|
|
10
10
|
for e in results:
|
|
11
11
|
notes = f" — {e['notes']}" if e.get("notes") else ""
|
|
@@ -37,14 +37,14 @@ def handle_entity_update(id: int, name: str = "", type: str = "", value: str = "
|
|
|
37
37
|
def handle_entity_delete(id: int) -> str:
|
|
38
38
|
"""Delete an entity."""
|
|
39
39
|
if not delete_entity(id):
|
|
40
|
-
return f"ERROR:
|
|
40
|
+
return f"ERROR: Entity [{id}] not found."
|
|
41
41
|
return f"Entidad [{id}] eliminada."
|
|
42
42
|
|
|
43
43
|
def handle_entity_list(type: str = "") -> str:
|
|
44
44
|
"""List all entities, optionally filtered by type."""
|
|
45
45
|
results = list_entities(type)
|
|
46
46
|
if not results:
|
|
47
|
-
return "
|
|
47
|
+
return "No entities found."
|
|
48
48
|
grouped = {}
|
|
49
49
|
for e in results:
|
|
50
50
|
t = e["type"]
|
package/src/server.py
CHANGED
|
@@ -395,7 +395,7 @@ def nexo_index_add_dir(path: str, dir_type: str = "code",
|
|
|
395
395
|
result = fts_add_dir(path, dir_type, patterns, notes)
|
|
396
396
|
if "error" in result:
|
|
397
397
|
return f"ERROR: {result['error']}"
|
|
398
|
-
return f"
|
|
398
|
+
return f"Directory registered: {result['path']} ({result['dir_type']}, patterns: {result['patterns']})\nUse nexo_reindex to index now."
|
|
399
399
|
|
|
400
400
|
|
|
401
401
|
@mcp.tool
|
|
@@ -408,7 +408,7 @@ def nexo_index_remove_dir(path: str) -> str:
|
|
|
408
408
|
result = fts_remove_dir(path)
|
|
409
409
|
if "error" in result:
|
|
410
410
|
return f"ERROR: {result['error']}"
|
|
411
|
-
return f"
|
|
411
|
+
return f"Directory removed from index: {result['removed']}"
|
|
412
412
|
|
|
413
413
|
|
|
414
414
|
@mcp.tool
|
|
@@ -416,7 +416,7 @@ def nexo_index_dirs() -> str:
|
|
|
416
416
|
"""List all directories being indexed by FTS5 (builtin + dynamic)."""
|
|
417
417
|
dirs = fts_list_dirs()
|
|
418
418
|
if not dirs:
|
|
419
|
-
return "
|
|
419
|
+
return "No directories configured."
|
|
420
420
|
lines = ["DIRECTORIOS INDEXADOS:"]
|
|
421
421
|
for d in dirs:
|
|
422
422
|
source_tag = "⚙️" if d["source"] == "builtin" else "➕"
|
|
@@ -533,7 +533,7 @@ def nexo_plugin_load(filename: str) -> str:
|
|
|
533
533
|
"""
|
|
534
534
|
try:
|
|
535
535
|
n = load_plugin(mcp, filename)
|
|
536
|
-
return f"Plugin {filename}: {n} tools
|
|
536
|
+
return f"Plugin {filename}: {n} tools registered."
|
|
537
537
|
except Exception as e:
|
|
538
538
|
return f"Error cargando plugin {filename}: {e}"
|
|
539
539
|
|
|
@@ -543,7 +543,7 @@ def nexo_plugin_list() -> str:
|
|
|
543
543
|
"""List all loaded plugins and their tools."""
|
|
544
544
|
plugins = list_plugins()
|
|
545
545
|
if not plugins:
|
|
546
|
-
return "
|
|
546
|
+
return "No plugins loaded."
|
|
547
547
|
lines = ["PLUGINS CARGADOS:"]
|
|
548
548
|
for p in plugins:
|
|
549
549
|
names = p["tool_names"] or "(sin tools)"
|
|
@@ -561,8 +561,8 @@ def nexo_plugin_remove(filename: str) -> str:
|
|
|
561
561
|
try:
|
|
562
562
|
removed = remove_plugin(mcp, filename)
|
|
563
563
|
if removed:
|
|
564
|
-
return f"Plugin {filename}
|
|
565
|
-
return f"Plugin {filename}
|
|
564
|
+
return f"Plugin {filename} removed. Tools unregistered: {', '.join(removed)}"
|
|
565
|
+
return f"Plugin {filename} removed (had no registered tools)."
|
|
566
566
|
except Exception as e:
|
|
567
567
|
return f"Error eliminando plugin {filename}: {e}"
|
|
568
568
|
|
package/src/tools_credentials.py
CHANGED
|
@@ -23,7 +23,7 @@ def handle_credential_create(service: str, key: str, value: str, notes: str = ''
|
|
|
23
23
|
result = create_credential(service, key, value, notes)
|
|
24
24
|
if "error" in result:
|
|
25
25
|
return f"ERROR: {result['error']}"
|
|
26
|
-
return f"
|
|
26
|
+
return f"Credential {service}/{key} created."
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def handle_credential_update(service: str, key: str, value: str = '', notes: str = '') -> str:
|
|
@@ -36,7 +36,7 @@ def handle_credential_update(service: str, key: str, value: str = '', notes: str
|
|
|
36
36
|
)
|
|
37
37
|
if "error" in result:
|
|
38
38
|
return f"ERROR: {result['error']}"
|
|
39
|
-
return f"
|
|
39
|
+
return f"Credential {service}/{key} updated."
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
def handle_credential_delete(service: str, key: str = '') -> str:
|
|
@@ -46,8 +46,8 @@ def handle_credential_delete(service: str, key: str = '') -> str:
|
|
|
46
46
|
target = f"{service}/{key}" if key else service
|
|
47
47
|
return f"ERROR: No se encontraron credenciales para '{target}'."
|
|
48
48
|
if key:
|
|
49
|
-
return f"
|
|
50
|
-
return f"
|
|
49
|
+
return f"Credential {service}/{key} deleted."
|
|
50
|
+
return f"All credentials for {service} deleted."
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def handle_credential_list(service: str = '') -> str:
|
|
@@ -55,8 +55,8 @@ def handle_credential_list(service: str = '') -> str:
|
|
|
55
55
|
results = list_credentials(service if service else None)
|
|
56
56
|
label = service if service else "TODAS"
|
|
57
57
|
if not results:
|
|
58
|
-
return f"
|
|
59
|
-
lines = [f"
|
|
58
|
+
return f"CREDENTIALS {label.upper()}: No entries."
|
|
59
|
+
lines = [f"CREDENTIALS {label.upper()} ({len(results)}):"]
|
|
60
60
|
for r in results:
|
|
61
61
|
notes = r.get("notes") or ""
|
|
62
62
|
suffix = f" — {notes}" if notes else ""
|
package/src/tools_learnings.py
CHANGED
|
@@ -107,7 +107,7 @@ def handle_learning_search(query: str, category: str = '') -> str:
|
|
|
107
107
|
"""Search learnings by query string, optionally filtered by category."""
|
|
108
108
|
results = search_learnings(query, category if category else None)
|
|
109
109
|
if not results:
|
|
110
|
-
return f"
|
|
110
|
+
return f"No results for '{query}'."
|
|
111
111
|
lines = [f"RESULTADOS ({len(results)}):"]
|
|
112
112
|
for r in results:
|
|
113
113
|
snippet = r["content"][:100] + "..." if len(r["content"]) > 100 else r["content"]
|
|
@@ -155,7 +155,7 @@ def handle_learning_update(id: int, title: str = '', content: str = '', category
|
|
|
155
155
|
if review_days > 0:
|
|
156
156
|
kwargs["review_days"] = review_days
|
|
157
157
|
if not kwargs:
|
|
158
|
-
return "ERROR:
|
|
158
|
+
return "ERROR: Nothing to update. Provide new fields."
|
|
159
159
|
basic_kwargs = {k: v for k, v in kwargs.items() if k in {"title", "content", "category", "reasoning"}}
|
|
160
160
|
result = update_learning(id, **basic_kwargs)
|
|
161
161
|
if "error" in result:
|
|
@@ -192,7 +192,7 @@ def handle_learning_list(category: str = '') -> str:
|
|
|
192
192
|
results = list_learnings(category if category else None)
|
|
193
193
|
if not results:
|
|
194
194
|
label = category if category else "TODOS"
|
|
195
|
-
return f"LEARNINGS {label} (0):
|
|
195
|
+
return f"LEARNINGS {label} (0): No entries."
|
|
196
196
|
|
|
197
197
|
if category:
|
|
198
198
|
label = category.upper()
|
package/src/tools_menu.py
CHANGED
|
@@ -101,7 +101,7 @@ def handle_menu() -> str:
|
|
|
101
101
|
dashboard_alerts = _get_dashboard_alerts()
|
|
102
102
|
memory_reviews = _get_memory_review_summary()
|
|
103
103
|
due = handle_reminders("due")
|
|
104
|
-
has_alerts = dashboard_alerts or memory_reviews["total"] > 0 or (due and "
|
|
104
|
+
has_alerts = dashboard_alerts or memory_reviews["total"] > 0 or (due and "No reminders" not in due)
|
|
105
105
|
|
|
106
106
|
if has_alerts:
|
|
107
107
|
lines.append("║" + " PROACTIVE ALERTS".ljust(W) + "║")
|
|
@@ -124,7 +124,7 @@ def handle_menu() -> str:
|
|
|
124
124
|
)[:W - 4]
|
|
125
125
|
lines.append("║" + f" ! {text}".ljust(W) + "║")
|
|
126
126
|
|
|
127
|
-
if due and "
|
|
127
|
+
if due and "No reminders" not in due:
|
|
128
128
|
for reminder_line in due.split("\n"):
|
|
129
129
|
if reminder_line.strip():
|
|
130
130
|
truncated = reminder_line[:W - 2]
|
|
@@ -190,7 +190,7 @@ def handle_menu() -> str:
|
|
|
190
190
|
|
|
191
191
|
# Active sessions
|
|
192
192
|
sessions = handle_status()
|
|
193
|
-
if "
|
|
193
|
+
if "No sessions" not in sessions:
|
|
194
194
|
lines.append("║" + " ACTIVE SESSIONS".ljust(W) + "║")
|
|
195
195
|
lines.append("║" + "─" * W + "║")
|
|
196
196
|
for s_line in sessions.split("\n"):
|