@yemi33/minions 0.1.568 → 0.1.570
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 +5 -1
- package/dashboard/js/render-other.js +29 -23
- package/dashboard/pages/engine.html +4 -4
- package/engine/llm.js +9 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.570 (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
|
|
|
9
|
+
### Fixes
|
|
10
|
+
- remove dead Context Pressure tile from engine page
|
|
11
|
+
|
|
8
12
|
### Other
|
|
9
13
|
- refactor: use safeJson/safeWrite for spawn-agent cache, remove unused checkedAt
|
|
10
14
|
|
|
@@ -42,7 +42,6 @@ function renderMetrics(metrics) {
|
|
|
42
42
|
if (agents.length === 0) {
|
|
43
43
|
el.innerHTML = '<p class="empty">No metrics yet. Metrics appear after agents complete tasks.</p>';
|
|
44
44
|
renderTokenUsage(metrics);
|
|
45
|
-
renderContextPressure(metrics);
|
|
46
45
|
return;
|
|
47
46
|
}
|
|
48
47
|
// Consolidate temp-* agents into one row
|
|
@@ -90,8 +89,35 @@ function renderMetrics(metrics) {
|
|
|
90
89
|
}
|
|
91
90
|
html += '</tbody></table>';
|
|
92
91
|
el.innerHTML = html;
|
|
92
|
+
renderLlmPerf(metrics);
|
|
93
93
|
renderTokenUsage(metrics);
|
|
94
|
-
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function renderLlmPerf(metrics) {
|
|
97
|
+
const el = document.getElementById('llm-perf-content');
|
|
98
|
+
if (!el) return;
|
|
99
|
+
const engine = metrics._engine;
|
|
100
|
+
if (!engine || Object.keys(engine).length === 0) {
|
|
101
|
+
el.innerHTML = '<p class="empty">No LLM performance data yet.</p>';
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
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>';
|
|
105
|
+
const entries = Object.entries(engine).sort((a, b) => (b[1].calls || 0) - (a[1].calls || 0));
|
|
106
|
+
for (const [type, m] of entries) {
|
|
107
|
+
const calls = m.calls || 0;
|
|
108
|
+
const totalMs = m.totalDurationMs || 0;
|
|
109
|
+
const avgMs = calls > 0 ? totalMs / calls : 0;
|
|
110
|
+
const fmtTotal = totalMs < 60000 ? Math.round(totalMs / 1000) + 's' : Math.round(totalMs / 60000) + 'm';
|
|
111
|
+
const fmtAvg = avgMs < 1000 ? Math.round(avgMs) + 'ms' : avgMs < 60000 ? Math.round(avgMs / 1000) + 's' : Math.round(avgMs / 60000) + 'm';
|
|
112
|
+
const cost = m.costUsd ? '$' + m.costUsd.toFixed(2) : '-';
|
|
113
|
+
html += '<tr><td style="font-weight:600">' + escHtml(type) + '</td>' +
|
|
114
|
+
'<td>' + calls + '</td>' +
|
|
115
|
+
'<td style="color:var(--muted)">' + (totalMs ? fmtTotal : '-') + '</td>' +
|
|
116
|
+
'<td style="color:var(--blue)">' + (avgMs ? fmtAvg : '-') + '</td>' +
|
|
117
|
+
'<td style="color:var(--muted)">' + cost + '</td></tr>';
|
|
118
|
+
}
|
|
119
|
+
html += '</tbody></table>';
|
|
120
|
+
el.innerHTML = html;
|
|
95
121
|
}
|
|
96
122
|
|
|
97
123
|
function renderTokenUsage(metrics) {
|
|
@@ -229,26 +255,6 @@ function renderTokenUsage(metrics) {
|
|
|
229
255
|
el.innerHTML = html;
|
|
230
256
|
}
|
|
231
257
|
|
|
232
|
-
function renderContextPressure(metrics) {
|
|
233
|
-
const el = document.getElementById('context-pressure-content');
|
|
234
|
-
if (!el) return;
|
|
235
|
-
const cp = metrics._contextPressure;
|
|
236
|
-
if (!cp || !cp.dispatches) {
|
|
237
|
-
el.innerHTML = '<p class="empty">No context pressure data yet. Data appears after agents complete tasks.</p>';
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
const avgTurns = (cp.totalTurns / cp.dispatches).toFixed(1);
|
|
241
|
-
const turnLimitPct = ((cp.turnLimitHits / cp.dispatches) * 100).toFixed(1);
|
|
242
|
-
const pctColor = parseFloat(turnLimitPct) > 20 ? 'var(--red)' : parseFloat(turnLimitPct) > 5 ? 'var(--yellow, orange)' : 'var(--green)';
|
|
243
|
-
|
|
244
|
-
let html = '<div class="token-tiles">';
|
|
245
|
-
html += '<div class="token-tile"><div class="token-tile-label">Avg Turns</div><div class="token-tile-value">' + avgTurns + '</div><div class="token-tile-sub">per dispatch</div></div>';
|
|
246
|
-
html += '<div class="token-tile"><div class="token-tile-label">Max Turns</div><div class="token-tile-value">' + cp.maxTurns + '</div></div>';
|
|
247
|
-
html += '<div class="token-tile"><div class="token-tile-label">Hit Turn Limit</div><div class="token-tile-value" style="color:' + pctColor + '">' + turnLimitPct + '%</div><div class="token-tile-sub">' + cp.turnLimitHits + ' of ' + cp.dispatches + ' dispatches</div></div>';
|
|
248
|
-
html += '<div class="token-tile"><div class="token-tile-label">Total Dispatches</div><div class="token-tile-value">' + cp.dispatches + '</div></div>';
|
|
249
|
-
html += '</div>';
|
|
250
|
-
el.innerHTML = html;
|
|
251
|
-
}
|
|
252
258
|
|
|
253
259
|
async function openScanProjectsModal() {
|
|
254
260
|
document.getElementById('modal-title').textContent = 'Scan for Projects';
|
|
@@ -345,4 +351,4 @@ async function _addSelectedProjects() {
|
|
|
345
351
|
}
|
|
346
352
|
}
|
|
347
353
|
|
|
348
|
-
window.MinionsOther = { renderProjects, renderMcpServers, renderMetrics,
|
|
354
|
+
window.MinionsOther = { renderProjects, renderMcpServers, renderMetrics, renderLlmPerf, renderTokenUsage, 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>
|
|
@@ -10,7 +14,3 @@
|
|
|
10
14
|
<h2>Token Usage</h2>
|
|
11
15
|
<div id="token-usage-content"><p class="empty">No usage data yet.</p></div>
|
|
12
16
|
</section>
|
|
13
|
-
<section>
|
|
14
|
-
<h2>Context Pressure</h2>
|
|
15
|
-
<div id="context-pressure-content"><p class="empty">No context pressure data yet. Data appears after agents complete tasks.</p></div>
|
|
16
|
-
</section>
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "0.1.570",
|
|
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"
|