nexo-brain 7.25.3 → 7.25.5

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.25.1",
3
+ "version": "7.25.5",
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.25.1` is the current packaged-runtime line. Patch release over v7.25.0 - shell guardrails skip non-path curl/wget arguments and daily protocol-debt audits keep ERROR classes visible by severity and type.
21
+ Version `7.25.5` is the current packaged-runtime line. Patch release over v7.25.4 - explicit user-included Local Memory roots can override default system/noisy-tree skips, while Brain LocalIndex operator messages stay in English and Desktop continues to enforce the Core-pinned Python 3.12 runtime.
22
+
23
+ Previously in `7.25.4`: patch release over v7.25.3 - Local Memory starts from safe user-content and email roots, adds configurable included/excluded file types, and cleans legacy whole-disk index state with backup or archive-rebuild safety.
24
+
25
+ Previously in `7.25.3`: patch release over v7.25.2 - Desktop-managed Brain installs require the same Python ABI as the bundled wheels and repair incompatible managed virtual environments before reuse.
22
26
 
23
27
  Previously in `7.25.0`: minor release over v7.24.0 - Memory Fabric links transcript lookup, historical backup diary recovery, unified search and knowledge graph evidence so memories are not available only inside expiring snapshots.
24
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "7.25.3",
3
+ "version": "7.25.5",
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
@@ -1853,6 +1853,42 @@ def _local_context_exclusions(args) -> int:
1853
1853
  return _local_context_emit({"ok": False, "error": f"unsupported exclusions command: {command}"}, args)
1854
1854
 
1855
1855
 
1856
+ def _local_context_filetypes(args) -> int:
1857
+ import local_context
1858
+ command = str(getattr(args, "local_context_filetypes_command", "") or "")
1859
+ if command == "list":
1860
+ return _local_context_emit(local_context.list_file_type_rules(readonly=False), args)
1861
+ if command == "include":
1862
+ return _local_context_emit(
1863
+ local_context.set_file_type_rule(
1864
+ getattr(args, "extension", ""),
1865
+ action=getattr(args, "action", "extract") or "extract",
1866
+ reason=getattr(args, "reason", "user") or "user",
1867
+ ),
1868
+ args,
1869
+ )
1870
+ if command == "exclude":
1871
+ return _local_context_emit(
1872
+ local_context.set_file_type_rule(
1873
+ getattr(args, "extension", ""),
1874
+ action="ignore",
1875
+ reason=getattr(args, "reason", "user") or "user",
1876
+ ),
1877
+ args,
1878
+ )
1879
+ if command == "remove":
1880
+ return _local_context_emit(local_context.remove_file_type_rule(getattr(args, "extension", "")), args)
1881
+ if command == "reset":
1882
+ return _local_context_emit(local_context.reset_file_type_rules(), args)
1883
+ return _local_context_emit({"ok": False, "error": f"unsupported filetypes command: {command}"}, args)
1884
+
1885
+
1886
+ def _local_context_migrate_roots_v2(args) -> int:
1887
+ import local_context
1888
+ dry_run = not bool(getattr(args, "apply", False))
1889
+ return _local_context_emit(local_context.migrate_roots_seed_v2(dry_run=dry_run), args)
1890
+
1891
+
1856
1892
  def _local_context_query(args) -> int:
1857
1893
  import local_context
1858
1894
  return _local_context_emit(
@@ -3759,6 +3795,29 @@ def main():
3759
3795
  local_context_exclusions_remove_p.add_argument("path", help="Folder path")
3760
3796
  local_context_exclusions_remove_p.add_argument("--json", action="store_true", help="JSON output")
3761
3797
 
3798
+ local_context_filetypes_p = local_context_sub.add_parser("filetypes", help="Manage included and excluded file extensions")
3799
+ local_context_filetypes_sub = local_context_filetypes_p.add_subparsers(dest="local_context_filetypes_command")
3800
+ local_context_filetypes_list_p = local_context_filetypes_sub.add_parser("list", help="List file type rules")
3801
+ local_context_filetypes_list_p.add_argument("--json", action="store_true", help="JSON output")
3802
+ local_context_filetypes_include_p = local_context_filetypes_sub.add_parser("include", help="Include a file extension")
3803
+ local_context_filetypes_include_p.add_argument("extension", help="Extension, for example .pdf or asd")
3804
+ local_context_filetypes_include_p.add_argument("--action", choices=["extract", "metadata"], default="extract", help="How to index this extension")
3805
+ local_context_filetypes_include_p.add_argument("--reason", default="user", help="Reason label")
3806
+ local_context_filetypes_include_p.add_argument("--json", action="store_true", help="JSON output")
3807
+ local_context_filetypes_exclude_p = local_context_filetypes_sub.add_parser("exclude", help="Exclude a file extension")
3808
+ local_context_filetypes_exclude_p.add_argument("extension", help="Extension, for example .jpg or tmp")
3809
+ local_context_filetypes_exclude_p.add_argument("--reason", default="user", help="Reason label")
3810
+ local_context_filetypes_exclude_p.add_argument("--json", action="store_true", help="JSON output")
3811
+ local_context_filetypes_remove_p = local_context_filetypes_sub.add_parser("remove", help="Remove a user extension override")
3812
+ local_context_filetypes_remove_p.add_argument("extension", help="Extension to reset")
3813
+ local_context_filetypes_remove_p.add_argument("--json", action="store_true", help="JSON output")
3814
+ local_context_filetypes_reset_p = local_context_filetypes_sub.add_parser("reset", help="Remove all user extension overrides")
3815
+ local_context_filetypes_reset_p.add_argument("--json", action="store_true", help="JSON output")
3816
+
3817
+ local_context_migrate_roots_v2_p = local_context_sub.add_parser("migrate-roots-v2", help="Plan or apply Local Memory roots v2 cleanup")
3818
+ local_context_migrate_roots_v2_p.add_argument("--apply", action="store_true", help="Apply cleanup. Omit for dry-run.")
3819
+ local_context_migrate_roots_v2_p.add_argument("--json", action="store_true", help="JSON output")
3820
+
3762
3821
  local_context_query_p = local_context_sub.add_parser("query", help="Query local memory evidence")
3763
3822
  local_context_query_p.add_argument("query", help="Question or search phrase")
3764
3823
  local_context_query_p.add_argument("--intent", default="answer", help="Intent label included with the query result")
@@ -4407,6 +4466,13 @@ def main():
4407
4466
  local_context_exclusions_p.print_help()
4408
4467
  return 0
4409
4468
  return _local_context_exclusions(args)
4469
+ if args.local_context_command == "filetypes":
4470
+ if not args.local_context_filetypes_command:
4471
+ local_context_filetypes_p.print_help()
4472
+ return 0
4473
+ return _local_context_filetypes(args)
4474
+ if args.local_context_command == "migrate-roots-v2":
4475
+ return _local_context_migrate_roots_v2(args)
4410
4476
  if args.local_context_command == "query":
4411
4477
  return _local_context_query(args)
4412
4478
  if args.local_context_command == "diagnostics":
package/src/db/_schema.py CHANGED
@@ -1775,6 +1775,9 @@ def _m63_local_context_layer(conn):
1775
1775
  display_path TEXT NOT NULL,
1776
1776
  mode TEXT NOT NULL DEFAULT 'normal',
1777
1777
  depth INTEGER NOT NULL DEFAULT 2,
1778
+ source TEXT NOT NULL DEFAULT 'user',
1779
+ remote INTEGER NOT NULL DEFAULT 0,
1780
+ seed_version INTEGER NOT NULL DEFAULT 1,
1778
1781
  status TEXT NOT NULL DEFAULT 'active',
1779
1782
  last_scan_at REAL,
1780
1783
  created_at REAL NOT NULL,
@@ -1785,10 +1788,24 @@ def _m63_local_context_layer(conn):
1785
1788
  id INTEGER PRIMARY KEY AUTOINCREMENT,
1786
1789
  path TEXT NOT NULL UNIQUE,
1787
1790
  display_path TEXT NOT NULL,
1791
+ source TEXT NOT NULL DEFAULT 'user',
1792
+ kind TEXT NOT NULL DEFAULT 'folder',
1788
1793
  reason TEXT NOT NULL DEFAULT 'user',
1789
1794
  created_at REAL NOT NULL
1790
1795
  );
1791
1796
 
1797
+ CREATE TABLE IF NOT EXISTS local_index_file_type_rules (
1798
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
1799
+ extension TEXT NOT NULL,
1800
+ action TEXT NOT NULL DEFAULT 'ignore',
1801
+ source TEXT NOT NULL DEFAULT 'user',
1802
+ priority INTEGER NOT NULL DEFAULT 0,
1803
+ reason TEXT NOT NULL DEFAULT '',
1804
+ created_at REAL NOT NULL,
1805
+ updated_at REAL NOT NULL,
1806
+ UNIQUE(extension, source)
1807
+ );
1808
+
1792
1809
  CREATE TABLE IF NOT EXISTS local_index_jobs (
1793
1810
  job_id TEXT PRIMARY KEY,
1794
1811
  asset_id TEXT NOT NULL,
@@ -1940,6 +1957,12 @@ def _m63_local_context_layer(conn):
1940
1957
 
1941
1958
  CREATE INDEX IF NOT EXISTS idx_local_index_roots_status
1942
1959
  ON local_index_roots(status);
1960
+ CREATE INDEX IF NOT EXISTS idx_local_index_roots_source
1961
+ ON local_index_roots(source, status);
1962
+ CREATE INDEX IF NOT EXISTS idx_local_index_exclusions_source
1963
+ ON local_index_exclusions(source);
1964
+ CREATE INDEX IF NOT EXISTS idx_local_index_file_type_rules_ext
1965
+ ON local_index_file_type_rules(extension, source);
1943
1966
  CREATE INDEX IF NOT EXISTS idx_local_index_jobs_status_priority
1944
1967
  ON local_index_jobs(status, priority, created_at);
1945
1968
  CREATE INDEX IF NOT EXISTS idx_local_index_jobs_asset
@@ -17,17 +17,22 @@ from .api import (
17
17
  get_asset,
18
18
  get_neighbors,
19
19
  list_exclusions,
20
+ list_file_type_rules,
20
21
  list_roots,
21
22
  local_index_hygiene,
23
+ migrate_roots_seed_v2,
22
24
  model_status,
23
25
  pause,
24
26
  performance_config,
25
27
  purge_asset,
26
28
  reconcile_live_changes,
27
29
  remove_exclusion,
30
+ remove_file_type_rule,
28
31
  remove_root,
32
+ reset_file_type_rules,
29
33
  resume,
30
34
  run_once,
35
+ set_file_type_rule,
31
36
  set_performance_profile,
32
37
  status,
33
38
  warmup_models,
@@ -45,17 +50,22 @@ __all__ = [
45
50
  "get_asset",
46
51
  "get_neighbors",
47
52
  "list_exclusions",
53
+ "list_file_type_rules",
48
54
  "list_roots",
49
55
  "local_index_hygiene",
56
+ "migrate_roots_seed_v2",
50
57
  "model_status",
51
58
  "pause",
52
59
  "performance_config",
53
60
  "purge_asset",
54
61
  "reconcile_live_changes",
55
62
  "remove_exclusion",
63
+ "remove_file_type_rule",
56
64
  "remove_root",
65
+ "reset_file_type_rules",
57
66
  "resume",
58
67
  "run_once",
68
+ "set_file_type_rule",
59
69
  "set_performance_profile",
60
70
  "status",
61
71
  "warmup_models",