@yemi33/minions 0.1.472 → 0.1.474

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/CHANGELOG.md CHANGED
@@ -1,8 +1,17 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.472 (2026-04-07)
3
+ ## 0.1.474 (2026-04-07)
4
+
5
+ ### Features
6
+ - Limit SSE initial live-stream payload to last 64KB
7
+
8
+ ### Fixes
9
+ - pass config to updatePrAfterReview to fix test failure
10
+
11
+ ## 0.1.473 (2026-04-07)
4
12
 
5
13
  ### Fixes
14
+ - agent card click feels instant — show panel before API loads
6
15
  - steering audit — prevent double-kill, clean up temp files, fix leaks
7
16
  - steering resume improvements — better error logging, heartbeat restart
8
17
  - prevent slow work item modal on large descriptions
@@ -33,6 +33,11 @@ async function openAgentDetail(id) {
33
33
  '<span style="color:var(--muted)">' + escHtml(agent.lastAction) + '</span>' +
34
34
  (agent.resultSummary ? '<div style="margin-top:4px;font-size:11px;color:var(--text);line-height:1.4">' + renderMd(agent.resultSummary.slice(0, 300)) + '</div>' : '');
35
35
 
36
+ // Show panel immediately with loading state — don't wait for API
37
+ document.getElementById('detail-content').innerHTML = '<div style="padding:24px;text-align:center;color:var(--muted)">Loading...</div>';
38
+ document.getElementById('detail-overlay').classList.add('open');
39
+ document.getElementById('detail-panel').classList.add('open');
40
+
36
41
  try {
37
42
  const detail = await safeFetch('/api/agent/' + id).then(r => r.json());
38
43
  renderDetailTabs(detail);
@@ -46,8 +51,6 @@ async function openAgentDetail(id) {
46
51
  '</div>';
47
52
  }
48
53
 
49
- document.getElementById('detail-overlay').classList.add('open');
50
- document.getElementById('detail-panel').classList.add('open');
51
54
  }
52
55
 
53
56
  window.MinionsAgents = { renderAgents, openAgentDetail };
package/dashboard.js CHANGED
@@ -1511,15 +1511,25 @@ const server = http.createServer(async (req, res) => {
1511
1511
  'Connection': 'keep-alive',
1512
1512
  });
1513
1513
 
1514
- // Send initial content
1514
+ // Send initial content — tail only (last 64KB by default) to avoid memory spikes
1515
+ const params = new URL(req.url, 'http://localhost').searchParams;
1516
+ const tailBytes = Math.max(0, parseInt(params.get('tail') || '65536', 10) || 65536);
1515
1517
  let offset = 0;
1516
1518
  try {
1517
- const content = fs.readFileSync(liveLogPath, 'utf8');
1518
- if (content.length > 0) {
1519
- safeWrite(`data: ${JSON.stringify(content)}\n\n`);
1520
- offset = Buffer.byteLength(content, 'utf8');
1519
+ const stat = fs.statSync(liveLogPath);
1520
+ const fileSize = stat.size;
1521
+ if (fileSize > 0) {
1522
+ const readStart = Math.max(0, fileSize - tailBytes);
1523
+ const readLen = fileSize - readStart;
1524
+ const fd = fs.openSync(liveLogPath, 'r');
1525
+ const buf = Buffer.alloc(readLen);
1526
+ fs.readSync(fd, buf, 0, readLen, readStart);
1527
+ fs.closeSync(fd);
1528
+ const content = buf.toString('utf8');
1529
+ if (content) safeWrite(`data: ${JSON.stringify(content)}\n\n`);
1530
+ offset = fileSize;
1521
1531
  }
1522
- } catch { /* optional */ }
1532
+ } catch { /* optional — file may not exist yet */ }
1523
1533
 
1524
1534
  // Watch for changes using fs.watchFile (cross-platform, works on Windows)
1525
1535
  const watcher = () => {
@@ -712,11 +712,11 @@ function syncPrsFromOutput(output, agentId, meta, config) {
712
712
 
713
713
  // ─── Post-Completion Hooks ──────────────────────────────────────────────────
714
714
 
715
- function updatePrAfterReview(agentId, pr, project) {
715
+ function updatePrAfterReview(agentId, pr, project, config) {
716
716
 
717
717
  if (!pr?.id) return;
718
718
 
719
- const config = getConfig();
719
+ if (!config) config = getConfig();
720
720
  const reviewerName = config.agents[agentId]?.name || agentId;
721
721
  const dispatch = getDispatch();
722
722
  const completedEntry = (dispatch.completed || []).find(d => d.agent === agentId && d.type === 'review');
@@ -1322,7 +1322,7 @@ function runPostCompletionHooks(dispatchItem, agentId, code, stdout, config) {
1322
1322
  }
1323
1323
  }
1324
1324
 
1325
- if (type === WORK_TYPE.REVIEW) updatePrAfterReview(agentId, meta?.pr, meta?.project);
1325
+ if (type === WORK_TYPE.REVIEW) updatePrAfterReview(agentId, meta?.pr, meta?.project, config);
1326
1326
  if (type === WORK_TYPE.FIX) updatePrAfterFix(meta?.pr, meta?.project, meta?.source);
1327
1327
  checkForLearnings(agentId, config.agents[agentId], dispatchItem.task);
1328
1328
  if (effectiveSuccess) {
package/engine/queries.js CHANGED
@@ -254,7 +254,9 @@ function getAgentDetail(id) {
254
254
  const agentDir = path.join(AGENTS_DIR, id);
255
255
  const charter = safeRead(path.join(agentDir, 'charter.md')) || 'No charter found.';
256
256
  const history = safeRead(path.join(agentDir, 'history.md')) || 'No history yet.';
257
- const outputLog = safeRead(path.join(agentDir, 'output.log')) || '';
257
+ // Only send last 50KB of output.log full logs can be megabytes and slow down the API
258
+ let outputLog = safeRead(path.join(agentDir, 'output.log')) || '';
259
+ if (outputLog.length > 50000) outputLog = '…(truncated — showing last 50KB)\n\n' + outputLog.slice(-50000);
258
260
 
259
261
  const statusData = getAgentStatus(id); // derives from dispatch.json
260
262
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.472",
3
+ "version": "0.1.474",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"