@yemi33/minions 0.1.417 → 0.1.419
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 +9 -0
- package/engine/dispatch.js +1 -1
- package/engine/lifecycle.js +1 -0
- package/engine/pipeline.js +30 -13
- package/engine/shared.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.419 (2026-04-06)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- Fix 6 medium bugs: dispatch pruning, null guards, skill regex, meeting advancement, CLI PID check, pipeline retry
|
|
7
|
+
- Convert remaining lifecycle.js safeWrite calls to mutateJsonFileLocked
|
|
8
|
+
|
|
9
|
+
### Fixes
|
|
10
|
+
- address review feedback — pipeline.js socket leak and magic numbers
|
|
11
|
+
|
|
3
12
|
## 0.1.417 (2026-04-06)
|
|
4
13
|
|
|
5
14
|
### Features
|
package/engine/dispatch.js
CHANGED
|
@@ -87,7 +87,7 @@ function completeDispatch(id, result = DISPATCH_RESULT.SUCCESS, reason = '', res
|
|
|
87
87
|
if (reason) item.reason = reason;
|
|
88
88
|
if (resultSummary) item.resultSummary = resultSummary;
|
|
89
89
|
delete item.prompt;
|
|
90
|
-
if (dispatch.completed.length
|
|
90
|
+
if (dispatch.completed.length >= 100) {
|
|
91
91
|
dispatch.completed = dispatch.completed.slice(-100);
|
|
92
92
|
}
|
|
93
93
|
dispatch.completed.push(item);
|
package/engine/lifecycle.js
CHANGED
|
@@ -901,6 +901,7 @@ function extractSkillsFromOutput(output, agentId, dispatchItem, config) {
|
|
|
901
901
|
if (!fullText) fullText = output;
|
|
902
902
|
const skillBlocks = [];
|
|
903
903
|
const skillRegex = /```skill\s*\n([\s\S]*?)```/g;
|
|
904
|
+
skillRegex.lastIndex = 0;
|
|
904
905
|
let match;
|
|
905
906
|
while ((match = skillRegex.exec(fullText)) !== null) {
|
|
906
907
|
skillBlocks.push(match[1].trim());
|
package/engine/pipeline.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const shared = require('./shared');
|
|
10
|
-
const { safeJson, safeWrite, safeRead, safeReadDir, uid, log, ts, dateStamp, mutateJsonFileLocked, WI_STATUS, WORK_TYPE, PLAN_STATUS, PR_STATUS, PIPELINE_STATUS, STAGE_TYPE, MEETING_STATUS } = shared;
|
|
10
|
+
const { safeJson, safeWrite, safeRead, safeReadDir, uid, log, ts, dateStamp, mutateJsonFileLocked, WI_STATUS, WORK_TYPE, PLAN_STATUS, PR_STATUS, PIPELINE_STATUS, STAGE_TYPE, MEETING_STATUS, ENGINE_DEFAULTS } = shared;
|
|
11
|
+
const http = require('http');
|
|
11
12
|
const { parseCronExpr, shouldRunNow } = require('./scheduler');
|
|
12
13
|
|
|
13
14
|
const PIPELINES_DIR = path.join(__dirname, '..', 'pipelines');
|
|
@@ -313,18 +314,34 @@ function executeApiStage(stage, stageState, run) {
|
|
|
313
314
|
for (const call of calls) {
|
|
314
315
|
const url = `http://localhost:${process.env.MINIONS_PORT || 7331}${call.endpoint}`;
|
|
315
316
|
const body = typeof call.body === 'string' ? call.body : JSON.stringify(call.body || {});
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
317
|
+
const maxAttempts = ENGINE_DEFAULTS.pipelineApiRetries;
|
|
318
|
+
const retryDelay = ENGINE_DEFAULTS.pipelineApiRetryDelay;
|
|
319
|
+
const makeRequest = (attempt) => {
|
|
320
|
+
try {
|
|
321
|
+
const parsed = new URL(url);
|
|
322
|
+
const req = http.request({
|
|
323
|
+
hostname: parsed.hostname, port: parsed.port, path: parsed.pathname,
|
|
324
|
+
method: call.method || 'POST',
|
|
325
|
+
headers: { 'Content-Type': 'application/json' },
|
|
326
|
+
}, (res) => {
|
|
327
|
+
res.resume(); // drain body to free socket
|
|
328
|
+
if (res.statusCode >= 400) {
|
|
329
|
+
log('warn', `Pipeline API call to ${call.endpoint} returned ${res.statusCode} (attempt ${attempt})`);
|
|
330
|
+
if (attempt < maxAttempts) setTimeout(() => makeRequest(attempt + 1), retryDelay);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
req.on('error', (err) => {
|
|
334
|
+
log('warn', `Pipeline API call to ${call.endpoint} failed: ${err.message} (attempt ${attempt})`);
|
|
335
|
+
if (attempt < maxAttempts) setTimeout(() => makeRequest(attempt + 1), retryDelay);
|
|
336
|
+
});
|
|
337
|
+
req.write(body);
|
|
338
|
+
req.end();
|
|
339
|
+
} catch (e) {
|
|
340
|
+
log('warn', `Pipeline API call to ${call.endpoint} threw: ${e.message} (attempt ${attempt})`);
|
|
341
|
+
if (attempt < maxAttempts) setTimeout(() => makeRequest(attempt + 1), retryDelay);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
makeRequest(1);
|
|
328
345
|
}
|
|
329
346
|
return { status: PIPELINE_STATUS.COMPLETED, completedAt: ts() };
|
|
330
347
|
}
|
package/engine/shared.js
CHANGED
|
@@ -438,6 +438,8 @@ const ENGINE_DEFAULTS = {
|
|
|
438
438
|
evalMaxIterations: 3, // max review→fix cycles before escalating to human
|
|
439
439
|
evalMaxCost: null, // USD ceiling per work item across all eval iterations; null = no limit (gather baseline data first)
|
|
440
440
|
maxRetries: 3, // max dispatch retries before marking work item as failed
|
|
441
|
+
pipelineApiRetries: 2, // max attempts for pipeline API calls
|
|
442
|
+
pipelineApiRetryDelay: 2000, // ms delay between pipeline API retries
|
|
441
443
|
};
|
|
442
444
|
|
|
443
445
|
// ─── Status & Type Constants ─────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.419",
|
|
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"
|