@monoes/monomindcli 2.4.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/README.md +2 -0
- package/dist/src/init/claudemd-generator.d.ts.map +1 -1
- package/dist/src/init/claudemd-generator.js +7 -4
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +3 -1
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts +8 -0
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +22 -0
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/session.d.ts +2 -0
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +5 -0
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/ui/dashboard.html +11 -2
- package/dist/src/ui/server.mjs +83 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/src/ui/server.mjs
CHANGED
|
@@ -1035,6 +1035,89 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
1035
1035
|
.catch(() => { /* warm-up is best-effort */ });
|
|
1036
1036
|
}, 3000);
|
|
1037
1037
|
if (_warmTimer.unref) _warmTimer.unref();
|
|
1038
|
+
|
|
1039
|
+
// ── Second Brain live ingestion ──────────────────────────────────
|
|
1040
|
+
// This server is the one long-lived local process AND holds the warm
|
|
1041
|
+
// embedding model — so it watches for document changes and ingests
|
|
1042
|
+
// in-process within seconds, instead of waiting for the next session
|
|
1043
|
+
// start. Best-effort: recursive fs.watch is unsupported on some
|
|
1044
|
+
// platforms/volumes; the session-start reindex remains the backstop.
|
|
1045
|
+
try {
|
|
1046
|
+
const _sbDocExts = new Set(['.md', '.txt', '.pdf', '.docx']);
|
|
1047
|
+
const _sbSkip = /(^|\/)(node_modules|\.git|dist|\.monomind|\.claude|\.next|__pycache__|\.venv|vendor)(\/|$)/;
|
|
1048
|
+
const _sbPending = new Map(); // file -> debounce timer
|
|
1049
|
+
const _sbRoot = path.resolve(projectDir || process.cwd());
|
|
1050
|
+
const _sbWatcher = fs.watch(_sbRoot, { recursive: true }, (_evt, rel) => {
|
|
1051
|
+
try {
|
|
1052
|
+
if (!rel) return;
|
|
1053
|
+
const relStr = String(rel);
|
|
1054
|
+
if (_sbSkip.test(relStr) || relStr.startsWith('.')) return;
|
|
1055
|
+
if (!_sbDocExts.has(path.extname(relStr).toLowerCase())) return;
|
|
1056
|
+
const full = path.join(_sbRoot, relStr);
|
|
1057
|
+
clearTimeout(_sbPending.get(full));
|
|
1058
|
+
_sbPending.set(full, setTimeout(async () => {
|
|
1059
|
+
_sbPending.delete(full);
|
|
1060
|
+
try {
|
|
1061
|
+
if (!fs.existsSync(full)) return; // deleted — session-start reindex handles removal
|
|
1062
|
+
const pipeline = await import('../knowledge/document-pipeline.js');
|
|
1063
|
+
const r = await pipeline.ingestDocument(full, 'shared', _sbRoot);
|
|
1064
|
+
if (r.chunksIndexed > 0 && !r.skipped) {
|
|
1065
|
+
console.log(`[knowledge] live-ingested ${path.basename(full)} (${r.chunksIndexed} chunks)`);
|
|
1066
|
+
}
|
|
1067
|
+
} catch (_) { /* single-file ingest failure never matters here */ }
|
|
1068
|
+
}, 5000));
|
|
1069
|
+
} catch (_) { /* watcher callback must never throw */ }
|
|
1070
|
+
});
|
|
1071
|
+
activeWatchers.push(_sbWatcher);
|
|
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 */ }
|
|
1038
1121
|
}
|
|
1039
1122
|
} catch (_) { /* non-fatal */ }
|
|
1040
1123
|
|