nexo-brain 7.20.17 → 7.20.19

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": "7.20.14",
3
+ "version": "7.20.19",
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,11 @@
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.20.17` is the current packaged-runtime line. Patch release over v7.20.16validated DB backups now tolerate tiny live-write growth from the Local Memory indexer while still rejecting real protected-table loss.
21
+ Version `7.20.19` is the current packaged-runtime line. Patch release over v7.20.18Local Memory status and long first-indexing runs stay stable during Desktop-managed updates; stale macOS Full Disk Access denials are cleared after a live access probe succeeds.
22
+
23
+ Previously in `7.20.18`: patch release over v7.20.17 — Desktop-managed setup now preserves a completed onboarding flag when Brain is later invoked with the non-interactive `--skip` bootstrap path.
24
+
25
+ Previously in `7.20.17`: patch release over v7.20.16 — validated DB backups now tolerate tiny live-write growth from the Local Memory indexer while still rejecting real protected-table loss.
22
26
 
23
27
  Previously in `7.20.16`: patch release over v7.20.15 — packaged updates keep the `local_context` runtime shim importable and rollback code-tree snapshots safely when compatibility directories are symlinks.
24
28
 
package/bin/nexo-brain.js CHANGED
@@ -3551,6 +3551,13 @@ async function runSetup() {
3551
3551
  },
3552
3552
  };
3553
3553
 
3554
+ const existingCalibrationRecord = readRuntimeCalibration(NEXO_HOME);
3555
+ const existingCalibrationPayload = existingCalibrationRecord.payload || {};
3556
+ const existingCalibrationMeta = existingCalibrationPayload.meta && typeof existingCalibrationPayload.meta === "object"
3557
+ ? existingCalibrationPayload.meta
3558
+ : {};
3559
+ const preserveExistingOnboardingCompletion = useDefaults && isOnboardingComplete(existingCalibrationPayload);
3560
+ const onboardingCompletedAt = new Date().toISOString();
3554
3561
  const existingIdentity = resolveExistingIdentityDefaults(NEXO_HOME);
3555
3562
 
3556
3563
  // Detect language from input or use default
@@ -3695,8 +3702,10 @@ async function runSetup() {
3695
3702
  // lives in the renderer. Marking it complete here used to short-
3696
3703
  // circuit that wizard and leave new users staring at an empty chat
3697
3704
  // (Inma 2026-05-03 smoke install).
3698
- onboarding_completed: !useDefaults,
3699
- onboarding_completed_at: !useDefaults ? new Date().toISOString() : null,
3705
+ onboarding_completed: preserveExistingOnboardingCompletion ? true : !useDefaults,
3706
+ onboarding_completed_at: preserveExistingOnboardingCompletion
3707
+ ? (existingCalibrationMeta.onboarding_completed_at || onboardingCompletedAt)
3708
+ : (!useDefaults ? onboardingCompletedAt : null),
3700
3709
  },
3701
3710
  auto_install: "ask", // updated later if user answers P11
3702
3711
  calibrated_at: new Date().toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "7.20.17",
3
+ "version": "7.20.19",
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/cli.py CHANGED
@@ -1389,6 +1389,17 @@ def _local_context_models(args) -> int:
1389
1389
  return _local_context_emit(local_context.model_status(), args)
1390
1390
 
1391
1391
 
1392
+ def _local_context_performance(args) -> int:
1393
+ import local_context
1394
+ command = str(getattr(args, "local_context_performance_command", "") or "status")
1395
+ if command == "set":
1396
+ return _local_context_emit(
1397
+ local_context.set_performance_profile(getattr(args, "profile", "") or "medium"),
1398
+ args,
1399
+ )
1400
+ return _local_context_emit({"ok": True, "performance": local_context.performance_config()}, args)
1401
+
1402
+
1392
1403
  def _local_context_service_config(args) -> int:
1393
1404
  from local_context import api as local_context_api
1394
1405
  return _local_context_emit(
@@ -3238,6 +3249,14 @@ def main():
3238
3249
  local_context_models_warmup_p.add_argument("--allow-download", action="store_true", help="Allow model downloads")
3239
3250
  local_context_models_warmup_p.add_argument("--json", action="store_true", help="JSON output")
3240
3251
 
3252
+ local_context_performance_p = local_context_sub.add_parser("performance", help="Show or change local memory indexing speed")
3253
+ local_context_performance_sub = local_context_performance_p.add_subparsers(dest="local_context_performance_command")
3254
+ local_context_performance_status_p = local_context_performance_sub.add_parser("status", help="Show active indexing speed")
3255
+ local_context_performance_status_p.add_argument("--json", action="store_true", help="JSON output")
3256
+ local_context_performance_set_p = local_context_performance_sub.add_parser("set", help="Set indexing speed")
3257
+ local_context_performance_set_p.add_argument("profile", choices=["low", "medium", "high", "extreme"], help="Indexing speed profile")
3258
+ local_context_performance_set_p.add_argument("--json", action="store_true", help="JSON output")
3259
+
3241
3260
  local_context_asset_p = local_context_sub.add_parser("asset", help="Inspect or purge one indexed asset")
3242
3261
  local_context_asset_sub = local_context_asset_p.add_subparsers(dest="local_context_asset_command")
3243
3262
  local_context_asset_get_p = local_context_asset_sub.add_parser("get", help="Get indexed asset details")
@@ -3784,6 +3803,10 @@ def main():
3784
3803
  if not args.local_context_models_command:
3785
3804
  args.local_context_models_command = "status"
3786
3805
  return _local_context_models(args)
3806
+ if args.local_context_command == "performance":
3807
+ if not args.local_context_performance_command:
3808
+ args.local_context_performance_command = "status"
3809
+ return _local_context_performance(args)
3787
3810
  if args.local_context_command == "asset":
3788
3811
  if not args.local_context_asset_command:
3789
3812
  local_context_asset_p.print_help()
@@ -311,7 +311,7 @@
311
311
  "recovery_policy": "restart",
312
312
  "idempotent": true,
313
313
  "max_catchup_age": 600,
314
- "stuck_after_seconds": 900,
314
+ "stuck_after_seconds": 21600,
315
315
  "run_on_boot": true,
316
316
  "run_on_wake": true
317
317
  },
@@ -566,6 +566,14 @@ def detect_full_disk_access_reasons(*, system: str | None = None) -> list[str]:
566
566
  if system != "Darwin":
567
567
  return []
568
568
 
569
+ try:
570
+ probe = probe_full_disk_access()
571
+ if probe.get("granted") is True:
572
+ clear_full_disk_access_required_state()
573
+ return []
574
+ except Exception:
575
+ pass
576
+
569
577
  reasons: list[str] = []
570
578
  if _is_protected_macos_path(NEXO_HOME):
571
579
  reasons.append(
@@ -14,13 +14,26 @@ mkdir -p "$BACKUP_DIR" "$WEEKLY_DIR"
14
14
 
15
15
  # Hourly backup
16
16
  TIMESTAMP=$(date +%Y-%m-%d-%H%M)
17
- sqlite3 "$DB" ".backup '$BACKUP_DIR/nexo-$TIMESTAMP.db'"
17
+ BACKUP_FILE="$BACKUP_DIR/nexo-$TIMESTAMP.db"
18
+ TMP_BACKUP="$BACKUP_FILE.tmp.$$"
19
+ rm -f "$TMP_BACKUP"
20
+ if sqlite3 -cmd ".timeout 60000" "$DB" <<SQL
21
+ PRAGMA busy_timeout=60000;
22
+ .backup '$TMP_BACKUP'
23
+ SQL
24
+ then
25
+ mv "$TMP_BACKUP" "$BACKUP_FILE"
26
+ else
27
+ rm -f "$TMP_BACKUP"
28
+ echo "NEXO backup failed: database busy or unavailable" >&2
29
+ exit 1
30
+ fi
18
31
 
19
32
  # Weekly backup — save one per week (Sundays)
20
33
  WEEK=$(date +%Y-W%V)
21
34
  WEEKLY_FILE="$WEEKLY_DIR/weekly-$WEEK.db"
22
- if [ ! -f "$WEEKLY_FILE" ] && [ "$(date +%u)" = "7" ]; then
23
- cp "$BACKUP_DIR/nexo-$TIMESTAMP.db" "$WEEKLY_FILE"
35
+ if [ ! -f "$WEEKLY_FILE" ] && [ "$(date +%u)" = "7" ] && [ -f "$BACKUP_FILE" ]; then
36
+ cp "$BACKUP_FILE" "$WEEKLY_FILE"
24
37
  fi
25
38
 
26
39
  # Cleanup: hourly >48h, weekly >90 days
@@ -3,7 +3,7 @@
3
3
  # nexo: description=Cooperative local memory indexing cycle for Brain/Desktop.
4
4
  # nexo: category=memory
5
5
  # nexo: runtime=python
6
- # nexo: timeout=900
6
+ # nexo: timeout=21600
7
7
  # nexo: cron_id=local-index
8
8
  # nexo: interval_seconds=60
9
9
  # nexo: schedule_required=true
@@ -12,6 +12,7 @@
12
12
  # nexo: run_on_wake=true
13
13
  # nexo: idempotent=true
14
14
  # nexo: max_catchup_age=600
15
+ # nexo: stuck_after_seconds=21600
15
16
  # nexo: doctor_allow_db=true
16
17
 
17
18
  from __future__ import annotations