monomind 2.1.0 → 2.1.3

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.
Files changed (49) hide show
  1. package/README.md +74 -92
  2. package/package.json +3 -3
  3. package/packages/@monomind/cli/.claude/helpers/handlers/capture-handler.cjs +24 -10
  4. package/packages/@monomind/cli/.claude/helpers/handlers/gates-handler.cjs +2 -2
  5. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +29 -0
  6. package/packages/@monomind/cli/.claude/helpers/handlers/session-handler.cjs +35 -23
  7. package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +21 -0
  8. package/packages/@monomind/cli/.claude/helpers/utils/monograph.cjs +73 -2
  9. package/packages/@monomind/cli/README.md +74 -92
  10. package/packages/@monomind/cli/dist/src/browser/workflow/store.d.ts +2 -2
  11. package/packages/@monomind/cli/dist/src/commands/browse.d.ts +1 -1
  12. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +5 -0
  13. package/packages/@monomind/cli/dist/src/commands/org.js +46 -29
  14. package/packages/@monomind/cli/dist/src/commands/platforms.d.ts +1 -1
  15. package/packages/@monomind/cli/dist/src/init/executor.js +30 -6
  16. package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.d.ts +8 -8
  17. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.d.ts +31 -31
  18. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +5 -1
  19. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +28 -3
  20. package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.d.ts +36 -36
  21. package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts +4 -4
  22. package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.d.ts +12 -0
  23. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +12 -0
  24. package/packages/@monomind/cli/dist/src/orgrt/broker.d.ts +3 -1
  25. package/packages/@monomind/cli/dist/src/orgrt/broker.js +8 -3
  26. package/packages/@monomind/cli/dist/src/orgrt/bus.d.ts +5 -1
  27. package/packages/@monomind/cli/dist/src/orgrt/bus.js +5 -1
  28. package/packages/@monomind/cli/dist/src/orgrt/daemon.d.ts +17 -1
  29. package/packages/@monomind/cli/dist/src/orgrt/daemon.js +115 -21
  30. package/packages/@monomind/cli/dist/src/orgrt/forwarder.js +41 -8
  31. package/packages/@monomind/cli/dist/src/orgrt/inbox.d.ts +11 -0
  32. package/packages/@monomind/cli/dist/src/orgrt/inbox.js +56 -0
  33. package/packages/@monomind/cli/dist/src/orgrt/policy.d.ts +5 -1
  34. package/packages/@monomind/cli/dist/src/orgrt/policy.js +58 -5
  35. package/packages/@monomind/cli/dist/src/orgrt/server.d.ts +3 -2
  36. package/packages/@monomind/cli/dist/src/orgrt/server.js +7 -40
  37. package/packages/@monomind/cli/dist/src/orgrt/session.d.ts +10 -1
  38. package/packages/@monomind/cli/dist/src/orgrt/session.js +24 -1
  39. package/packages/@monomind/cli/dist/src/orgrt/test-loop.js +8 -8
  40. package/packages/@monomind/cli/dist/src/orgrt/types.d.ts +52 -52
  41. package/packages/@monomind/cli/dist/src/output.d.ts +29 -29
  42. package/packages/@monomind/cli/dist/src/output.js +10 -2
  43. package/packages/@monomind/cli/dist/src/types.d.ts +2 -2
  44. package/packages/@monomind/cli/dist/src/ui/dashboard.html +203 -9
  45. package/packages/@monomind/cli/dist/src/ui/orgs-files.js +192 -0
  46. package/packages/@monomind/cli/dist/src/ui/orgs.html +21 -52
  47. package/packages/@monomind/cli/dist/src/ui/server.mjs +42 -6
  48. package/packages/@monomind/cli/package.json +12 -16
  49. package/packages/@monomind/cli/dist/src/orgrt/live.html +0 -56
@@ -9,6 +9,9 @@ import { collectAll, getWatchPaths, collectProject, collectSessions, collectSwar
9
9
  import { addSseClient, removeSseClient, broadcast, getSseClientCount, closeSseClients, addMmClient, removeMmClient, broadcastMm, getMmClientCount } from './sse-manager.mjs';
10
10
 
11
11
  const JSONL_SIZE_CAP = 10 * 1024 * 1024; // 10 MB — skip files larger than this in /api/graph
12
+ // Session id format for data/sessions/<id>.jsonl persistence — no path traversal (".."), starts
13
+ // with a word char, rest is word chars/dot/dash. Shared by every session-id-accepting endpoint.
14
+ const SESSION_ID_RE = /^(?!.*\.\.)[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/;
12
15
  const buildDocsState = new Map();
13
16
 
14
17
  // Pricing per token (mirrors token-tracker.cjs FALLBACK_PRICING)
@@ -608,10 +611,26 @@ function bindServer(server, port) {
608
611
  * uses a greedy BFS over the real filesystem to find the correct path.
609
612
  * Falls back to cwd in session files, then to direct slug replacement.
610
613
  */
614
+ const _slugPathCache = new Map();
615
+
611
616
  function resolveSlugToPath(slug, projDir) {
612
- // 1. Try filesystem BFS (most reliable)
617
+ if (_slugPathCache.has(slug)) return _slugPathCache.get(slug);
618
+ const resolved = _resolveSlugToPathUncached(slug, projDir);
619
+ _slugPathCache.set(slug, resolved);
620
+ return resolved;
621
+ }
622
+
623
+ function _resolveSlugToPathUncached(slug, projDir) {
624
+ // 1. Try filesystem BFS (most reliable). Branching is O(2^hyphens) in the
625
+ // worst case (a slug with N hyphens can require exploring both "new path
626
+ // segment" and "hyphen is part of this segment's name" at each of the N
627
+ // positions) — bound total exploration so a slug with many hyphens (e.g.
628
+ // a UUID-embedded temp/scratchpad dir) can't hang the event loop.
613
629
  const parts = slug.replace(/^-/, '').split('-');
630
+ const MAX_CALLS = 20000;
631
+ let calls = 0;
614
632
  function tryPaths(idx, current) {
633
+ if (++calls > MAX_CALLS) return null;
615
634
  if (idx === parts.length) return fs.existsSync(current) ? current : null;
616
635
  // Option A: next part is a new path component
617
636
  const asDir = path.join(current, parts[idx]);
@@ -690,7 +709,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
690
709
  // Extracted from the request dispatcher to reduce cyclomatic complexity.
691
710
  // Handles POST /api/mastermind/event: parses body, enriches with runId/session,
692
711
  // persists to JSONL files, broadcasts to SSE clients, returns {ok:true}.
693
- async function handleMastermindEvent(req, res) {
712
+ async function handleMastermindEvent(req, res, corsOrigin) {
694
713
  let body = '';
695
714
  for await (const chunk of req) { body += chunk; if (body.length > 2097152) { req.destroy(); break; } }
696
715
  let event = {};
@@ -887,7 +906,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
887
906
  // Format: data/sessions/<sessionId>.jsonl + data/sessions/_index.json
888
907
  try {
889
908
  const _sid = String(event.session || '').trim();
890
- if (_sid.length > 0 && _sid.length <= 128 && /^(?!.*\.\.)[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/.test(_sid)) {
909
+ if (_sid.length > 0 && _sid.length <= 128 && SESSION_ID_RE.test(_sid)) {
891
910
  const sessDir = path.join(dataDir, 'sessions');
892
911
  fs.mkdirSync(sessDir, { recursive: true });
893
912
  // Append event to per-session JSONL (O(1), no read)
@@ -5397,7 +5416,7 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
5397
5416
  // ------------------------------------------------- Mastermind event system
5398
5417
  // POST /api/mastermind/event — ingest event from mastermind skill
5399
5418
  if (req.method === 'POST' && url === '/api/mastermind/event') {
5400
- return handleMastermindEvent(req, res);
5419
+ return handleMastermindEvent(req, res, corsOrigin);
5401
5420
  }
5402
5421
 
5403
5422
  // GET /api/mastermind-stream — SSE for real-time events
@@ -5449,7 +5468,7 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
5449
5468
  const top = idx.slice(0, limitParam);
5450
5469
  for (const entry of top) {
5451
5470
  const _sid = String(entry.id || '').trim();
5452
- if (!_sid || !/^(?!.*\.\.)[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/.test(_sid)) continue;
5471
+ if (!_sid || !SESSION_ID_RE.test(_sid)) continue;
5453
5472
  let events = [];
5454
5473
  try {
5455
5474
  const jl = fs.readFileSync(path.join(sessDir, `${_sid}.jsonl`), 'utf8');
@@ -5557,6 +5576,23 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
5557
5576
  return;
5558
5577
  }
5559
5578
 
5579
+ // ------------------------------------------------ GET /orgs-files.js
5580
+ // Files-tab + diff-view script, split out of orgs.html (see orgs.html's
5581
+ // script-src comment). Not a generic static handler — this UI serves each
5582
+ // sibling asset via its own hardcoded route, same as GET /orgs above.
5583
+ if (req.method === 'GET' && url === '/orgs-files.js') {
5584
+ try {
5585
+ const jsPath = path.join(__dirname, 'orgs-files.js');
5586
+ const js = fs.readFileSync(jsPath, 'utf8');
5587
+ res.writeHead(200, { 'Content-Type': 'application/javascript; charset=utf-8' });
5588
+ res.end(js);
5589
+ } catch (err) {
5590
+ res.writeHead(404);
5591
+ res.end(`orgs-files.js not found: ${err.message}`);
5592
+ }
5593
+ return;
5594
+ }
5595
+
5560
5596
  // GET /api/mastermind/loops — list all active loop state files
5561
5597
  if (req.method === 'GET' && url === '/api/mastermind/loops') {
5562
5598
  try {
@@ -6193,7 +6229,7 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
6193
6229
  const _migIndex = [];
6194
6230
  for (const sess of (_migOld || [])) {
6195
6231
  const _msid = String(sess.id || '').trim();
6196
- if (!_msid || !/^(?!.*\.\.)[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/.test(_msid)) continue;
6232
+ if (!_msid || !SESSION_ID_RE.test(_msid)) continue;
6197
6233
  // Write per-session JSONL
6198
6234
  const _mEvts = (sess.events || []);
6199
6235
  const _mLines = _mEvts.map(e => JSON.stringify(e)).join('\n');
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "2.1.0",
3
+ "version": "2.1.3",
4
4
  "type": "module",
5
- "description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
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",
7
7
  "types": "dist/src/index.d.ts",
8
8
  "sideEffects": false,
@@ -27,21 +27,17 @@
27
27
  "claude",
28
28
  "claude-code",
29
29
  "anthropic",
30
- "ai-agents",
31
- "multi-agent",
32
- "swarm",
33
30
  "mcp",
34
31
  "model-context-protocol",
35
- "llm",
32
+ "knowledge-graph",
33
+ "tree-sitter",
34
+ "code-analysis",
35
+ "ai-agents",
36
+ "multi-agent",
36
37
  "cli",
37
- "orchestration",
38
- "automation",
39
38
  "developer-tools",
40
- "coding-assistant",
41
- "vector-database",
42
- "embeddings",
43
- "self-learning",
44
- "enterprise"
39
+ "open-source",
40
+ "local-first"
45
41
  ],
46
42
  "author": {
47
43
  "name": "nokhodian",
@@ -83,8 +79,8 @@
83
79
  "README.md"
84
80
  ],
85
81
  "scripts": {
86
- "build": "tsc && mkdir -p dist/src/browser/dashboard && cp src/browser/dashboard/ui.html dist/src/browser/dashboard/ui.html && mkdir -p dist/src/orgrt && cp src/orgrt/live.html dist/src/orgrt/",
87
- "build:loose": "tsc --noEmitOnError false || true && mkdir -p dist/src/browser/dashboard && cp src/browser/dashboard/ui.html dist/src/browser/dashboard/ui.html && mkdir -p dist/src/orgrt && cp src/orgrt/live.html dist/src/orgrt/",
82
+ "build": "tsc && mkdir -p dist/src/browser/dashboard && cp src/browser/dashboard/ui.html dist/src/browser/dashboard/ui.html",
83
+ "build:loose": "tsc --noEmitOnError false || true && mkdir -p dist/src/browser/dashboard && cp src/browser/dashboard/ui.html dist/src/browser/dashboard/ui.html",
88
84
  "test": "vitest run",
89
85
  "test:pattern-store": "npx tsx src/transfer/store/tests/standalone-test.ts",
90
86
  "prepublishOnly": "cp ../../../README.md ./README.md",
@@ -92,7 +88,7 @@
92
88
  "publish:all": "./scripts/publish.sh"
93
89
  },
94
90
  "devDependencies": {
95
- "typescript": "^5.3.0",
91
+ "typescript": "^7.0.2",
96
92
  "vitest": "^4.1.4"
97
93
  },
98
94
  "dependencies": {
@@ -1,56 +0,0 @@
1
- <!-- packages/@monomind/cli/src/orgrt/live.html -->
2
- <!doctype html>
3
- <html><head><meta charset="utf-8"><title>org live</title>
4
- <style>
5
- :root { color-scheme: dark; }
6
- body { margin:0; font:13px/1.5 ui-monospace,monospace; background:#0d1117; color:#e6edf3;
7
- display:grid; grid-template-columns:220px 1fr 1fr; grid-template-rows:auto 1fr 1fr; gap:1px; height:100vh; }
8
- header { grid-column:1/4; padding:8px 14px; background:#161b22; font-weight:700; }
9
- section { background:#161b22; overflow:auto; padding:10px; }
10
- h2 { font-size:11px; text-transform:uppercase; letter-spacing:.1em; color:#7d8590; margin:0 0 8px; }
11
- #agents { grid-row:2/4; }
12
- .agent { padding:6px 8px; border-left:3px solid #2f81f7; margin-bottom:6px; background:#0d1117; }
13
- .agent small { color:#7d8590; display:block; }
14
- .row { padding:4px 6px; border-bottom:1px solid #21262d; word-break:break-word; }
15
- .from { color:#2f81f7; font-weight:700; } .to { color:#a371f7; }
16
- .deny { color:#f85149; } .allow { color:#3fb950; } .xorg { color:#d29922; font-weight:700; }
17
- .ts { color:#484f58; font-size:11px; margin-right:6px; }
18
- </style></head>
19
- <body>
20
- <header>org live — <span id="conn">connecting…</span></header>
21
- <section id="agents"><h2>Agents</h2><div id="agents-list"></div></section>
22
- <section id="chat"><h2>Chats &amp; Messages</h2><div id="chat-list"></div></section>
23
- <section id="tools"><h2>Tool Activity &amp; Assets</h2><div id="tools-list"></div></section>
24
- <script>
25
- const $ = id => document.getElementById(id);
26
- const fmt = ts => new Date(ts).toLocaleTimeString();
27
- const add = (listId, html, cap = 500) => {
28
- const el = document.createElement('div'); el.className = 'row'; el.innerHTML = html;
29
- const list = $(listId); list.prepend(el);
30
- while (list.children.length > cap) list.lastChild.remove();
31
- };
32
- const esc = s => String(s ?? '').replace(/[&<>]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));
33
- const decisionClass = d => (d === 'allow' || d === 'deny') ? d : 'unknown';
34
- function render(e) {
35
- const t = `<span class="ts">${fmt(e.ts)}</span>`;
36
- if (e.type === 'chat') add('chat-list', `${t}<span class="from">${esc(e.org)}/${esc(e.from)}</span>: ${esc(e.msg)}`);
37
- else if (e.type === 'message') add('chat-list', `${t}<span class="from">${esc(e.from)}</span> → <span class="to">${esc(e.to)}</span> [${esc(e.subject||'')}] ${esc(e.msg)}`);
38
- else if (e.type === 'xorg') add('chat-list', `${t}<span class="xorg">⇄ ${esc(e.from)} → ${esc(e.to)}</span> [${esc(e.subject||'')}] ${esc(e.msg)}`);
39
- else if (e.type === 'tool') add('tools-list', `${t}<span class="from">${esc(e.from)}</span> ${esc(e.tool)} <span class="${decisionClass(e.decision)}">${esc(e.decision)}</span>${e.reason ? ' — ' + esc(e.reason) : ''}`);
40
- else if (e.type === 'asset') add('tools-list', `${t}<span class="from">${esc(e.from)}</span> 📄 <b>${esc(e.path)}</b>`);
41
- else if (e.type === 'status' || e.type === 'usage') add('tools-list', `${t}<i>${esc(e.org)}/${esc(e.from ?? 'org')}: ${esc(e.msg ?? JSON.stringify(e.data))}</i>`);
42
- }
43
- async function refreshAgents() {
44
- const orgs = await fetch('/api/orgs').then(r => r.json()).catch(() => []);
45
- $('agents-list').innerHTML = orgs.map(o =>
46
- `<div class="agent"><b>${esc(o.name)}</b><small>${esc(o.run)}</small>` +
47
- o.agents.map(a => `<div>${a.closed ? '⚫' : '🟢'} ${esc(a.id)} <small>${esc(a.usage)} tok</small></div>`).join('') +
48
- `</div>`).join('') || '<i>no running orgs</i>';
49
- }
50
- const ws = new WebSocket(`ws://${location.host}/ws`);
51
- ws.onopen = () => { $('conn').textContent = 'live'; refreshAgents(); };
52
- ws.onclose = () => { $('conn').textContent = 'disconnected'; };
53
- ws.onmessage = ev => { render(JSON.parse(ev.data)); };
54
- setInterval(refreshAgents, 5000);
55
- </script>
56
- </body></html>