@monoes/monomindcli 1.12.0 → 1.13.0
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/.claude/helpers/handlers/route-handler.cjs +11 -4
- package/.claude/helpers/handlers/session-restore-handler.cjs +14 -8
- package/.claude/helpers/hook-handler.cjs +40 -0
- package/.claude/helpers/intelligence.cjs +129 -57
- package/.claude/helpers/memory-palace.cjs +461 -0
- package/.claude/helpers/memory.cjs +134 -15
- package/.claude/helpers/metrics-db.mjs +87 -0
- package/.claude/helpers/router.cjs +296 -41
- package/.claude/helpers/session.cjs +89 -32
- package/.claude/helpers/statusline.cjs +138 -2
- package/.claude/helpers/toggle-statusline.cjs +73 -0
- package/.claude/helpers/token-tracker.cjs +934 -0
- package/.claude/helpers/utils/monograph.cjs +39 -4
- package/.claude/helpers/utils/telemetry.cjs +3 -3
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +96 -4
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +329 -37
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/services/worker-daemon.d.ts.map +1 -1
- package/dist/src/services/worker-daemon.js +295 -5
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/transfer/serialization/cfp.js +1 -1
- package/dist/src/transfer/serialization/cfp.js.map +1 -1
- package/dist/src/ui/dashboard.html +673 -6
- package/dist/src/ui/server.mjs +144 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/src/ui/server.mjs
CHANGED
|
@@ -409,12 +409,22 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
409
409
|
const cwd = projectDir || process.cwd();
|
|
410
410
|
const name = gitExec('git config user.name', { cwd, encoding: 'utf8' }).trim();
|
|
411
411
|
const email = gitExec('git config user.email', { cwd, encoding: 'utf8' }).trim();
|
|
412
|
+
let remoteUrl = '';
|
|
413
|
+
try { remoteUrl = gitExec('git remote get-url origin', { cwd, encoding: 'utf8' }).trim(); } catch {}
|
|
414
|
+
// Normalise SSH remote to HTTPS URL for browser linking
|
|
415
|
+
if (remoteUrl.startsWith('git@')) {
|
|
416
|
+
remoteUrl = remoteUrl.replace(/^git@([^:]+):/, 'https://$1/').replace(/\.git$/, '');
|
|
417
|
+
} else if (remoteUrl.endsWith('.git')) {
|
|
418
|
+
remoteUrl = remoteUrl.slice(0, -4);
|
|
419
|
+
}
|
|
420
|
+
let branch = '';
|
|
421
|
+
try { branch = gitExec('git rev-parse --abbrev-ref HEAD', { cwd, encoding: 'utf8' }).trim(); } catch {}
|
|
412
422
|
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
413
|
-
res.end(JSON.stringify({ name, email, cwd }));
|
|
423
|
+
res.end(JSON.stringify({ name, email, cwd, remoteUrl, branch }));
|
|
414
424
|
} catch (_) {
|
|
415
425
|
const cwd2 = projectDir || process.cwd();
|
|
416
426
|
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
417
|
-
res.end(JSON.stringify({ name: '', email: '', cwd: cwd2 }));
|
|
427
|
+
res.end(JSON.stringify({ name: '', email: '', cwd: cwd2, remoteUrl: '', branch: '' }));
|
|
418
428
|
}
|
|
419
429
|
return;
|
|
420
430
|
}
|
|
@@ -631,6 +641,69 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
631
641
|
return;
|
|
632
642
|
}
|
|
633
643
|
|
|
644
|
+
// ------------------------------------------------------- GET /api/recent-events
|
|
645
|
+
if (req.method === 'GET' && url === '/api/recent-events') {
|
|
646
|
+
try {
|
|
647
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
648
|
+
const dir = qs.get('dir') || projectDir || process.cwd();
|
|
649
|
+
const limit = Math.min(parseInt(qs.get('limit') || '50', 10), 200);
|
|
650
|
+
const d = path.resolve(dir || process.cwd());
|
|
651
|
+
const slug = d.replace(/\//g, '-');
|
|
652
|
+
const projectClaudeDir = path.join(os.homedir(), '.claude', 'projects', slug);
|
|
653
|
+
let sessionFiles = [];
|
|
654
|
+
try {
|
|
655
|
+
sessionFiles = fs.readdirSync(projectClaudeDir)
|
|
656
|
+
.filter(f => f.endsWith('.jsonl'))
|
|
657
|
+
.map(f => { try { return { f, mtime: fs.statSync(path.join(projectClaudeDir, f)).mtimeMs }; } catch { return null; } })
|
|
658
|
+
.filter(Boolean)
|
|
659
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
660
|
+
.slice(0, 5); // check last 5 sessions
|
|
661
|
+
} catch {}
|
|
662
|
+
|
|
663
|
+
const events = [];
|
|
664
|
+
const HOOK_RE = /^<(local-command-|command-name>|command-message>)/;
|
|
665
|
+
for (const { f } of sessionFiles) {
|
|
666
|
+
const fp = path.join(projectClaudeDir, f);
|
|
667
|
+
const sessId = f.replace('.jsonl', '');
|
|
668
|
+
try {
|
|
669
|
+
const lines = fs.readFileSync(fp, 'utf8').split('\n').filter(Boolean).slice(-200);
|
|
670
|
+
for (const line of lines) {
|
|
671
|
+
let e; try { e = JSON.parse(line); } catch { continue; }
|
|
672
|
+
if (e.type === 'assistant') {
|
|
673
|
+
const content = e.message?.content || [];
|
|
674
|
+
for (const block of content) {
|
|
675
|
+
if (block?.type === 'tool_use') {
|
|
676
|
+
events.push({ kind: 'tool', ts: e.timestamp, tool: block.name, session: sessId });
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
} else if (e.type === 'user') {
|
|
680
|
+
const content = e.message?.content || [];
|
|
681
|
+
for (const block of content) {
|
|
682
|
+
if (block?.type === 'text' && block.text?.trim() && !HOOK_RE.test(block.text.trim())) {
|
|
683
|
+
events.push({ kind: 'user', ts: e.timestamp, text: block.text.slice(0, 120), session: sessId });
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
} catch {}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// sort by ts desc, take limit
|
|
692
|
+
events.sort((a, b) => {
|
|
693
|
+
const ta = a.ts ? new Date(a.ts).getTime() : 0;
|
|
694
|
+
const tb = b.ts ? new Date(b.ts).getTime() : 0;
|
|
695
|
+
return tb - ta;
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
699
|
+
res.end(JSON.stringify({ events: events.slice(0, limit) }));
|
|
700
|
+
} catch (err) {
|
|
701
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
702
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
703
|
+
}
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
634
707
|
// ------------------------------------------------------- GET /api/tool-errors
|
|
635
708
|
if (req.method === 'GET' && url === '/api/tool-errors') {
|
|
636
709
|
try {
|
|
@@ -4637,6 +4710,75 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
4637
4710
|
return;
|
|
4638
4711
|
}
|
|
4639
4712
|
|
|
4713
|
+
// GET /api/status — live system snapshot for dashboard polling
|
|
4714
|
+
if (req.method === 'GET' && url === '/api/status') {
|
|
4715
|
+
try {
|
|
4716
|
+
const root = projectDir || process.cwd();
|
|
4717
|
+
// Active org runs: { orgName -> runId }
|
|
4718
|
+
const orgRuns = {};
|
|
4719
|
+
activeOrgRuns.forEach((runId, org) => { orgRuns[org] = runId; });
|
|
4720
|
+
// Recent events (last 10)
|
|
4721
|
+
let recentEvents = [];
|
|
4722
|
+
try {
|
|
4723
|
+
const evPath = path.join(root, 'data', 'mastermind-events.jsonl');
|
|
4724
|
+
const lines = fs.readFileSync(evPath, 'utf8').split('\n').filter(l => l.trim()).slice(-10);
|
|
4725
|
+
recentEvents = lines.map(l => { try { return JSON.parse(l); } catch(_) { return null; } }).filter(Boolean);
|
|
4726
|
+
} catch(_) {}
|
|
4727
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
4728
|
+
res.end(JSON.stringify({
|
|
4729
|
+
ts: Date.now(),
|
|
4730
|
+
uptime: process.uptime(),
|
|
4731
|
+
sseClients: mmSseClients.size,
|
|
4732
|
+
activeOrgs: Object.keys(orgRuns).length,
|
|
4733
|
+
orgRuns,
|
|
4734
|
+
recentEvents,
|
|
4735
|
+
}));
|
|
4736
|
+
} catch(err) {
|
|
4737
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
4738
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
4739
|
+
}
|
|
4740
|
+
return;
|
|
4741
|
+
}
|
|
4742
|
+
|
|
4743
|
+
// GET /api/orgs/:name/runs/current — events from the active run file for an org
|
|
4744
|
+
if (req.method === 'GET' && /^\/api\/orgs\/[^/]+\/runs\/current$/.test(url)) {
|
|
4745
|
+
try {
|
|
4746
|
+
const orgName = decodeURIComponent(url.split('/')[3]);
|
|
4747
|
+
const root = projectDir || process.cwd();
|
|
4748
|
+
// Validate orgName
|
|
4749
|
+
if (!orgName || orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) {
|
|
4750
|
+
res.writeHead(400); res.end('{"error":"invalid org name"}'); return;
|
|
4751
|
+
}
|
|
4752
|
+
const runId = activeOrgRuns.get(orgName);
|
|
4753
|
+
const monoDir = _getGitMonomindDir(root) || path.join(root, '.monomind');
|
|
4754
|
+
// Try active run first, then fall back to most recent run file
|
|
4755
|
+
let runFile = null;
|
|
4756
|
+
if (runId) {
|
|
4757
|
+
const candidate = path.join(monoDir, 'orgs', orgName, 'runs', `${runId}.jsonl`);
|
|
4758
|
+
if (fs.existsSync(candidate)) runFile = candidate;
|
|
4759
|
+
}
|
|
4760
|
+
if (!runFile) {
|
|
4761
|
+
const runsDir = path.join(monoDir, 'orgs', orgName, 'runs');
|
|
4762
|
+
if (fs.existsSync(runsDir)) {
|
|
4763
|
+
const files = fs.readdirSync(runsDir).filter(f => f.endsWith('.jsonl'));
|
|
4764
|
+
if (files.length) {
|
|
4765
|
+
files.sort();
|
|
4766
|
+
runFile = path.join(runsDir, files[files.length - 1]);
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4770
|
+
if (!runFile) { res.writeHead(404); res.end('{"events":[],"runId":null}'); return; }
|
|
4771
|
+
const detectedRunId = path.basename(runFile, '.jsonl');
|
|
4772
|
+
const lines = fs.readFileSync(runFile, 'utf8').split('\n').filter(l => l.trim()).slice(-100);
|
|
4773
|
+
const events = lines.map(l => { try { return JSON.parse(l); } catch(_) { return null; } }).filter(Boolean);
|
|
4774
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
4775
|
+
res.end(JSON.stringify({ runId: detectedRunId, events, active: activeOrgRuns.has(orgName) }));
|
|
4776
|
+
} catch(err) {
|
|
4777
|
+
res.writeHead(500); res.end(JSON.stringify({ error: err.message }));
|
|
4778
|
+
}
|
|
4779
|
+
return;
|
|
4780
|
+
}
|
|
4781
|
+
|
|
4640
4782
|
// GET /api/mastermind/metrics — aggregate system metrics from token-summary and swarm-activity
|
|
4641
4783
|
if (req.method === 'GET' && url === '/api/mastermind/metrics') {
|
|
4642
4784
|
try {
|