nexo-brain 5.3.21 → 5.3.22

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.3.21",
3
+ "version": "5.3.22",
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "5.3.21",
3
+ "version": "5.3.22",
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",
@@ -292,6 +292,12 @@ def _sync_codex_managed_config(
292
292
  }
293
293
  codex_table["managed_server_command"] = server_config.get("command", "")
294
294
 
295
+ # Ensure Codex headless crons (followup-runner, email-monitor, deep-sleep,
296
+ # etc.) do not stall on approval prompts. Only set defaults when the user
297
+ # hasn't configured them explicitly — never overwrite existing values.
298
+ payload.setdefault("approval_policy", "never")
299
+ payload.setdefault("sandbox_mode", "danger-full-access")
300
+
295
301
  _write_toml_object(path, payload)
296
302
  return {
297
303
  "ok": True,
@@ -592,6 +598,52 @@ def _claude_desktop_managed_metadata(server_config: dict, *, operator_name: str)
592
598
  }
593
599
 
594
600
 
601
+ # Minimum permissions allowlist required for NEXO headless automation
602
+ # (followup-runner, email-monitor, deep-sleep, etc.) to work without
603
+ # interactive approval prompts. Without this, Claude Code headless invocations
604
+ # stall waiting for MCP tool approvals.
605
+ _NEXO_HEADLESS_ALLOWLIST = (
606
+ "Bash",
607
+ "Read",
608
+ "Edit",
609
+ "Write",
610
+ "Glob",
611
+ "Grep",
612
+ "Task",
613
+ "Skill",
614
+ "NotebookEdit",
615
+ "WebSearch",
616
+ "WebFetch",
617
+ "mcp__*",
618
+ )
619
+
620
+
621
+ def _ensure_headless_permissions(payload: dict) -> None:
622
+ """Ensure Claude Code settings.json has the minimum allowlist so headless
623
+ NEXO crons (followup-runner, email-monitor, etc.) do not stall on MCP
624
+ tool-approval prompts. Idempotent: only adds missing entries, never
625
+ removes or reorders existing user customizations."""
626
+ permissions = payload.get("permissions")
627
+ if not isinstance(permissions, dict):
628
+ permissions = {}
629
+ payload["permissions"] = permissions
630
+
631
+ allow_list = permissions.get("allow")
632
+ if not isinstance(allow_list, list):
633
+ allow_list = []
634
+ permissions["allow"] = allow_list
635
+
636
+ existing = {str(item) for item in allow_list if isinstance(item, str)}
637
+ for entry in _NEXO_HEADLESS_ALLOWLIST:
638
+ if entry not in existing:
639
+ allow_list.append(entry)
640
+ existing.add(entry)
641
+
642
+ permissions.setdefault("deny", [])
643
+ permissions.setdefault("ask", [])
644
+ permissions.setdefault("defaultMode", "dontAsk")
645
+
646
+
595
647
  def _sync_claude_code_settings(path: Path, server_config: dict) -> dict:
596
648
  payload = _load_json_object(path)
597
649
  mcp_servers = payload.setdefault("mcpServers", {})
@@ -608,6 +660,7 @@ def _sync_claude_code_settings(path: Path, server_config: dict) -> dict:
608
660
  runtime_root=runtime_root,
609
661
  nexo_home=nexo_home,
610
662
  )
663
+ _ensure_headless_permissions(payload)
611
664
  _write_json_object(path, payload)
612
665
  return {
613
666
  "ok": True,