@yemi33/minions 0.1.567 → 0.1.569

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,9 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.567 (2026-04-08)
3
+ ## 0.1.569 (2026-04-08)
4
4
 
5
5
  ### Features
6
+ - add LLM Call Performance tile to engine page
6
7
  - add ccModel/ccEffort settings and agent runtime tracking
7
8
 
8
9
  ### Other
@@ -90,10 +90,38 @@ function renderMetrics(metrics) {
90
90
  }
91
91
  html += '</tbody></table>';
92
92
  el.innerHTML = html;
93
+ renderLlmPerf(metrics);
93
94
  renderTokenUsage(metrics);
94
95
  renderContextPressure(metrics);
95
96
  }
96
97
 
98
+ function renderLlmPerf(metrics) {
99
+ const el = document.getElementById('llm-perf-content');
100
+ if (!el) return;
101
+ const engine = metrics._engine;
102
+ if (!engine || Object.keys(engine).length === 0) {
103
+ el.innerHTML = '<p class="empty">No LLM performance data yet.</p>';
104
+ return;
105
+ }
106
+ let html = '<table class="pr-table"><thead><tr><th>Call Type</th><th>Calls</th><th>Total Time</th><th>Avg Time</th><th>Cost</th></tr></thead><tbody>';
107
+ const entries = Object.entries(engine).sort((a, b) => (b[1].calls || 0) - (a[1].calls || 0));
108
+ for (const [type, m] of entries) {
109
+ const calls = m.calls || 0;
110
+ const totalMs = m.totalDurationMs || 0;
111
+ const avgMs = calls > 0 ? totalMs / calls : 0;
112
+ const fmtTotal = totalMs < 60000 ? Math.round(totalMs / 1000) + 's' : Math.round(totalMs / 60000) + 'm';
113
+ const fmtAvg = avgMs < 1000 ? Math.round(avgMs) + 'ms' : avgMs < 60000 ? Math.round(avgMs / 1000) + 's' : Math.round(avgMs / 60000) + 'm';
114
+ const cost = m.costUsd ? '$' + m.costUsd.toFixed(2) : '-';
115
+ html += '<tr><td style="font-weight:600">' + escHtml(type) + '</td>' +
116
+ '<td>' + calls + '</td>' +
117
+ '<td style="color:var(--muted)">' + (totalMs ? fmtTotal : '-') + '</td>' +
118
+ '<td style="color:var(--blue)">' + (avgMs ? fmtAvg : '-') + '</td>' +
119
+ '<td style="color:var(--muted)">' + cost + '</td></tr>';
120
+ }
121
+ html += '</tbody></table>';
122
+ el.innerHTML = html;
123
+ }
124
+
97
125
  function renderTokenUsage(metrics) {
98
126
  const el = document.getElementById('token-usage-content');
99
127
  const agents = Object.entries(metrics).filter(([k]) => !k.startsWith('_'));
@@ -345,4 +373,4 @@ async function _addSelectedProjects() {
345
373
  }
346
374
  }
347
375
 
348
- window.MinionsOther = { renderProjects, renderMcpServers, renderMetrics, renderTokenUsage, renderContextPressure, openScanProjectsModal };
376
+ window.MinionsOther = { renderProjects, renderMcpServers, renderMetrics, renderLlmPerf, renderTokenUsage, renderContextPressure, openScanProjectsModal };
@@ -2,6 +2,10 @@
2
2
  <h2>Engine Log <span style="font-size:10px;color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0">tick-by-tick audit trail of engine operations</span></h2>
3
3
  <div class="log-list" id="engine-log">No log entries yet.</div>
4
4
  </section>
5
+ <section>
6
+ <h2>LLM Call Performance</h2>
7
+ <div id="llm-perf-content"><p class="empty">No LLM performance data yet. Data appears after CC, doc-chat, or consolidation calls.</p></div>
8
+ </section>
5
9
  <section>
6
10
  <h2>Agent Metrics</h2>
7
11
  <div id="metrics-content"><p class="empty">No metrics yet. Metrics appear after agents complete tasks.</p></div>
package/engine/llm.js CHANGED
@@ -27,6 +27,7 @@ function trackEngineUsage(category, usage) {
27
27
  cat.outputTokens += usage.outputTokens || 0;
28
28
  cat.cacheRead += usage.cacheRead || 0;
29
29
  cat.cacheCreation = (cat.cacheCreation || 0) + (usage.cacheCreation || 0);
30
+ if (usage.durationMs) cat.totalDurationMs = (cat.totalDurationMs || 0) + usage.durationMs;
30
31
 
31
32
  const today = ts().slice(0, 10);
32
33
  if (!metrics._daily) metrics._daily = {};
@@ -66,6 +67,7 @@ function callLLM(promptText, sysPromptText, { timeout = 120000, label = 'llm', m
66
67
 
67
68
  if (sessionId) args.push('--resume', sessionId);
68
69
 
70
+ const _startMs = Date.now();
69
71
  const proc = runFile(process.execPath, args, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
70
72
 
71
73
  let stdout = '';
@@ -80,7 +82,9 @@ function callLLM(promptText, sysPromptText, { timeout = 120000, label = 'llm', m
80
82
  safeUnlink(promptPath);
81
83
  safeUnlink(sysPath);
82
84
  const parsed = parseStreamJsonOutput(stdout);
83
- resolve({ text: parsed.text || '', usage: parsed.usage, sessionId: parsed.sessionId || null, code, stderr, raw: stdout });
85
+ const durationMs = Date.now() - _startMs;
86
+ const usage = parsed.usage ? { ...parsed.usage, durationMs } : { durationMs };
87
+ resolve({ text: parsed.text || '', usage, sessionId: parsed.sessionId || null, code, stderr, raw: stdout });
84
88
  });
85
89
 
86
90
  proc.on('error', (err) => {
@@ -136,6 +140,7 @@ function callLLMStreaming(promptText, sysPromptText, { timeout = 120000, label =
136
140
  args.push('--permission-mode', 'bypassPermissions');
137
141
  if (sessionId) args.push('--resume', sessionId);
138
142
 
143
+ const _startMs = Date.now();
139
144
  const proc = runFile(process.execPath, args, { cwd: MINIONS_DIR, stdio: ['pipe', 'pipe', 'pipe'], env: cleanChildEnv() });
140
145
 
141
146
  _abort = () => { shared.killImmediate(proc); };
@@ -179,7 +184,9 @@ function callLLMStreaming(promptText, sysPromptText, { timeout = 120000, label =
179
184
  safeUnlink(promptPath);
180
185
  safeUnlink(sysPath);
181
186
  const parsed = parseStreamJsonOutput(stdout);
182
- resolve({ text: parsed.text || '', usage: parsed.usage, sessionId: parsed.sessionId || null, code, stderr, raw: stdout });
187
+ const durationMs = Date.now() - _startMs;
188
+ const usage = parsed.usage ? { ...parsed.usage, durationMs } : { durationMs };
189
+ resolve({ text: parsed.text || '', usage, sessionId: parsed.sessionId || null, code, stderr, raw: stdout });
183
190
  });
184
191
 
185
192
  proc.on('error', (err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.567",
3
+ "version": "0.1.569",
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"