nexo-brain 2.6.2 → 2.6.4

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": "2.5.1",
3
+ "version": "2.6.3",
4
4
  "description": "Cognitive co-operator — persistent memory, learning, autonomous processes, Deep Sleep overnight analysis, unified diagnostics, executable skills, day orchestrator, and web dashboard for AI agents.",
5
5
  "author": {
6
6
  "name": "NEXO Brain",
package/bin/nexo-brain.js CHANGED
@@ -226,9 +226,11 @@ function registerAllCoreHooks(settings, hooksDir, nexoHome) {
226
226
  // We need to search and update in both formats.
227
227
  let found = false;
228
228
 
229
- for (const entry of settings.hooks[hook.event]) {
229
+ for (let idx = 0; idx < settings.hooks[hook.event].length; idx++) {
230
+ const entry = settings.hooks[hook.event][idx];
230
231
  if (entry.hooks && Array.isArray(entry.hooks)) {
231
232
  // Nested format: {matcher, hooks: [...]}
233
+ if (!entry.matcher) entry.matcher = "*";
232
234
  const subIdx = entry.hooks.findIndex(
233
235
  (h) => h.command && h.command.includes(hook.key)
234
236
  );
@@ -240,19 +242,25 @@ function registerAllCoreHooks(settings, hooksDir, nexoHome) {
240
242
  break;
241
243
  }
242
244
  } else if (entry.command && entry.command.includes(hook.key)) {
243
- // Flat format: {type:"command", command:"..."}
244
- if (entry.command !== command) entry.command = command;
245
- if (hook.timeout && !entry.timeout) entry.timeout = hook.timeout;
245
+ // Legacy flat format: migrate to nested matcher+hooks.
246
+ const migrated = { type: "command", command };
247
+ if (hook.timeout) migrated.timeout = hook.timeout;
248
+ settings.hooks[hook.event][idx] = {
249
+ matcher: "*",
250
+ hooks: [migrated],
251
+ };
246
252
  found = true;
247
253
  break;
248
254
  }
249
255
  }
250
256
 
251
257
  if (!found) {
252
- // Hook missing add it in flat format (Claude Code accepts both)
253
- const newEntry = { type: "command", command };
254
- if (hook.timeout) newEntry.timeout = hook.timeout;
255
- settings.hooks[hook.event].push(newEntry);
258
+ const newHook = { type: "command", command };
259
+ if (hook.timeout) newHook.timeout = hook.timeout;
260
+ settings.hooks[hook.event].push({
261
+ matcher: "*",
262
+ hooks: [newHook],
263
+ });
256
264
  }
257
265
  }
258
266
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
4
4
  "mcpName": "io.github.wazionapps/nexo",
5
5
  "description": "NEXO — Cognitive co-operator for Claude Code. Memory, emotional intelligence, overnight learning (Deep Sleep), personal scripts registry, cron management, trust scoring, managed evolution, and adaptive calibration.",
6
6
  "bin": {
package/src/crons/sync.py CHANGED
@@ -139,6 +139,14 @@ def _copy_into_runtime(src: Path) -> Path:
139
139
  dest = RUNTIME_ROOT / _runtime_relative_path(src)
140
140
  dest.parent.mkdir(parents=True, exist_ok=True)
141
141
 
142
+ try:
143
+ if dest.exists() and src.resolve() == dest.resolve():
144
+ if src.is_file() and (src.suffix in {".sh", ".py"} or os.access(src, os.X_OK)):
145
+ dest.chmod(0o755)
146
+ return dest
147
+ except Exception:
148
+ pass
149
+
142
150
  if src.is_dir():
143
151
  if dest.exists():
144
152
  shutil.rmtree(dest)
@@ -371,7 +379,7 @@ def sync_linux(dry_run: bool = False):
371
379
 
372
380
  manifest_crons = load_manifest()
373
381
  wrapper_src = SOURCE_ROOT / "scripts" / "nexo-cron-wrapper.sh"
374
- wrapper_dest = _copy_script_to_nexo_home(wrapper_src)
382
+ wrapper_dest = _copy_into_runtime(wrapper_src)
375
383
 
376
384
  log(f"Manifest: {len(manifest_crons)} core crons")
377
385
 
@@ -384,14 +392,14 @@ def sync_linux(dry_run: bool = False):
384
392
  for cron in manifest_crons:
385
393
  cron_id = cron["id"]
386
394
  script_src = SOURCE_ROOT / cron["script"]
387
- script_dest = _copy_script_to_nexo_home(script_src)
395
+ script_dest = _copy_into_runtime(script_src)
388
396
  script_type = cron.get("type", "python")
389
397
 
390
398
  # Copy subdirectories
391
399
  subdir_name = script_src.stem.replace("nexo-", "")
392
400
  subdir_src = SOURCE_ROOT / "scripts" / subdir_name
393
401
  if subdir_src.is_dir():
394
- _copy_script_to_nexo_home(subdir_src)
402
+ _copy_into_runtime(subdir_src)
395
403
 
396
404
  if script_type == "shell":
397
405
  exec_cmd = f"/bin/bash {wrapper_dest} {cron_id} /bin/bash {script_dest}"