nexo-brain 7.30.33 → 7.31.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 +3 -1
- package/bin/nexo-brain.js +1 -1
- package/package.json +1 -1
- package/src/auto_update.py +2 -2
- package/src/client_sync.py +1 -1
- package/src/model_defaults.json +4 -4
- package/src/model_defaults.py +5 -5
- package/src/resonance_tiers.json +4 -4
- package/src/scripts/nexo-learning-housekeep.py +15 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.31.0",
|
|
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,9 @@
|
|
|
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 `7.
|
|
21
|
+
Version `7.31.0` is the current packaged-runtime line. Minor release over v7.30.33 - the recommended Claude Code model moves from Opus 4.8 to Fable 5 with max reasoning (`claude-fable-5`) across all four main resonance tiers (the `muy_bajo` tier keeps Haiku for cheap internal classifiers and Codex stays on GPT-5.5), existing installs riding NEXO defaults auto-migrate on update while customized models are respected, and learning housekeeping no longer aborts when the embedding backend is missing.
|
|
22
|
+
|
|
23
|
+
Previously in `7.30.33`: patch release over v7.30.32 - personal agent/script status now keeps the newest real run between manual executions and cron history, so a successful manual agent run cannot be hidden behind an older scheduled failure.
|
|
22
24
|
|
|
23
25
|
Previously in `7.30.32`: patch release over v7.30.31 - packaged update/doctor now repair npm/npx wrapper drift, archive stale personal script backups, validate observable automation health contracts, and block legacy Claude/Codex project memory writes.
|
|
24
26
|
|
package/bin/nexo-brain.js
CHANGED
|
@@ -115,7 +115,7 @@ const PUBLIC_CONTRIBUTION_UPSTREAM = "wazionapps/nexo";
|
|
|
115
115
|
const MODEL_DEFAULTS_PATH = path.join(__dirname, "..", "src", "model_defaults.json");
|
|
116
116
|
function _loadModelDefaults() {
|
|
117
117
|
const fallback = {
|
|
118
|
-
claude_code: { model: "claude-
|
|
118
|
+
claude_code: { model: "claude-fable-5", reasoning_effort: "max", display_name: "Fable 5 with max reasoning" },
|
|
119
119
|
codex: { model: "gpt-5.5", reasoning_effort: "xhigh", display_name: "GPT-5.5 with max reasoning" },
|
|
120
120
|
};
|
|
121
121
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.31.0",
|
|
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",
|
package/src/auto_update.py
CHANGED
|
@@ -2058,7 +2058,7 @@ def _refresh_resonance_tiers_model_defaults(dest: Path = NEXO_HOME) -> list[str]
|
|
|
2058
2058
|
dest / "personal" / "brain" / "resonance_tiers.json",
|
|
2059
2059
|
dest / "brain" / "resonance_tiers.json",
|
|
2060
2060
|
]
|
|
2061
|
-
old_prefixes = ("claude-opus-4-6", "claude-opus-4-7")
|
|
2061
|
+
old_prefixes = ("claude-opus-4-6", "claude-opus-4-7", "claude-opus-4-8")
|
|
2062
2062
|
|
|
2063
2063
|
for target_path in target_paths:
|
|
2064
2064
|
try:
|
|
@@ -2089,7 +2089,7 @@ def _refresh_resonance_tiers_model_defaults(dest: Path = NEXO_HOME) -> list[str]
|
|
|
2089
2089
|
model = str(claude.get("model") or "").strip()
|
|
2090
2090
|
tier_changed = False
|
|
2091
2091
|
if model and model.startswith(old_prefixes):
|
|
2092
|
-
claude["model"] = str(source_claude.get("model") or "claude-
|
|
2092
|
+
claude["model"] = str(source_claude.get("model") or "claude-fable-5")
|
|
2093
2093
|
tier_changed = True
|
|
2094
2094
|
if tier_changed and not str(claude.get("effort") or "").strip() and source_claude.get("effort"):
|
|
2095
2095
|
claude["effort"] = str(source_claude.get("effort"))
|
package/src/client_sync.py
CHANGED
|
@@ -83,7 +83,7 @@ except Exception:
|
|
|
83
83
|
|
|
84
84
|
def resolve_client_runtime_profile(client: str, preferences: dict | None = None) -> dict:
|
|
85
85
|
defaults = {
|
|
86
|
-
"claude_code": {"model": "claude-
|
|
86
|
+
"claude_code": {"model": "claude-fable-5", "reasoning_effort": "max"},
|
|
87
87
|
"codex": {"model": "gpt-5.5", "reasoning_effort": "xhigh"},
|
|
88
88
|
}
|
|
89
89
|
return dict(defaults.get(client, {}))
|
package/src/model_defaults.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"claude_code": {
|
|
4
|
-
"model": "claude-
|
|
4
|
+
"model": "claude-fable-5",
|
|
5
5
|
"reasoning_effort": "max",
|
|
6
|
-
"display_name": "
|
|
7
|
-
"recommendation_version":
|
|
8
|
-
"previous_defaults": ["claude-opus-4-7[1m]", "claude-opus-4-7", "claude-opus-4-6[1m]"]
|
|
6
|
+
"display_name": "Fable 5 with max reasoning",
|
|
7
|
+
"recommendation_version": 4,
|
|
8
|
+
"previous_defaults": ["claude-opus-4-8", "claude-opus-4-7[1m]", "claude-opus-4-7", "claude-opus-4-6[1m]"]
|
|
9
9
|
},
|
|
10
10
|
"codex": {
|
|
11
11
|
"model": "gpt-5.5",
|
package/src/model_defaults.py
CHANGED
|
@@ -20,11 +20,11 @@ from typing import Any
|
|
|
20
20
|
_FALLBACK: dict[str, Any] = {
|
|
21
21
|
"schema_version": 1,
|
|
22
22
|
"claude_code": {
|
|
23
|
-
"model": "claude-
|
|
23
|
+
"model": "claude-fable-5",
|
|
24
24
|
"reasoning_effort": "max",
|
|
25
|
-
"display_name": "
|
|
26
|
-
"recommendation_version":
|
|
27
|
-
"previous_defaults": ["claude-opus-4-7[1m]", "claude-opus-4-7", "claude-opus-4-6[1m]"],
|
|
25
|
+
"display_name": "Fable 5 with max reasoning",
|
|
26
|
+
"recommendation_version": 4,
|
|
27
|
+
"previous_defaults": ["claude-opus-4-8", "claude-opus-4-7[1m]", "claude-opus-4-7", "claude-opus-4-6[1m]"],
|
|
28
28
|
},
|
|
29
29
|
"codex": {
|
|
30
30
|
"model": "gpt-5.5",
|
|
@@ -99,7 +99,7 @@ def looks_like_claude_model(model: str) -> bool:
|
|
|
99
99
|
return str(model or "").strip().lower().startswith(_CLAUDE_MODEL_PREFIXES)
|
|
100
100
|
|
|
101
101
|
|
|
102
|
-
_CLAUDE_DEFAULT_PREFIXES = ("claude-opus-4-6", "claude-opus-4-7")
|
|
102
|
+
_CLAUDE_DEFAULT_PREFIXES = ("claude-opus-4-6", "claude-opus-4-7", "claude-opus-4-8")
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
def heal_runtime_profiles(profiles: dict) -> tuple[dict, list[str]]:
|
package/src/resonance_tiers.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"tiers": {
|
|
3
3
|
"maximo": {
|
|
4
|
-
"claude_code": { "model": "claude-
|
|
4
|
+
"claude_code": { "model": "claude-fable-5", "effort": "max" },
|
|
5
5
|
"codex": { "model": "gpt-5.5", "effort": "xhigh" }
|
|
6
6
|
},
|
|
7
7
|
"alto": {
|
|
8
|
-
"claude_code": { "model": "claude-
|
|
8
|
+
"claude_code": { "model": "claude-fable-5", "effort": "xhigh" },
|
|
9
9
|
"codex": { "model": "gpt-5.5", "effort": "high" }
|
|
10
10
|
},
|
|
11
11
|
"medio": {
|
|
12
|
-
"claude_code": { "model": "claude-
|
|
12
|
+
"claude_code": { "model": "claude-fable-5", "effort": "high" },
|
|
13
13
|
"codex": { "model": "gpt-5.5", "effort": "medium" }
|
|
14
14
|
},
|
|
15
15
|
"bajo": {
|
|
16
|
-
"claude_code": { "model": "claude-
|
|
16
|
+
"claude_code": { "model": "claude-fable-5", "effort": "medium" },
|
|
17
17
|
"codex": { "model": "gpt-5.5", "effort": "low" }
|
|
18
18
|
},
|
|
19
19
|
"muy_bajo": {
|
|
@@ -158,10 +158,21 @@ def detect_duplicates(conn):
|
|
|
158
158
|
if len(learnings) < 2:
|
|
159
159
|
return []
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
# build_fastembed_embedding() lazily imports fastembed inside its body, so a
|
|
162
|
+
# missing backend raises ModuleNotFoundError HERE, not at the import guard
|
|
163
|
+
# above (which only resolves the helper symbol). Without this guard the whole
|
|
164
|
+
# housekeeping run crashes with exit 1 whenever there are >=2 learnings to
|
|
165
|
+
# compare and fastembed is absent. Degrade exactly like the "not available"
|
|
166
|
+
# branch instead of aborting decay/prioritization/archival.
|
|
167
|
+
try:
|
|
168
|
+
model = build_fastembed_embedding("bge-base-embeddings")
|
|
169
|
+
texts = [f"{l['title']}: {l['content'][:300]}" for l in learnings]
|
|
170
|
+
embeddings = list(model.embed(texts))
|
|
171
|
+
embeddings = np.array(embeddings)
|
|
172
|
+
except Exception as exc:
|
|
173
|
+
print(f"[{ts}] Dedup skipped: embedding backend unavailable "
|
|
174
|
+
f"({type(exc).__name__}: {exc})")
|
|
175
|
+
return []
|
|
165
176
|
|
|
166
177
|
# Normalize
|
|
167
178
|
norms = np.linalg.norm(embeddings, axis=1, keepdims=True)
|