nexo-brain 7.23.7 → 7.23.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "7.23.7",
3
+ "version": "7.23.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",
@@ -832,12 +832,15 @@ def resolve_restart_required(
832
832
  reason = ""
833
833
  client_action = ""
834
834
  marker_clients = dict(marker.get("clients") or {})
835
+ client_acknowledged = False
835
836
  fingerprint_usable = bool(installed_fp) and bool(process_fp) and process_fp != "unknown"
836
837
 
837
838
  if marker.get("required"):
838
- restart_required = True
839
- reason = "marker_required"
840
839
  client_action = str(marker_clients.get(client) or "")
840
+ client_acknowledged = bool(client and client_action == "ok")
841
+ if not client_acknowledged:
842
+ restart_required = True
843
+ reason = "marker_required"
841
844
  if marker.get("corrupt"):
842
845
  restart_required = True
843
846
  reason = "marker_corrupt"
@@ -847,7 +850,12 @@ def resolve_restart_required(
847
850
  # fingerprint change and therefore never reach this branch.
848
851
  restart_required = True
849
852
  reason = reason or "fingerprint_mismatch"
850
- elif marker.get("required") and marker_fp and (not process_fp or process_fp == "unknown"):
853
+ elif (
854
+ marker.get("required")
855
+ and not client_acknowledged
856
+ and marker_fp
857
+ and (not process_fp or process_fp == "unknown")
858
+ ):
851
859
  restart_required = True
852
860
  reason = reason or "process_fingerprint_missing"
853
861
  elif not fingerprint_usable and installed and process and installed != process:
@@ -856,7 +864,7 @@ def resolve_restart_required(
856
864
  # mismatch check so we never leave a stale process running unnoticed.
857
865
  restart_required = True
858
866
  reason = reason or "version_mismatch"
859
- elif client and client_action == "ok":
867
+ elif client_acknowledged:
860
868
  restart_required = False
861
869
  reason = ""
862
870
 
@@ -882,15 +890,28 @@ def _mcp_client_readiness(
882
890
  ) -> dict:
883
891
  generation = runtime_generation(installed_version_value, installed_fp, str(active_runtime_root()))
884
892
  process_fp = str(state.get("process_fingerprint") or "").strip()
893
+ service_fp = str(service_status.get("runtime_fingerprint") or "").strip()
894
+ effective_process_fp = process_fp or service_fp
885
895
  service_ok = bool(service_status.get("ok", True))
886
896
  fingerprint_ready = (
887
897
  bool(installed_fp)
888
- and bool(process_fp)
889
- and process_fp != "unknown"
890
- and installed_fp == process_fp
898
+ and bool(effective_process_fp)
899
+ and effective_process_fp != "unknown"
900
+ and installed_fp == effective_process_fp
901
+ )
902
+ marker_recoverable_reason = str(state.get("reason") or "") in {
903
+ "marker_required",
904
+ "process_fingerprint_missing",
905
+ }
906
+ marker_recoverable_for_client = (
907
+ bool(client)
908
+ and bool(state.get("restart_required"))
909
+ and marker_recoverable_reason
910
+ and fingerprint_ready
911
+ and service_ok
891
912
  )
892
913
  global_ready = (
893
- not bool(state.get("restart_required"))
914
+ (not bool(state.get("restart_required")) or marker_recoverable_for_client)
894
915
  and fingerprint_ready
895
916
  and service_ok
896
917
  )
@@ -898,13 +919,13 @@ def _mcp_client_readiness(
898
919
  global_reason = "runtime_service_unavailable"
899
920
  elif not installed_fp:
900
921
  global_reason = "installed_fingerprint_missing"
901
- elif not process_fp or process_fp == "unknown":
922
+ elif not effective_process_fp or effective_process_fp == "unknown":
902
923
  global_reason = "process_fingerprint_missing"
903
- elif installed_fp != process_fp:
924
+ elif installed_fp != effective_process_fp:
904
925
  global_reason = "process_fingerprint_mismatch"
905
926
  else:
906
927
  global_reason = "ready"
907
- if state.get("restart_required"):
928
+ if state.get("restart_required") and not marker_recoverable_for_client:
908
929
  return {
909
930
  "runtime_generation": generation,
910
931
  "global_ready": False,
@@ -995,6 +1016,11 @@ def build_mcp_status(*, client: str = "") -> dict:
995
1016
  service_status=service_status,
996
1017
  )
997
1018
  client_states = read_mcp_client_states()
1019
+ service_fp = str(service_status.get("runtime_fingerprint") or "").strip()
1020
+ effective_process_fp = process_fp or service_fp
1021
+ restart_required = bool(state["restart_required"]) and not bool(
1022
+ readiness["client_ready"]
1023
+ )
998
1024
  return {
999
1025
  "ok": True,
1000
1026
  "schema_version": MCP_STATUS_SCHEMA_VERSION,
@@ -1005,14 +1031,14 @@ def build_mcp_status(*, client: str = "") -> dict:
1005
1031
  "process_fingerprint": process_fp,
1006
1032
  "fingerprint_match": (
1007
1033
  bool(installed_fp)
1008
- and bool(process_fp)
1009
- and process_fp != "unknown"
1010
- and installed_fp == process_fp
1034
+ and bool(effective_process_fp)
1035
+ and effective_process_fp != "unknown"
1036
+ and installed_fp == effective_process_fp
1011
1037
  ),
1012
1038
  "active_runtime_root": str(active_runtime_root()),
1013
1039
  "active_runtime_version": read_version_for_path(active_runtime_root()),
1014
- "restart_required": bool(state["restart_required"]),
1015
- "reason": state["reason"],
1040
+ "restart_required": restart_required,
1041
+ "reason": state["reason"] if restart_required else "",
1016
1042
  "client_action": readiness["client_action"],
1017
1043
  "reason_code": readiness["reason_code"],
1018
1044
  "global_ready": bool(readiness["global_ready"]),