nexo-brain 3.1.5 → 3.1.6

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": "3.1.5",
3
+ "version": "3.1.6",
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": "3.1.5",
3
+ "version": "3.1.6",
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",
@@ -284,7 +284,14 @@ def _find_similar_followup(description: str, threshold: float = 0.58) -> dict |
284
284
  return candidates[0]
285
285
 
286
286
 
287
- def _touch_existing_followup(existing: dict, *, description: str, date: str = "", reasoning_note: str = "") -> dict:
287
+ def _touch_existing_followup(
288
+ existing: dict,
289
+ *,
290
+ description: str,
291
+ date: str = "",
292
+ reasoning_note: str = "",
293
+ status: str = "",
294
+ ) -> dict:
288
295
  cols = _table_columns(NEXO_DB, "followups")
289
296
  if not cols:
290
297
  return {"success": False, "error": "followups table not found"}
@@ -296,6 +303,9 @@ def _touch_existing_followup(existing: dict, *, description: str, date: str = ""
296
303
  preferred_date = _prefer_due_date(existing.get("date", ""), date)
297
304
  if preferred_date and preferred_date != str(existing.get("date", "") or "") and "date" in cols:
298
305
  updates["date"] = preferred_date
306
+ desired_status = (status or "").strip()
307
+ if desired_status and "status" in cols and desired_status != str(existing.get("status", "") or ""):
308
+ updates["status"] = desired_status
299
309
  note = reasoning_note or "Deep Sleep matched this followup semantically."
300
310
  changed = False
301
311
  if updates:
@@ -503,19 +513,23 @@ def add_learning(category: str, title: str, content: str) -> dict:
503
513
  return {"success": False, "error": str(e)}
504
514
 
505
515
 
506
- def create_followup(description: str, date: str = "", reasoning_note: str = "") -> dict:
516
+ def create_followup(description: str, date: str = "", reasoning_note: str = "", status: str = "PENDING") -> dict:
507
517
  """Create a followup in nexo.db. Returns result dict."""
508
518
  if not NEXO_DB.exists():
509
519
  return {"success": False, "error": "nexo.db not found"}
510
520
  try:
511
- matched = _find_similar_followup(description)
512
- if matched:
513
- return _touch_existing_followup(
514
- matched,
515
- description=description,
516
- date=date,
517
- reasoning_note=reasoning_note or "Deep Sleep matched this followup semantically.",
518
- )
521
+ desired_status = (status or "PENDING").strip() or "PENDING"
522
+ is_abandoned = description.strip().startswith("[Abandoned]")
523
+ if not is_abandoned:
524
+ matched = _find_similar_followup(description)
525
+ if matched:
526
+ return _touch_existing_followup(
527
+ matched,
528
+ description=description,
529
+ date=date,
530
+ reasoning_note=reasoning_note or "Deep Sleep matched this followup semantically.",
531
+ status=desired_status,
532
+ )
519
533
 
520
534
  # Generate a deterministic ID
521
535
  fid = "NF-DS-" + hashlib.md5(description.encode()).hexdigest()[:8].upper()
@@ -526,6 +540,7 @@ def create_followup(description: str, date: str = "", reasoning_note: str = "")
526
540
  description=description,
527
541
  date=date,
528
542
  reasoning_note=reasoning_note or "Deep Sleep revisited this deterministic followup.",
543
+ status=desired_status,
529
544
  )
530
545
 
531
546
  followup_result = nexo_db.create_followup(
@@ -533,11 +548,18 @@ def create_followup(description: str, date: str = "", reasoning_note: str = "")
533
548
  description=description,
534
549
  date=date or None,
535
550
  verification="",
551
+ status=desired_status,
536
552
  reasoning=reasoning_note or "Deep Sleep v2 overnight analysis",
537
553
  recurrence=None,
538
554
  )
539
555
  if followup_result.get("error"):
540
556
  return {"success": False, "error": followup_result["error"]}
557
+ if desired_status != "PENDING":
558
+ nexo_db.add_followup_note(
559
+ fid,
560
+ f"Deep Sleep created this followup directly as {desired_status}.",
561
+ actor="deep-sleep",
562
+ )
541
563
  return {"success": True, "id": fid, "outcome": "new_followup"}
542
564
  except Exception as e:
543
565
  return {"success": False, "error": str(e)}
@@ -733,7 +755,9 @@ def create_abandoned_followups(synthesis: dict) -> list[dict]:
733
755
  continue
734
756
  result = create_followup(
735
757
  description=f"[Abandoned] {proj.get('description', '')}",
736
- date="" # No date — it's a discovered gap
758
+ date="", # No date — it's a discovered gap
759
+ reasoning_note="Deep Sleep marked this as abandoned. Keep it as archived history, not active work.",
760
+ status="archived",
737
761
  )
738
762
  results.append(result)
739
763
  return results