@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 +2 -1
- package/dashboard/js/render-other.js +29 -1
- package/dashboard/pages/engine.html +4 -0
- package/engine/llm.js +9 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -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
|
-
|
|
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.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"
|