nexo-brain 5.4.7 → 5.4.9

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "5.4.7",
3
+ "version": "5.4.9",
4
4
  "description": "Local cognitive runtime for Claude Code \u2014 persistent memory, overnight learning, doctor diagnostics, personal scripts, recovery-aware jobs, startup preflight, and optional dashboard/power helper.",
5
5
  "author": {
6
6
  "name": "NEXO Brain",
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  [Watch the overview video](https://nexo-brain.com/watch/) · [Watch on YouTube](https://www.youtube.com/watch?v=i2lkGhKyVqI) · [Open the infographic](https://nexo-brain.com/assets/nexo-brain-infographic-v5.png)
20
20
 
21
- Version `5.4.7` is the current packaged-runtime line: tool-enforcement-map.json for Protocol Enforcer — canonical map of all 247 tools with enforcement metadata, plus verify script.
21
+ Version `5.4.9` is the current packaged-runtime line: headless Protocol Enforcer — all crons get enforcement rules automatically.
22
22
 
23
23
  Previously in `5.4.6`: runtime dependency management in `nexo update` + daily auto-update cron.
24
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "5.4.7",
3
+ "version": "5.4.9",
4
4
  "mcpName": "io.github.wazionapps/nexo",
5
5
  "description": "NEXO Brain — Shared brain for AI agents. Persistent memory, semantic RAG, natural forgetting, metacognitive guard, trust scoring, 150+ MCP tools. Works with Claude Code, Codex, Claude Desktop & any MCP client. 100% local, free.",
6
6
  "homepage": "https://nexo-brain.com",
@@ -61,7 +61,11 @@
61
61
  "postinstall": "node bin/postinstall.js"
62
62
  },
63
63
  "runtimeDependencies": [
64
- {"name": "@anthropic-ai/claude-code", "type": "npm-global", "optional": false}
64
+ {
65
+ "name": "@anthropic-ai/claude-code",
66
+ "type": "npm-global",
67
+ "optional": false
68
+ }
65
69
  ],
66
70
  "engines": {
67
71
  "node": ">=18"
@@ -56,7 +56,6 @@ class TerminalClientUnavailableError(AgentRunnerError):
56
56
  class AutomationBackendUnavailableError(AgentRunnerError):
57
57
  """Raised when the configured automation backend is unavailable."""
58
58
 
59
-
60
59
  def _canonical_pricing_model(model: str) -> str:
61
60
  lowered = str(model or "").strip().lower()
62
61
  lowered = lowered.split("[", 1)[0]
@@ -533,6 +532,63 @@ def _build_codex_prompt(
533
532
  return prompt
534
533
 
535
534
 
535
+ def _build_enforcement_system_prompt() -> str:
536
+ """Build a system prompt fragment from tool-enforcement-map.json for headless sessions.
537
+
538
+ Reads the map and generates concise enforcement rules that the model must follow.
539
+ Only includes 'must' and 'should' level tools — 'none' tools are omitted.
540
+ """
541
+ map_path = NEXO_HOME / "tool-enforcement-map.json"
542
+ if not map_path.exists():
543
+ for candidate in [
544
+ Path(__file__).parent.parent / "tool-enforcement-map.json",
545
+ ]:
546
+ if candidate.exists():
547
+ map_path = candidate
548
+ break
549
+ else:
550
+ return ""
551
+ try:
552
+ data = json.loads(map_path.read_text())
553
+ except Exception:
554
+ return ""
555
+
556
+ lines = ["[PROTOCOL ENFORCEMENT — these rules are mandatory]"]
557
+ must_rules = []
558
+ should_rules = []
559
+
560
+ for tool_name, tool in data.get("tools", {}).items():
561
+ enf = tool.get("enforcement", {})
562
+ level = enf.get("level", "none")
563
+ if level == "none":
564
+ continue
565
+ rules = enf.get("rules", [])
566
+ rule_descs = [r.get("description", "") for r in rules if r.get("description")]
567
+ notes = enf.get("notes", "")
568
+ if rule_descs:
569
+ desc = f"{tool_name}: {'; '.join(rule_descs)}"
570
+ elif notes:
571
+ desc = f"{tool_name}: {notes[:120]}"
572
+ else:
573
+ rule_types = [r.get("type", "") for r in rules]
574
+ desc = f"{tool_name} ({', '.join(rule_types)})" if rule_types else tool_name
575
+ if level == "must":
576
+ must_rules.append(desc)
577
+ elif level == "should":
578
+ should_rules.append(desc)
579
+
580
+ if must_rules:
581
+ lines.append("MUST (violation creates protocol debt):")
582
+ for r in must_rules:
583
+ lines.append(f" - {r}")
584
+ if should_rules:
585
+ lines.append("SHOULD (recommended, check if relevant):")
586
+ for r in should_rules:
587
+ lines.append(f" - {r}")
588
+
589
+ return "\n".join(lines) if (must_rules or should_rules) else ""
590
+
591
+
536
592
  def run_automation_prompt(
537
593
  prompt: str,
538
594
  *,
@@ -562,6 +618,13 @@ def run_automation_prompt(
562
618
  reasoning_effort = profile["reasoning_effort"]
563
619
  selected_backend = _resolve_available_backend(selected_backend, preferences=prefs)
564
620
 
621
+ enforcement_fragment = _build_enforcement_system_prompt()
622
+ if enforcement_fragment:
623
+ if append_system_prompt:
624
+ append_system_prompt = append_system_prompt + "\n\n" + enforcement_fragment
625
+ else:
626
+ append_system_prompt = enforcement_fragment
627
+
565
628
  cwd_path = Path(cwd).expanduser().resolve() if cwd else Path.cwd()
566
629
  run_env = _headless_env(env)
567
630
  extra_args = list(extra_args or [])