monomind 2.5.3 → 2.5.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.
- package/README.md +10 -3
- package/package.json +1 -1
- package/packages/@monomind/cli/.claude/commands/mastermind/topology.md +121 -0
- package/packages/@monomind/cli/.claude/commands/mastermind.md +121 -102
- package/packages/@monomind/cli/.claude/helpers/control-start.cjs +22 -2
- package/packages/@monomind/cli/.claude/helpers/control-stop.cjs +95 -0
- package/packages/@monomind/cli/.claude/helpers/graphify-freshen.cjs +6 -0
- package/packages/@monomind/cli/.claude/helpers/handlers/gates-handler.cjs +5 -0
- package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +13 -5
- package/packages/@monomind/cli/.claude/helpers/utils/monograph.cjs +33 -10
- package/packages/@monomind/cli/.claude/helpers/utils/system-pressure.cjs +46 -0
- package/packages/@monomind/cli/.claude/settings.json +448 -0
- package/packages/@monomind/cli/README.md +10 -3
- package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/agent-ops.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/cleanup.js +53 -1
- package/packages/@monomind/cli/dist/src/commands/config.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/hooks.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/index.js +4 -0
- package/packages/@monomind/cli/dist/src/commands/init-wizard.js +3 -3
- package/packages/@monomind/cli/dist/src/commands/init.js +2 -2
- package/packages/@monomind/cli/dist/src/commands/mcp.js +2 -2
- package/packages/@monomind/cli/dist/src/commands/memory-admin.js +8 -7
- package/packages/@monomind/cli/dist/src/commands/memory-list.js +2 -2
- package/packages/@monomind/cli/dist/src/commands/memory.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/commands/memory.js +4 -4
- package/packages/@monomind/cli/dist/src/commands/neural-core.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/performance.js +8 -9
- package/packages/@monomind/cli/dist/src/commands/status.js +2 -2
- package/packages/@monomind/cli/dist/src/commands/swarm.js +1 -1
- package/packages/@monomind/cli/dist/src/index.js +1 -1
- package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +2 -2
- package/packages/@monomind/cli/dist/src/init/executor.js +13 -6
- package/packages/@monomind/cli/dist/src/init/helpers-generator.js +66 -3
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +1 -1
- package/packages/@monomind/cli/dist/src/init/statusline-generator.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/init/statusline-generator.js +2 -2
- package/packages/@monomind/cli/dist/src/init/types.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/knowledge/document-pipeline.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/knowledge/document-pipeline.js +3 -3
- package/packages/@monomind/cli/dist/src/mcp-client.d.ts +13 -51
- package/packages/@monomind/cli/dist/src/mcp-client.js +79 -134
- package/packages/@monomind/cli/dist/src/mcp-server.js +4 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +45 -19
- package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +1 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +2 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.js +2 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/knowledge-tools.js +1 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-compat.js +2 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +22 -9
- package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +3 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +1 -1
- package/packages/@monomind/cli/dist/src/memory/embedding-operations.js +2 -2
- package/packages/@monomind/cli/dist/src/memory/hnsw-operations.js +53 -26
- package/packages/@monomind/cli/dist/src/memory/intelligence.js +2 -2
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +7 -3
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +24 -10
- package/packages/@monomind/cli/dist/src/memory/memory-crud.js +2 -2
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.d.ts +2 -2
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +6 -6
- package/packages/@monomind/cli/dist/src/memory/memory-read.js +4 -4
- package/packages/@monomind/cli/dist/src/orgrt/daemon.js +12 -6
- package/packages/@monomind/cli/dist/src/orgrt/mailbox.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/orgrt/mailbox.js +4 -0
- package/packages/@monomind/cli/dist/src/orgrt/policy.js +1 -1
- package/packages/@monomind/cli/dist/src/orgrt/server.js +25 -0
- package/packages/@monomind/cli/dist/src/ui/dashboard.html +327 -611
- package/packages/@monomind/cli/dist/src/ui/server.mjs +165 -22
- package/packages/@monomind/cli/package.json +1 -1
|
@@ -5,6 +5,7 @@ import os from 'os';
|
|
|
5
5
|
import crypto from 'crypto';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { createRequire } from 'module';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
8
9
|
import { collectAll, getWatchPaths, collectProject, collectSessions, collectSwarm, collectSwarmHistory, appendSwarmHistory, collectSwarmEvents, getSwarmDataSize, cleanSwarmData, collectAgents, collectTokens, collectHooks, collectKnowledge, collectMetrics, collectMemory, collectMemoryFiles, collectSystem } from './collector.mjs';
|
|
9
10
|
import { addSseClient, removeSseClient, broadcast, getSseClientCount, closeSseClients, addMmClient, removeMmClient, broadcastMm, getMmClientCount } from './sse-manager.mjs';
|
|
10
11
|
|
|
@@ -226,6 +227,23 @@ let _runDbInsertStmt = null; // prepared INSERT statement
|
|
|
226
227
|
|
|
227
228
|
const _require = createRequire(import.meta.url);
|
|
228
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Guard against a stale PID file outliving its process and the OS recycling
|
|
232
|
+
* that PID for an unrelated process — verify the live process actually looks
|
|
233
|
+
* like ours (node/npx running something under this project or monomind)
|
|
234
|
+
* before signaling it or reporting it as "running".
|
|
235
|
+
*/
|
|
236
|
+
function looksLikeOurProcess(pid, dir) {
|
|
237
|
+
try {
|
|
238
|
+
const { execSync } = _require('child_process');
|
|
239
|
+
const cmd = execSync(`ps -p ${pid} -o command=`, { timeout: 2000, encoding: 'utf-8' }).trim();
|
|
240
|
+
const looksLikeNode = cmd.includes('node') || cmd.includes('npx') || cmd.includes('npm exec');
|
|
241
|
+
return looksLikeNode && (cmd.includes('monomind') || cmd.includes('monograph') || cmd.includes(dir));
|
|
242
|
+
} catch {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
229
247
|
async function _initRunDb(monoHome) {
|
|
230
248
|
try {
|
|
231
249
|
const initSqlJs = _require('sql.js');
|
|
@@ -410,6 +428,7 @@ function appendToFile(filePath, line) {
|
|
|
410
428
|
// reach /main/.git, then up one more to /main/ for the monomind data root.
|
|
411
429
|
// Falls back to the working directory if git isn't available.
|
|
412
430
|
const _gitMonomindCache = new Map();
|
|
431
|
+
const _MAX_GIT_CACHE = 100;
|
|
413
432
|
function _getGitMonomindDir(workDir) {
|
|
414
433
|
if (!workDir) return null;
|
|
415
434
|
if (_gitMonomindCache.has(workDir)) return _gitMonomindCache.get(workDir);
|
|
@@ -433,6 +452,10 @@ function _getGitMonomindDir(workDir) {
|
|
|
433
452
|
}
|
|
434
453
|
} catch {}
|
|
435
454
|
if (!result) result = path.join(workDir, '.monomind'); // fallback
|
|
455
|
+
if (_gitMonomindCache.size >= _MAX_GIT_CACHE) {
|
|
456
|
+
const oldest = _gitMonomindCache.keys().next().value;
|
|
457
|
+
_gitMonomindCache.delete(oldest);
|
|
458
|
+
}
|
|
436
459
|
_gitMonomindCache.set(workDir, result);
|
|
437
460
|
return result;
|
|
438
461
|
}
|
|
@@ -629,10 +652,15 @@ function bindServer(server, port) {
|
|
|
629
652
|
* Falls back to cwd in session files, then to direct slug replacement.
|
|
630
653
|
*/
|
|
631
654
|
const _slugPathCache = new Map();
|
|
655
|
+
const _MAX_SLUG_CACHE = 200;
|
|
632
656
|
|
|
633
657
|
function resolveSlugToPath(slug, projDir) {
|
|
634
658
|
if (_slugPathCache.has(slug)) return _slugPathCache.get(slug);
|
|
635
659
|
const resolved = _resolveSlugToPathUncached(slug, projDir);
|
|
660
|
+
if (_slugPathCache.size >= _MAX_SLUG_CACHE) {
|
|
661
|
+
const oldest = _slugPathCache.keys().next().value;
|
|
662
|
+
_slugPathCache.delete(oldest);
|
|
663
|
+
}
|
|
636
664
|
_slugPathCache.set(slug, resolved);
|
|
637
665
|
return resolved;
|
|
638
666
|
}
|
|
@@ -3186,13 +3214,17 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
3186
3214
|
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
3187
3215
|
const dir = qs.get('dir') || projectDir || process.cwd();
|
|
3188
3216
|
const d = path.resolve(dir || process.cwd());
|
|
3189
|
-
const pidPath = path.join(d, '.monomind', 'monograph.watch.pid');
|
|
3190
3217
|
let running = false, pid = null;
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3218
|
+
for (const pidName of ['monograph.watch.pid', 'monograph-watch.pid']) {
|
|
3219
|
+
try {
|
|
3220
|
+
const pp = path.join(d, '.monomind', pidName);
|
|
3221
|
+
pid = parseInt(fs.readFileSync(pp, 'utf-8').trim(), 10);
|
|
3222
|
+
process.kill(pid, 0);
|
|
3223
|
+
if (!looksLikeOurProcess(pid, d)) continue;
|
|
3224
|
+
running = true;
|
|
3225
|
+
break;
|
|
3226
|
+
} catch {}
|
|
3227
|
+
}
|
|
3196
3228
|
res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
|
|
3197
3229
|
res.end(JSON.stringify({ running, pid }));
|
|
3198
3230
|
} catch (err) {
|
|
@@ -3210,13 +3242,17 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
3210
3242
|
const d = path.resolve(dir || process.cwd());
|
|
3211
3243
|
const pidPath = path.join(d, '.monomind', 'monograph.watch.pid');
|
|
3212
3244
|
let wasRunning = false;
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3245
|
+
for (const pidName of ['monograph.watch.pid', 'monograph-watch.pid']) {
|
|
3246
|
+
try {
|
|
3247
|
+
const pp = path.join(d, '.monomind', pidName);
|
|
3248
|
+
const pid = parseInt(fs.readFileSync(pp, 'utf-8').trim(), 10);
|
|
3249
|
+
process.kill(pid, 0);
|
|
3250
|
+
if (!looksLikeOurProcess(pid, d)) continue;
|
|
3251
|
+
wasRunning = true;
|
|
3252
|
+
process.kill(pid, 'SIGTERM');
|
|
3253
|
+
try { fs.unlinkSync(pp); } catch {}
|
|
3254
|
+
} catch {}
|
|
3255
|
+
}
|
|
3220
3256
|
|
|
3221
3257
|
if (wasRunning) {
|
|
3222
3258
|
res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
|
|
@@ -3237,6 +3273,28 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
3237
3273
|
return;
|
|
3238
3274
|
}
|
|
3239
3275
|
|
|
3276
|
+
// -------------------------------------------------- POST /api/shutdown
|
|
3277
|
+
if (req.method === 'POST' && url === '/api/shutdown') {
|
|
3278
|
+
res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
|
|
3279
|
+
res.end(JSON.stringify({ ok: true }));
|
|
3280
|
+
// Kill monograph watcher if running
|
|
3281
|
+
const d = projectDir || process.cwd();
|
|
3282
|
+
for (const pidName of ['monograph.watch.pid', 'monograph-watch.pid']) {
|
|
3283
|
+
try {
|
|
3284
|
+
const wp = path.join(d, '.monomind', pidName);
|
|
3285
|
+
if (fs.statSync(wp).size > 32) continue;
|
|
3286
|
+
const wpid = parseInt(fs.readFileSync(wp, 'utf-8').trim(), 10);
|
|
3287
|
+
if (!Number.isInteger(wpid) || wpid <= 0) { try { fs.unlinkSync(wp); } catch {} continue; }
|
|
3288
|
+
if (looksLikeOurProcess(wpid, d)) process.kill(wpid, 'SIGTERM');
|
|
3289
|
+
try { fs.unlinkSync(wp); } catch {}
|
|
3290
|
+
} catch {}
|
|
3291
|
+
}
|
|
3292
|
+
// Remove control.json so startup knows we're gone
|
|
3293
|
+
try { fs.unlinkSync(path.join(d, '.monomind', 'control.json')); } catch {}
|
|
3294
|
+
setTimeout(shutdown, 100);
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3240
3298
|
// -------------------------------------------------- POST /api/mcp/call
|
|
3241
3299
|
if (req.method === 'POST' && url === '/api/mcp/call') {
|
|
3242
3300
|
let body = '';
|
|
@@ -4559,6 +4617,43 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
4559
4617
|
return;
|
|
4560
4618
|
}
|
|
4561
4619
|
|
|
4620
|
+
// POST /api/org/:name/agent/:roleId/avatar — set (or clear) a custom avatar for one
|
|
4621
|
+
// role, stored inline as a data URL on the role itself so it travels with the org
|
|
4622
|
+
// config export/import. Body: { avatarDataUrl } — null/omitted avatarDataUrl clears
|
|
4623
|
+
// the custom avatar and reverts to the built-in library picture. `dir` (like every
|
|
4624
|
+
// other dir-accepting route in this file, POST included — see /goals above) comes
|
|
4625
|
+
// from the query string, not the body.
|
|
4626
|
+
if (req.method === 'POST' && /^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/agent\/[a-z0-9][a-z0-9_-]{0,63}\/avatar$/i.test(url)) {
|
|
4627
|
+
let body = '';
|
|
4628
|
+
for await (const chunk of req) { body += chunk; if (body.length > 8388608) { req.destroy(); break; } }
|
|
4629
|
+
try {
|
|
4630
|
+
const parts = url.split('/');
|
|
4631
|
+
const orgName = decodeURIComponent(parts[3]);
|
|
4632
|
+
const roleId = decodeURIComponent(parts[5]);
|
|
4633
|
+
if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('{"ok":false,"error":"Invalid org name"}'); return; }
|
|
4634
|
+
if (roleId.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(roleId)) { res.writeHead(400); res.end('{"ok":false,"error":"Invalid role id"}'); return; }
|
|
4635
|
+
const parsed = JSON.parse(body);
|
|
4636
|
+
const avatarDataUrl = parsed.avatarDataUrl;
|
|
4637
|
+
if (avatarDataUrl != null && (typeof avatarDataUrl !== 'string' || avatarDataUrl.length > 2_000_000 || !/^data:image\/(png|jpe?g|webp|gif);base64,[A-Za-z0-9+/=]+$/.test(avatarDataUrl))) {
|
|
4638
|
+
res.writeHead(400); res.end('{"ok":false,"error":"Invalid or oversized avatarDataUrl"}'); return;
|
|
4639
|
+
}
|
|
4640
|
+
const _avatarQs = new URL(req.url, 'http://localhost').searchParams;
|
|
4641
|
+
const d = path.resolve(_avatarQs.get('dir') || projectDir || process.cwd());
|
|
4642
|
+
const orgFile = path.join(d, '.monomind', 'orgs', `${orgName}.json`);
|
|
4643
|
+
if (!fs.existsSync(orgFile)) { res.writeHead(404); res.end('{"ok":false,"error":"org not found"}'); return; }
|
|
4644
|
+
const config = JSON.parse(fs.readFileSync(orgFile, 'utf8'));
|
|
4645
|
+
const role = (config.roles || []).find(r => r.id === roleId);
|
|
4646
|
+
if (!role) { res.writeHead(404); res.end('{"ok":false,"error":"role not found"}'); return; }
|
|
4647
|
+
if (avatarDataUrl) role.avatar = avatarDataUrl; else delete role.avatar;
|
|
4648
|
+
const tmp = `${orgFile}.tmp`;
|
|
4649
|
+
fs.writeFileSync(tmp, JSON.stringify(config, null, 2), 'utf-8');
|
|
4650
|
+
fs.renameSync(tmp, orgFile);
|
|
4651
|
+
res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
|
|
4652
|
+
res.end(JSON.stringify({ ok: true }));
|
|
4653
|
+
} catch (e) { res.writeHead(500); res.end(JSON.stringify({ ok: false, error: String(e.message || e) })); }
|
|
4654
|
+
return;
|
|
4655
|
+
}
|
|
4656
|
+
|
|
4562
4657
|
// GET /api/org/:name/search?q=<query> — fuzzy search across org data
|
|
4563
4658
|
if (req.method === 'GET' && /^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/search(\?.*)?$/i.test(url)) {
|
|
4564
4659
|
try {
|
|
@@ -4967,9 +5062,11 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
4967
5062
|
return;
|
|
4968
5063
|
}
|
|
4969
5064
|
|
|
4970
|
-
// GET /api/questions?dir=<projectDir> — list
|
|
4971
|
-
// every org in one project. Mirrors the existing -approvals.json
|
|
4972
|
-
// but reads this feature's .monomind/orgs/<org>/questions.json
|
|
5065
|
+
// GET /api/questions?dir=<projectDir> — list ask_human questions (pending and
|
|
5066
|
+
// answered) for every org in one project. Mirrors the existing -approvals.json
|
|
5067
|
+
// sidecar convention, but reads this feature's .monomind/orgs/<org>/questions.json
|
|
5068
|
+
// files (one per org dir). Each entry's `answer`/`answeredAt` fields (present once
|
|
5069
|
+
// answered, absent while pending) let the dashboard split them into tabs.
|
|
4973
5070
|
if (req.method === 'GET' && url === '/api/questions') {
|
|
4974
5071
|
try {
|
|
4975
5072
|
const _qDir = new URL(req.url, 'http://localhost').searchParams.get('dir') || projectDir || process.cwd();
|
|
@@ -4982,7 +5079,7 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
4982
5079
|
let data = { questions: [] };
|
|
4983
5080
|
try { data = JSON.parse(fs.readFileSync(qFile, 'utf8')); } catch (_) {}
|
|
4984
5081
|
for (const q of (data.questions || [])) {
|
|
4985
|
-
|
|
5082
|
+
out.push({ org: orgName, ...q });
|
|
4986
5083
|
}
|
|
4987
5084
|
}
|
|
4988
5085
|
}
|
|
@@ -5059,8 +5156,19 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
5059
5156
|
const queuedEvent = { type: 'org:question-answered', org, role, questionId, ts: Date.now(), queued: true };
|
|
5060
5157
|
appendToFile(path.join(projDir, 'data', 'mastermind-events.jsonl'), JSON.stringify(queuedEvent) + '\n').catch(() => {});
|
|
5061
5158
|
broadcastMm(queuedEvent);
|
|
5159
|
+
// Auto-wake: a queued answer is worthless if nothing ever restarts the org to
|
|
5160
|
+
// drain it (unlike the direct-daemon path, this control server holds no OrgDaemon
|
|
5161
|
+
// instance to call autoWake() on). `org run` itself no-ops if the org's runtime.json
|
|
5162
|
+
// already shows a live pid, so this is safe to fire even if another process is
|
|
5163
|
+
// racing to start it.
|
|
5164
|
+
try {
|
|
5165
|
+
const child = spawn('npx', ['-y', 'monomind@latest', 'org', 'run', org], {
|
|
5166
|
+
cwd: projDir, detached: true, stdio: 'ignore',
|
|
5167
|
+
});
|
|
5168
|
+
child.unref();
|
|
5169
|
+
} catch (_) { /* best-effort — the answer is still queued on disk either way */ }
|
|
5062
5170
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
5063
|
-
res.end(JSON.stringify({ ok: true, queued: true }));
|
|
5171
|
+
res.end(JSON.stringify({ ok: true, queued: true, waking: true }));
|
|
5064
5172
|
return;
|
|
5065
5173
|
}
|
|
5066
5174
|
const fwd = await fetch(`${hostUrl}/api/answer-question`, {
|
|
@@ -5496,8 +5604,10 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
5496
5604
|
const _delOrgQs = new URL(req.url, 'http://localhost').searchParams;
|
|
5497
5605
|
const orgsDir = path.join(path.resolve(_delOrgQs.get('dir') || projectDir || process.cwd()), '.monomind', 'orgs');
|
|
5498
5606
|
const configFile = path.join(orgsDir, `${orgName}.json`);
|
|
5499
|
-
|
|
5607
|
+
const v1ConfigFile = path.join(orgsDir, `${orgName}.v1.json`);
|
|
5608
|
+
if (!fs.existsSync(configFile) && !fs.existsSync(v1ConfigFile)) { res.writeHead(404); res.end('{"error":"org not found"}'); return; }
|
|
5500
5609
|
// Remove all org-associated files (config + state + data)
|
|
5610
|
+
try { if (fs.existsSync(v1ConfigFile)) fs.unlinkSync(v1ConfigFile); } catch(_) {}
|
|
5501
5611
|
const suffixes = ['', '-state', '-goals', '-routines', '-approvals', '-activity', '-issues', '-members', '-projects', '-workspaces', '-worktrees', '-environments', '-plugins', '-adapters', '-budgets', '-threads', '-secrets', '-join-requests', '-bootstrap', '-project-workspaces', '-approval-comments', '-skills'];
|
|
5502
5612
|
for (const suf of suffixes) {
|
|
5503
5613
|
const f = path.join(orgsDir, `${orgName}${suf}.json`);
|
|
@@ -6481,7 +6591,9 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
6481
6591
|
try { _chPayload = JSON.parse(_chBody); } catch(_) {}
|
|
6482
6592
|
const _chText = String(_chPayload.text || '').trim().slice(0, 4096);
|
|
6483
6593
|
if (!_chText) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'text is required' })); return; }
|
|
6484
|
-
const
|
|
6594
|
+
const _chQs = new URL(req.url, 'http://localhost').searchParams;
|
|
6595
|
+
const _chServerRoot = path.resolve(_chQs.get('dir') || projectDir || process.cwd());
|
|
6596
|
+
const _chRoot = _resolveOrgProjectDir(_chOrgName, _chServerRoot) || _chServerRoot;
|
|
6485
6597
|
const _chMonoDir = _getGitMonomindDir(_chRoot) || path.join(_chRoot, '.monomind');
|
|
6486
6598
|
const _chRunId = activeOrgRuns.get(_chOrgName) || _getActiveRunId(_chOrgName, _chRoot);
|
|
6487
6599
|
const _chEvent = { type: 'user:message', org: _chOrgName, runId: _chRunId || null, text: _chText, ts: Date.now() };
|
|
@@ -6490,7 +6602,8 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
6490
6602
|
const _chRunFile = path.join(_chMonoDir, 'orgs', _chOrgName, 'runs', `${_chRunId}.jsonl`);
|
|
6491
6603
|
if (fs.existsSync(_chRunFile)) await appendToFile(_chRunFile, JSON.stringify(_chEvent) + '\n');
|
|
6492
6604
|
}
|
|
6493
|
-
// Write to mailbox file so boss agent can pick up on next cycle
|
|
6605
|
+
// Write to mailbox file so boss agent can pick up on next cycle (durable
|
|
6606
|
+
// record + offline fallback — the live-delivery attempt below is best-effort)
|
|
6494
6607
|
const _chMailbox = path.join(_chRoot, '.monomind', 'orgs', `${_chOrgName}-threads.json`);
|
|
6495
6608
|
try {
|
|
6496
6609
|
let _chThreads = { messages: [] };
|
|
@@ -6506,8 +6619,36 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
6506
6619
|
const _chLine = `data: ${JSON.stringify(_chEvent)}\n\n`;
|
|
6507
6620
|
for (const _cl of _chFwdClients) { try { _cl.write(_chLine); } catch(_) { _chFwdClients.delete(_cl); } }
|
|
6508
6621
|
}
|
|
6622
|
+
// Forward to the org's live process (if any) so the message actually lands in a
|
|
6623
|
+
// running role's mailbox — looked up via the same file-based broker registry
|
|
6624
|
+
// orgrt's cross-process delivery already uses (mirrors POST /api/questions/answer).
|
|
6625
|
+
let _chDelivered = false;
|
|
6626
|
+
try {
|
|
6627
|
+
const _chBrokerEntryPath = path.join(os.homedir(), '.monomind', 'orgrt-broker', `${_chOrgName}.json`);
|
|
6628
|
+
const _chBrokerEntry = JSON.parse(fs.readFileSync(_chBrokerEntryPath, 'utf8'));
|
|
6629
|
+
if (Date.now() - _chBrokerEntry.updatedAt < 90000 && _chBrokerEntry.url) {
|
|
6630
|
+
let _chTargetRole = _chPayload.role;
|
|
6631
|
+
if (!_chTargetRole) {
|
|
6632
|
+
try {
|
|
6633
|
+
const _chCfg = JSON.parse(fs.readFileSync(path.join(_chRoot, '.monomind', 'orgs', `${_chOrgName}.json`), 'utf8'));
|
|
6634
|
+
const _chRoles = Array.isArray(_chCfg.roles) ? _chCfg.roles : [];
|
|
6635
|
+
const _chBoss = _chRoles.find(r => r.type === 'boss' || r.reports_to === null) || _chRoles[0];
|
|
6636
|
+
_chTargetRole = _chBoss?.id;
|
|
6637
|
+
} catch(_) {}
|
|
6638
|
+
}
|
|
6639
|
+
if (_chTargetRole) {
|
|
6640
|
+
const _chFwd = await fetch(`${_chBrokerEntry.url}/api/human-message`, {
|
|
6641
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
6642
|
+
body: JSON.stringify({ org: _chOrgName, role: _chTargetRole, text: _chText }),
|
|
6643
|
+
signal: AbortSignal.timeout(5000),
|
|
6644
|
+
});
|
|
6645
|
+
const _chFwdData = await _chFwd.json().catch(() => ({}));
|
|
6646
|
+
_chDelivered = !!(_chFwd.ok && _chFwdData.ok);
|
|
6647
|
+
}
|
|
6648
|
+
}
|
|
6649
|
+
} catch(_) {}
|
|
6509
6650
|
res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
|
|
6510
|
-
res.end(JSON.stringify({ ok: true }));
|
|
6651
|
+
res.end(JSON.stringify({ ok: true, delivered: _chDelivered }));
|
|
6511
6652
|
} catch (e) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: e.message })); }
|
|
6512
6653
|
return;
|
|
6513
6654
|
}
|
|
@@ -6942,12 +7083,14 @@ new Sigma(g,document.getElementById('g'),{renderEdgeLabels:false,labelColor:{col
|
|
|
6942
7083
|
currentPort = null;
|
|
6943
7084
|
currentUrl = null;
|
|
6944
7085
|
activeServer = null;
|
|
7086
|
+
process.exit(0);
|
|
6945
7087
|
});
|
|
6946
7088
|
});
|
|
6947
7089
|
}
|
|
6948
7090
|
|
|
6949
7091
|
process.once('SIGTERM', shutdown);
|
|
6950
7092
|
process.once('SIGINT', shutdown);
|
|
7093
|
+
process.once('SIGHUP', shutdown);
|
|
6951
7094
|
|
|
6952
7095
|
// ---------------------------------------------------------- Auto-open
|
|
6953
7096
|
if (openBrowser) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI engine for Monomind \u2014 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",
|