nexo-brain 7.34.0 → 7.36.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/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/db/_hot_context.py +30 -1
- package/src/db/_schema.py +64 -0
- package/src/deep_sleep_retention.py +8 -0
- package/src/email_sent_events.py +7 -0
- package/src/enforcement_engine.py +58 -0
- package/src/hooks/post_tool_use.py +114 -0
- package/src/local_context/api.py +157 -7
- package/src/local_context/db.py +61 -1
- package/src/memory_forget.py +1249 -0
- package/src/plugins/protocol.py +30 -0
- package/src/plugins/schema_abstraction.py +66 -0
- package/src/schema_abstraction.py +763 -0
- package/src/scripts/nexo-daily-self-audit.py +97 -13
- package/src/server.py +54 -0
- package/src/tools_credentials.py +60 -2
- package/tool-enforcement-map.json +66 -0
package/src/plugins/protocol.py
CHANGED
|
@@ -157,12 +157,42 @@ def _requires_external_real_world_check(task: dict, *parts: str) -> bool:
|
|
|
157
157
|
if str(task.get("task_type") or "").strip() not in ACTION_TASKS:
|
|
158
158
|
return False
|
|
159
159
|
text = _external_real_world_text(task, *parts)
|
|
160
|
+
if _is_local_only_followup_runner_close(task, text):
|
|
161
|
+
return False
|
|
160
162
|
return any(
|
|
161
163
|
_contains_external_action_keyword(text, keyword)
|
|
162
164
|
for keyword in EXTERNAL_REAL_WORLD_ACTION_KEYWORDS
|
|
163
165
|
)
|
|
164
166
|
|
|
165
167
|
|
|
168
|
+
def _is_local_only_followup_runner_close(task: dict, text: str) -> bool:
|
|
169
|
+
area = str(task.get("area") or "").lower()
|
|
170
|
+
goal = str(task.get("goal") or "").lower()
|
|
171
|
+
if "followup-runner" not in f"{area} {goal} {text}":
|
|
172
|
+
return False
|
|
173
|
+
|
|
174
|
+
local_only_markers = (
|
|
175
|
+
"sin envio externo",
|
|
176
|
+
"sin envío externo",
|
|
177
|
+
"no envio externo",
|
|
178
|
+
"no envío externo",
|
|
179
|
+
"no external send",
|
|
180
|
+
"no external delivery",
|
|
181
|
+
"internal followup-runner",
|
|
182
|
+
"followup-runner interna",
|
|
183
|
+
"followup-runner internas",
|
|
184
|
+
"solo lectura db",
|
|
185
|
+
"solo lectura de db",
|
|
186
|
+
"solo lectura bd",
|
|
187
|
+
"solo lectura de bd",
|
|
188
|
+
"archivos locales",
|
|
189
|
+
"local files",
|
|
190
|
+
"db/archivos locales",
|
|
191
|
+
"db/local files",
|
|
192
|
+
)
|
|
193
|
+
return any(marker in text for marker in local_only_markers)
|
|
194
|
+
|
|
195
|
+
|
|
166
196
|
def _has_external_real_world_evidence(text: str) -> bool:
|
|
167
197
|
lowered = str(text or "").lower()
|
|
168
198
|
if _is_trivial_evidence(lowered)[0]:
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Ola 4 — SCHEMA-ABSTRACTION plugin tools.
|
|
2
|
+
|
|
3
|
+
Thin MCP surface over ``schema_abstraction`` (the distiller). Templates are
|
|
4
|
+
non-authoritative GUIDANCE: they prime a complete diagnosis when a recurring
|
|
5
|
+
incident archetype reappears; they never block. Precision-first / anti-noise:
|
|
6
|
+
a template is minted only from a genuinely recurring cluster (>= 3 distinct
|
|
7
|
+
incidents of the same archetype, high confidence).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
import schema_abstraction as sa
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _dump(value) -> str:
|
|
18
|
+
return json.dumps(value, ensure_ascii=False)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def handle_schema_abstraction_distill() -> str:
|
|
22
|
+
"""Run the distillation pass: cluster recurring incidents → mint diagnostic
|
|
23
|
+
templates (idempotent). Safe to re-run; returns a report including anti-noise
|
|
24
|
+
skips (clusters below the recurrence/confidence threshold)."""
|
|
25
|
+
return _dump(sa.distill_templates())
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def handle_schema_abstraction_templates(status: str = "active", limit: int = 50) -> str:
|
|
29
|
+
"""List distilled diagnostic templates."""
|
|
30
|
+
return _dump({"templates": sa.list_templates(status=status, limit=limit)})
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def handle_schema_abstraction_match(query: str = "", area: str = "", limit: int = 1) -> str:
|
|
34
|
+
"""Return the diagnostic template(s) whose archetype clearly matches an
|
|
35
|
+
action (the same match used to prime pre-action context)."""
|
|
36
|
+
return _dump({"matches": sa.match_templates_for_action(query=query, area=area, limit=limit)})
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def handle_schema_abstraction_retire(template_uid: str, reason: str = "") -> str:
|
|
40
|
+
"""Retire a diagnostic template (lifecycle). Guidance-only; never deletes
|
|
41
|
+
the underlying incidents."""
|
|
42
|
+
return _dump(sa.retire_template(template_uid, reason=reason))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
TOOLS = [
|
|
46
|
+
(
|
|
47
|
+
handle_schema_abstraction_distill,
|
|
48
|
+
"nexo_schema_abstraction_distill",
|
|
49
|
+
"Distill recurring incident archetypes into reusable diagnostic templates (idempotent clustering pass)",
|
|
50
|
+
),
|
|
51
|
+
(
|
|
52
|
+
handle_schema_abstraction_templates,
|
|
53
|
+
"nexo_schema_abstraction_templates",
|
|
54
|
+
"List distilled diagnostic templates",
|
|
55
|
+
),
|
|
56
|
+
(
|
|
57
|
+
handle_schema_abstraction_match,
|
|
58
|
+
"nexo_schema_abstraction_match",
|
|
59
|
+
"Match an action against diagnostic-template archetypes (primed diagnosis)",
|
|
60
|
+
),
|
|
61
|
+
(
|
|
62
|
+
handle_schema_abstraction_retire,
|
|
63
|
+
"nexo_schema_abstraction_retire",
|
|
64
|
+
"Retire a diagnostic template (lifecycle, guidance-only)",
|
|
65
|
+
),
|
|
66
|
+
]
|