@monoes/monomindcli 1.6.0 → 1.6.2

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.
@@ -3,7 +3,7 @@ import fs from 'fs';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
5
  import { fileURLToPath } from 'url';
6
- import { collectAll, getWatchPaths, collectProject, collectSessions, collectSwarm, collectAgents, collectTokens, collectHooks, collectKnowledge, collectMetrics, collectMemory, collectMemoryFiles, collectSystem } from './collector.mjs';
6
+ import { collectAll, getWatchPaths, collectProject, collectSessions, collectSwarm, collectSwarmHistory, appendSwarmHistory, collectSwarmEvents, getSwarmDataSize, cleanSwarmData, collectAgents, collectTokens, collectHooks, collectKnowledge, collectMetrics, collectMemory, collectMemoryFiles, collectSystem } from './collector.mjs';
7
7
 
8
8
  const JSONL_SIZE_CAP = 10 * 1024 * 1024; // 10 MB — skip files larger than this in /api/graph
9
9
 
@@ -104,7 +104,7 @@ function buildSectionData(name, dir) {
104
104
  const d = path.resolve(dir);
105
105
  switch (name) {
106
106
  case 'sessions': return { sessions: collectSessions(d) };
107
- case 'swarm': return { swarm: collectSwarm(d), agents: collectAgents(d) };
107
+ case 'swarm': return { swarm: collectSwarm(d), swarmHistory: collectSwarmHistory(d), agents: collectAgents(d) };
108
108
  case 'agents': return { agents: collectAgents(d) };
109
109
  case 'tokens': return { tokens: collectTokens(d) };
110
110
  case 'hooks': return { hooks: collectHooks(d) };
@@ -187,7 +187,7 @@ function bindServer(server, port) {
187
187
  let attempt = 0;
188
188
 
189
189
  function tryPort(p) {
190
- server.listen(p, '127.0.0.1', () => resolve(p));
190
+ server.listen(p, () => resolve(p));
191
191
  server.once('error', (err) => {
192
192
  if (err.code === 'EADDRINUSE' && attempt < maxTries) {
193
193
  attempt += 1;
@@ -277,6 +277,65 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
277
277
  return;
278
278
  }
279
279
 
280
+ // ------------------------------------------------------- GET /api/session-journal
281
+ if (req.method === 'GET' && url === '/api/session-journal') {
282
+ try {
283
+ const qs = new URL(req.url, 'http://localhost').searchParams;
284
+ const dir = qs.get('dir') || projectDir;
285
+ const d = path.resolve(dir || process.cwd());
286
+ const slug = d.replace(/\//g, '-');
287
+ const projectClaudeDir = path.join(os.homedir(), '.claude', 'projects', slug);
288
+
289
+ let sessionFiles = [];
290
+ try {
291
+ sessionFiles = fs.readdirSync(projectClaudeDir)
292
+ .filter(f => f.endsWith('.jsonl'))
293
+ .map(f => { try { return { f, mtime: fs.statSync(path.join(projectClaudeDir, f)).mtimeMs }; } catch { return null; } })
294
+ .filter(Boolean)
295
+ .sort((a, b) => b.mtime - a.mtime)
296
+ .slice(0, 15);
297
+ } catch {}
298
+
299
+ const sessions = [];
300
+ for (const { f, mtime } of sessionFiles) {
301
+ const fp = path.join(projectClaudeDir, f);
302
+ const id = f.replace('.jsonl', '');
303
+ let lastPrompt = '', summaries = [], totalDurationMs = 0, totalMessages = 0, firstTs = null, lastTs = null;
304
+ try {
305
+ const lines = fs.readFileSync(fp, 'utf8').split('\n').filter(Boolean);
306
+ let pendingCompact = false;
307
+ for (const line of lines) {
308
+ let e; try { e = JSON.parse(line); } catch { continue; }
309
+ if (e.timestamp) { if (!firstTs) firstTs = e.timestamp; lastTs = e.timestamp; }
310
+ if (e.type === 'last-prompt' && e.lastPrompt) lastPrompt = e.lastPrompt;
311
+ if (e.type === 'system' && e.subtype === 'compact_boundary') pendingCompact = true;
312
+ if (pendingCompact && e.type === 'user') {
313
+ const msg = e.message || {};
314
+ const ct = msg.content || [];
315
+ let text = '';
316
+ if (Array.isArray(ct)) { for (const b of ct) { if (b && b.type === 'text') { text = b.text; break; } } }
317
+ else if (typeof ct === 'string') text = ct;
318
+ const m = text.match(/Summary:\s*([\s\S]+)/);
319
+ if (m) summaries.push({ ts: e.timestamp, text: m[1].trim() });
320
+ pendingCompact = false;
321
+ }
322
+ if (e.type === 'system' && e.subtype === 'turn_duration') {
323
+ totalDurationMs += e.durationMs || 0;
324
+ if ((e.messageCount || 0) > totalMessages) totalMessages = e.messageCount;
325
+ }
326
+ }
327
+ } catch {}
328
+ sessions.push({ id, mtime, firstTs, lastTs, lastPrompt, summaries, totalDurationMs, totalMessages });
329
+ }
330
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-cache' });
331
+ res.end(JSON.stringify({ sessions }));
332
+ } catch (err) {
333
+ res.writeHead(500, { 'Content-Type': 'application/json' });
334
+ res.end(JSON.stringify({ error: err.message }));
335
+ }
336
+ return;
337
+ }
338
+
280
339
  // ------------------------------------------------------- GET /api/palace
281
340
  if (req.method === 'GET' && url === '/api/palace') {
282
341
  try {
@@ -416,6 +475,47 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
416
475
  return;
417
476
  }
418
477
 
478
+ // ---------------------------------------------------------- GET /api/loops
479
+ if (req.method === 'GET' && url === '/api/loops') {
480
+ try {
481
+ const loopsDir = path.join(projectDir || process.cwd(), '.monomind', 'loops');
482
+ let loops = [];
483
+ try {
484
+ const files = fs.readdirSync(loopsDir).filter(f => f.endsWith('.json'));
485
+ const stopFiles = new Set(fs.readdirSync(loopsDir).filter(f => f.endsWith('.stop')).map(f => f.replace('.stop', '')));
486
+ for (const file of files) {
487
+ try {
488
+ const data = JSON.parse(fs.readFileSync(path.join(loopsDir, file), 'utf-8'));
489
+ data.stopRequested = stopFiles.has(data.id);
490
+ loops.push(data);
491
+ } catch {}
492
+ }
493
+ } catch (e) { if (e.code !== 'ENOENT') throw e; }
494
+ loops.sort((a, b) => (b.startedAt || 0) - (a.startedAt || 0));
495
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-cache' });
496
+ res.end(JSON.stringify({ loops }));
497
+ } catch (err) { res.writeHead(500); res.end(JSON.stringify({ error: err.message })); }
498
+ return;
499
+ }
500
+
501
+ // ---------------------------------------------------------- POST /api/loops/stop
502
+ if (req.method === 'POST' && url === '/api/loops/stop') {
503
+ let body = '';
504
+ req.on('data', chunk => { body += chunk; });
505
+ req.on('end', () => {
506
+ try {
507
+ const { id } = JSON.parse(body);
508
+ if (!id) { res.writeHead(400); res.end(JSON.stringify({ error: 'id required' })); return; }
509
+ const loopsDir = path.join(projectDir || process.cwd(), '.monomind', 'loops');
510
+ fs.mkdirSync(loopsDir, { recursive: true });
511
+ fs.writeFileSync(path.join(loopsDir, `${id}.stop`), `stop-requested-${Date.now()}`);
512
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
513
+ res.end(JSON.stringify({ ok: true }));
514
+ } catch (err) { res.writeHead(500); res.end(JSON.stringify({ error: err.message })); }
515
+ });
516
+ return;
517
+ }
518
+
419
519
  // ------------------------------------------------------- DELETE /api/knowledge-chunk
420
520
  if (req.method === 'DELETE' && url === '/api/knowledge-chunk') {
421
521
  let body = '';
@@ -726,6 +826,71 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
726
826
  return;
727
827
  }
728
828
 
829
+ // ------------------------------------------------- GET /api/swarm-history
830
+ if (req.method === 'GET' && url === '/api/swarm-history') {
831
+ try {
832
+ const qs = new URL(req.url, 'http://localhost').searchParams;
833
+ const dir = qs.get('dir') || projectDir || process.cwd();
834
+ const entries = collectSwarmHistory(path.resolve(dir));
835
+ res.writeHead(200, {
836
+ 'Content-Type': 'application/json',
837
+ 'Access-Control-Allow-Origin': '*',
838
+ 'Cache-Control': 'no-cache',
839
+ });
840
+ res.end(JSON.stringify({ entries }));
841
+ } catch (err) {
842
+ res.writeHead(500, { 'Content-Type': 'application/json' });
843
+ res.end(JSON.stringify({ error: err.message }));
844
+ }
845
+ return;
846
+ }
847
+
848
+ // ------------------------------------------------- GET /api/swarm-events
849
+ if (req.method === 'GET' && url === '/api/swarm-events') {
850
+ try {
851
+ const qs = new URL(req.url, 'http://localhost').searchParams;
852
+ const dir = qs.get('dir') || projectDir || process.cwd();
853
+ const swarmId = qs.get('swarmId') || undefined;
854
+ const agentId = qs.get('agentId') || undefined;
855
+ const last = qs.get('last') ? parseInt(qs.get('last')) : undefined;
856
+ const events = collectSwarmEvents(path.resolve(dir), { swarmId, agentId, last });
857
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-cache' });
858
+ res.end(JSON.stringify({ events, count: events.length }));
859
+ } catch (err) {
860
+ res.writeHead(500, { 'Content-Type': 'application/json' });
861
+ res.end(JSON.stringify({ error: err.message }));
862
+ }
863
+ return;
864
+ }
865
+
866
+ // ------------------------------------------------- GET /api/swarm-data-size
867
+ if (req.method === 'GET' && url === '/api/swarm-data-size') {
868
+ try {
869
+ const dir = new URL(req.url, 'http://localhost').searchParams.get('dir') || projectDir || process.cwd();
870
+ const size = getSwarmDataSize(path.resolve(dir));
871
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
872
+ res.end(JSON.stringify(size));
873
+ } catch (err) {
874
+ res.writeHead(500, { 'Content-Type': 'application/json' });
875
+ res.end(JSON.stringify({ error: err.message }));
876
+ }
877
+ return;
878
+ }
879
+
880
+ // ------------------------------------------------- DELETE /api/swarm-clean
881
+ if (req.method === 'DELETE' && url === '/api/swarm-clean') {
882
+ try {
883
+ const dir = new URL(req.url, 'http://localhost').searchParams.get('dir') || projectDir || process.cwd();
884
+ const result = cleanSwarmData(path.resolve(dir));
885
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
886
+ res.end(JSON.stringify({ success: true, ...result }));
887
+ } catch (err) {
888
+ res.writeHead(500, { 'Content-Type': 'application/json' });
889
+ res.end(JSON.stringify({ error: err.message }));
890
+ }
891
+ return;
892
+ }
893
+
729
894
  // ------------------------------------------------------- GET /api/section
730
895
  if (req.method === 'GET' && url === '/api/section') {
731
896
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "type": "module",
5
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",
6
6
  "main": "dist/src/index.js",