monomind 2.5.0 → 2.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monomind",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "Open-source CLI extension for Claude Code. Adds an MCP server with a codebase knowledge graph, persistent memory, multi-agent coordination, and reusable slash commands. MIT licensed, runs locally, no data leaves your machine.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -260,7 +260,9 @@ export async function bridgeStoreEntry(options) {
260
260
  ? options.value.slice(0, BRIDGE_MAX_VALUE_LEN) : options.value;
261
261
  const namespace = options.namespace ?? 'default';
262
262
  const tags = Array.isArray(options.tags)
263
- ? options.tags.filter(t => typeof t === 'string' && t.length > 0 && t.length <= MAX_TAG_LEN).slice(0, MAX_TAGS)
263
+ // src: tags carry the ingest source path for excerpt provenance paths
264
+ // routinely exceed the general 64-char tag cap, so they get 512.
265
+ ? options.tags.filter(t => typeof t === 'string' && t.length > 0 && t.length <= (t.startsWith('src:') ? 512 : MAX_TAG_LEN)).slice(0, MAX_TAGS)
264
266
  : [];
265
267
  const now = Date.now();
266
268
  const id = generateId('entry');
@@ -1069,7 +1069,55 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1069
1069
  } catch (_) { /* watcher callback must never throw */ }
1070
1070
  });
1071
1071
  activeWatchers.push(_sbWatcher);
1072
- } catch (_) { /* recursive watch unavailable — session-start reindex covers it */ }
1072
+ } catch (_) { /* recursive watch unavailable — the sweep below still covers it */ }
1073
+
1074
+ // Polling sweep backstop: fs.watch/fsevents silently stops delivering on
1075
+ // some volumes (exFAT/SMB — exactly where many projects live). Every 60s,
1076
+ // a bounded mtime walk ingests anything the watcher missed. Stat-only
1077
+ // when nothing changed; skips while a sweep is already running.
1078
+ try {
1079
+ const _sbDocExts2 = new Set(['.md', '.txt', '.pdf', '.docx']);
1080
+ const _sbSkipDirs = new Set(['node_modules', '.git', 'dist', '.monomind', '.claude', '.next', '__pycache__', '.venv', 'vendor']);
1081
+ const _sbSweepRoot = path.resolve(projectDir || process.cwd());
1082
+ let _sbLastSweep = Date.now();
1083
+ let _sbSweeping = false;
1084
+ const _sbSweepTimer = setInterval(async () => {
1085
+ if (_sbSweeping) return;
1086
+ _sbSweeping = true;
1087
+ const since = _sbLastSweep - 5000; // small overlap so boundary writes aren't missed
1088
+ _sbLastSweep = Date.now();
1089
+ try {
1090
+ const changed = [];
1091
+ let scanned = 0;
1092
+ const walk = (dir, depth) => {
1093
+ if (depth > 4 || scanned > 3000 || changed.length >= 20) return;
1094
+ let names;
1095
+ try { names = fs.readdirSync(dir, { withFileTypes: true }); } catch (_) { return; }
1096
+ for (const ent of names) {
1097
+ if (scanned++ > 3000 || changed.length >= 20) return;
1098
+ if (ent.name.startsWith('.') || _sbSkipDirs.has(ent.name)) continue;
1099
+ const full = path.join(dir, ent.name);
1100
+ if (ent.isDirectory()) { walk(full, depth + 1); continue; }
1101
+ if (!_sbDocExts2.has(path.extname(ent.name).toLowerCase())) continue;
1102
+ try { if (fs.statSync(full).mtimeMs > since) changed.push(full); } catch (_) {}
1103
+ }
1104
+ };
1105
+ walk(_sbSweepRoot, 0);
1106
+ if (changed.length) {
1107
+ const pipeline = await import('../knowledge/document-pipeline.js');
1108
+ for (const f of changed) {
1109
+ try {
1110
+ const r = await pipeline.ingestDocument(f, 'shared', _sbSweepRoot);
1111
+ if (r.chunksIndexed > 0 && !r.skipped) console.log(`[knowledge] sweep-ingested ${path.basename(f)} (${r.chunksIndexed} chunks)`);
1112
+ } catch (_) { /* per-file failures never matter here */ }
1113
+ }
1114
+ }
1115
+ } catch (_) { /* sweep is best-effort */ }
1116
+ finally { _sbSweeping = false; }
1117
+ }, 60_000);
1118
+ if (_sbSweepTimer.unref) _sbSweepTimer.unref();
1119
+ activeWatchers.push({ close: () => clearInterval(_sbSweepTimer) });
1120
+ } catch (_) { /* non-fatal */ }
1073
1121
  }
1074
1122
  } catch (_) { /* non-fatal */ }
1075
1123
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "type": "module",
5
5
  "description": "CLI engine for Monomind — an open-source MCP server that extends Claude Code with a codebase knowledge graph (tree-sitter + SQLite), persistent memory, multi-agent task coordination, and session hooks. MIT licensed, fully local.",
6
6
  "main": "dist/src/index.js",
@@ -105,7 +105,7 @@
105
105
  },
106
106
  "optionalDependencies": {
107
107
  "@huggingface/transformers": "^3.8.1",
108
- "@monoes/memory": "^1.0.8",
108
+ "@monoes/memory": "^1.0.10",
109
109
  "@monomind/hooks": "*",
110
110
  "@monomind/mcp": "*",
111
111
  "@monomind/routing": "*",