@yemi33/minions 0.1.146 β 0.1.147
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 +13 -0
- package/dashboard/js/render-work-items.js +3 -0
- package/engine/lifecycle.js +41 -0
- package/engine/shared.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.147 (2026-04-01)
|
|
4
|
+
|
|
5
|
+
### Engine
|
|
6
|
+
- engine/lifecycle.js
|
|
7
|
+
- engine/shared.js
|
|
8
|
+
|
|
9
|
+
### Dashboard
|
|
10
|
+
- dashboard/js/render-work-items.js
|
|
11
|
+
|
|
12
|
+
### Other
|
|
13
|
+
- .github/workflows/pr-tests.yml
|
|
14
|
+
- test/unit.test.js
|
|
15
|
+
|
|
3
16
|
## 0.1.146 (2026-04-01)
|
|
4
17
|
|
|
5
18
|
### Engine
|
|
@@ -388,6 +388,9 @@ function openWorkItemDetail(id) {
|
|
|
388
388
|
if (item.references?.length) html += field('References', item.references.map(r => '<a href="' + escHtml(r.url) + '" target="_blank" style="color:var(--blue)">' + escHtml(r.title || r.url) + '</a>' + (r.type ? ' <span style="color:var(--muted);font-size:10px">(' + escHtml(r.type) + ')</span>' : '')).join('<br>'));
|
|
389
389
|
if (item._humanFeedback) html += field('Human Feedback', (item._humanFeedback.rating === 'up' ? 'π' : 'π') + (item._humanFeedback.comment ? ' β ' + escHtml(item._humanFeedback.comment) : ''));
|
|
390
390
|
if (item._pr) html += field('Pull Request', '<a href="' + escHtml(item._prUrl || '#') + '" target="_blank" style="color:var(--blue)">' + escHtml(item._pr) + '</a>');
|
|
391
|
+
if (item._totalCostUsd != null) html += field('Cumulative Cost', '$' + Number(item._totalCostUsd).toFixed(4));
|
|
392
|
+
if (item._totalInputTokens) html += field('Total Input Tokens', Number(item._totalInputTokens).toLocaleString());
|
|
393
|
+
if (item._totalOutputTokens) html += field('Total Output Tokens', Number(item._totalOutputTokens).toLocaleString());
|
|
391
394
|
html += '</div>';
|
|
392
395
|
|
|
393
396
|
document.getElementById('modal-title').textContent = item.title || item.id;
|
package/engine/lifecycle.js
CHANGED
|
@@ -1153,6 +1153,47 @@ function runPostCompletionHooks(dispatchItem, agentId, code, stdout, config) {
|
|
|
1153
1153
|
} catch (err) { log('warn', `Session save: ${err.message}`); }
|
|
1154
1154
|
}
|
|
1155
1155
|
|
|
1156
|
+
// ββ Accumulate per-work-item cost tracking ββββββββββββββββββββββββββββββββββ
|
|
1157
|
+
if (taskUsage && meta?.item?.id) {
|
|
1158
|
+
try {
|
|
1159
|
+
const wiPath = meta.source === 'central-work-item' || meta.source === 'central-work-item-fanout'
|
|
1160
|
+
? path.join(MINIONS_DIR, 'work-items.json')
|
|
1161
|
+
: meta.project?.name ? path.join(MINIONS_DIR, 'projects', meta.project.name, 'work-items.json') : null;
|
|
1162
|
+
if (wiPath) {
|
|
1163
|
+
mutateJsonFileLocked(wiPath, (items) => {
|
|
1164
|
+
if (!Array.isArray(items)) return items;
|
|
1165
|
+
const wi = items.find(i => i.id === meta.item.id);
|
|
1166
|
+
if (wi) {
|
|
1167
|
+
wi._totalCostUsd = (wi._totalCostUsd || 0) + (taskUsage.costUsd || 0);
|
|
1168
|
+
wi._totalInputTokens = (wi._totalInputTokens || 0) + (taskUsage.inputTokens || 0);
|
|
1169
|
+
wi._totalOutputTokens = (wi._totalOutputTokens || 0) + (taskUsage.outputTokens || 0);
|
|
1170
|
+
}
|
|
1171
|
+
return items;
|
|
1172
|
+
}, { defaultValue: [] });
|
|
1173
|
+
|
|
1174
|
+
// Cost ceiling circuit breaker β treat like evalMaxIterations exceeded
|
|
1175
|
+
const engineCfg = config?.engine || {};
|
|
1176
|
+
const evalMaxCost = engineCfg.evalMaxCost != null ? engineCfg.evalMaxCost : shared.ENGINE_DEFAULTS.evalMaxCost;
|
|
1177
|
+
if (evalMaxCost != null && evalMaxCost > 0) {
|
|
1178
|
+
const freshItems = safeJson(wiPath) || [];
|
|
1179
|
+
const wi = freshItems.find(i => i.id === meta.item.id);
|
|
1180
|
+
if (wi && wi._totalCostUsd > evalMaxCost && wi.status !== 'needs-human-review') {
|
|
1181
|
+
mutateJsonFileLocked(wiPath, (items) => {
|
|
1182
|
+
if (!Array.isArray(items)) return items;
|
|
1183
|
+
const target = items.find(i => i.id === meta.item.id);
|
|
1184
|
+
if (target) {
|
|
1185
|
+
target.status = 'needs-human-review';
|
|
1186
|
+
target.failReason = `Cumulative cost $${wi._totalCostUsd.toFixed(2)} exceeds evalMaxCost ceiling $${evalMaxCost.toFixed(2)}`;
|
|
1187
|
+
log('warn', `Work item ${meta.item.id} exceeded cost ceiling ($${wi._totalCostUsd.toFixed(2)} > $${evalMaxCost.toFixed(2)}) β needs-human-review`);
|
|
1188
|
+
}
|
|
1189
|
+
return items;
|
|
1190
|
+
}, { defaultValue: [] });
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
} catch (err) { log('warn', `Cost accumulation: ${err.message}`); }
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1156
1197
|
// Handle decomposition results β create sub-items from decompose agent output
|
|
1157
1198
|
let skipDoneStatus = false;
|
|
1158
1199
|
if (type === 'decompose' && isSuccess && meta?.item?.id) {
|
package/engine/shared.js
CHANGED
|
@@ -358,6 +358,7 @@ const ENGINE_DEFAULTS = {
|
|
|
358
358
|
meetingRoundTimeout: 600000, // 10min per meeting round before auto-advance
|
|
359
359
|
evalLoop: true, // enable evaluateβfix loop after implementation completes
|
|
360
360
|
evalMaxIterations: 3, // max evaluateβfix cycles before escalating to human
|
|
361
|
+
evalMaxCost: null, // USD ceiling per work item across all eval iterations; null = no limit (gather baseline data first)
|
|
361
362
|
};
|
|
362
363
|
|
|
363
364
|
const DEFAULT_AGENTS = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.147",
|
|
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"
|