@yemi33/minions 0.1.1802 → 0.1.1803
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 -0
- package/engine/copilot-models.json +1 -1
- package/engine.js +51 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/engine.js
CHANGED
|
@@ -407,6 +407,50 @@ function mergePendingSteeringEntries(...groups) {
|
|
|
407
407
|
return merged;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
+
function promoteCheckpointSteeringForClose(agentId, procInfo, runtime, liveOutputPath) {
|
|
411
|
+
if (!procInfo || procInfo._steeringMessage) return { status: 'none', entries: [] };
|
|
412
|
+
if (runtime?.capabilities?.midRunSessionId !== false) return { status: 'none', entries: [] };
|
|
413
|
+
|
|
414
|
+
const startedAtMs = Date.parse(procInfo.startedAt);
|
|
415
|
+
const runStartMs = Number.isFinite(startedAtMs) ? startedAtMs : 0;
|
|
416
|
+
const pendingPaths = new Set((procInfo._pendingSteeringFiles || []).map(entry => entry?.path || entry).filter(Boolean));
|
|
417
|
+
const deferredPaths = new Set((procInfo._deferredSteeringFiles || []).filter(Boolean));
|
|
418
|
+
const unread = steering.listUnreadSteeringMessages(agentId).filter(entry => entry.message.trim());
|
|
419
|
+
const entriesByPath = new Map(unread.map(entry => [entry.path, entry]));
|
|
420
|
+
const pendingDeferred = Array.from(deferredPaths)
|
|
421
|
+
.map(filePath => entriesByPath.get(filePath))
|
|
422
|
+
.filter(Boolean);
|
|
423
|
+
const lateCheckpoint = unread.filter(entry =>
|
|
424
|
+
entry.createdAtMs >= runStartMs
|
|
425
|
+
&& !pendingPaths.has(entry.path)
|
|
426
|
+
&& !deferredPaths.has(entry.path)
|
|
427
|
+
);
|
|
428
|
+
const checkpointEntries = mergePendingSteeringEntries(pendingDeferred, lateCheckpoint);
|
|
429
|
+
if (checkpointEntries.length === 0) {
|
|
430
|
+
delete procInfo._deferredSteeringFiles;
|
|
431
|
+
return { status: 'none', entries: [] };
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (!procInfo.sessionId) {
|
|
435
|
+
log('warn', `Steering: ${agentId} exited before a resumable sessionId was available - ${checkpointEntries.length} message(s) remain pending`);
|
|
436
|
+
try { fs.appendFileSync(liveOutputPath, `\n[steering-pending] Agent exited before a resumable session was available. Your message remains unread and will be retried on the next dispatch.\n`); } catch {}
|
|
437
|
+
return { status: 'pending', entries: checkpointEntries };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (pendingDeferred.length > 0) {
|
|
441
|
+
log('info', `Steering: delivering ${pendingDeferred.length} deferred message(s) for ${agentId} at resumable checkpoint`);
|
|
442
|
+
}
|
|
443
|
+
if (lateCheckpoint.length > 0) {
|
|
444
|
+
log('info', `Steering: delivering ${lateCheckpoint.length} late checkpoint message(s) for ${agentId} at resumable checkpoint`);
|
|
445
|
+
}
|
|
446
|
+
procInfo._steeringMessage = checkpointEntries.map(entry => entry.message.trim()).join('\n\n');
|
|
447
|
+
procInfo._steeringSessionId = procInfo.sessionId;
|
|
448
|
+
procInfo._steeringEntry = checkpointEntries;
|
|
449
|
+
procInfo._steeringDeferredCheckpoint = true;
|
|
450
|
+
delete procInfo._deferredSteeringFiles;
|
|
451
|
+
return { status: 'promoted', entries: checkpointEntries };
|
|
452
|
+
}
|
|
453
|
+
|
|
410
454
|
// Resolve dependency plan item IDs to their PR branches
|
|
411
455
|
function resolveDependencyBranches(depIds, sourcePlan, project, config) {
|
|
412
456
|
const results = []; // [{ branch, prId }]
|
|
@@ -1193,6 +1237,7 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
1193
1237
|
const MAX_OUTPUT = 1024 * 1024; // 1MB
|
|
1194
1238
|
let stdout = '';
|
|
1195
1239
|
let stderr = '';
|
|
1240
|
+
let steeringAckStdout = '';
|
|
1196
1241
|
const sessionCaptureState = { sessionLineBuffer: '' };
|
|
1197
1242
|
let _trustCheckDone = false;
|
|
1198
1243
|
const _spawnTime = Date.now();
|
|
@@ -1207,6 +1252,7 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
1207
1252
|
const chunk = data.toString();
|
|
1208
1253
|
realActivityMap.set(id, Date.now());
|
|
1209
1254
|
if (stdout.length < MAX_OUTPUT) stdout += chunk.slice(0, MAX_OUTPUT - stdout.length);
|
|
1255
|
+
if (steeringAckStdout.length < MAX_OUTPUT) steeringAckStdout += chunk.slice(0, MAX_OUTPUT - steeringAckStdout.length);
|
|
1210
1256
|
try { fs.appendFileSync(liveOutputPath, chunk); } catch { /* optional */ }
|
|
1211
1257
|
|
|
1212
1258
|
// Trust gate detection: check first 30s of output for trust/permission prompts
|
|
@@ -1254,26 +1300,8 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
1254
1300
|
}
|
|
1255
1301
|
|
|
1256
1302
|
const procInfo = activeProcesses.get(id);
|
|
1257
|
-
ackPendingSteeringFiles(agentId, procInfo,
|
|
1258
|
-
|
|
1259
|
-
if (procInfo?._deferredSteeringFiles?.length && procInfo.sessionId) {
|
|
1260
|
-
const deferredPaths = new Set(procInfo._deferredSteeringFiles);
|
|
1261
|
-
const pendingDeferred = steering.listUnreadSteeringMessages(agentId)
|
|
1262
|
-
.filter(entry => deferredPaths.has(entry.path) && entry.message.trim());
|
|
1263
|
-
if (pendingDeferred.length > 0) {
|
|
1264
|
-
log('info', `Steering: delivering ${pendingDeferred.length} deferred message(s) for ${agentId} at resumable checkpoint`);
|
|
1265
|
-
procInfo._steeringMessage = pendingDeferred.map(entry => entry.message.trim()).join('\n\n');
|
|
1266
|
-
procInfo._steeringSessionId = procInfo.sessionId;
|
|
1267
|
-
procInfo._steeringEntry = pendingDeferred;
|
|
1268
|
-
procInfo._steeringDeferredCheckpoint = true;
|
|
1269
|
-
delete procInfo._deferredSteeringFiles;
|
|
1270
|
-
} else {
|
|
1271
|
-
delete procInfo._deferredSteeringFiles;
|
|
1272
|
-
}
|
|
1273
|
-
} else if (procInfo?._deferredSteeringFiles?.length) {
|
|
1274
|
-
log('warn', `Steering: ${agentId} exited before a resumable sessionId was available — message remains pending`);
|
|
1275
|
-
try { fs.appendFileSync(liveOutputPath, `\n[steering-pending] Agent exited before a resumable session was available. Your message remains unread and will be retried on the next dispatch.\n`); } catch {}
|
|
1276
|
-
}
|
|
1303
|
+
ackPendingSteeringFiles(agentId, procInfo, steeringAckStdout);
|
|
1304
|
+
promoteCheckpointSteeringForClose(agentId, procInfo, runtime, liveOutputPath);
|
|
1277
1305
|
|
|
1278
1306
|
// Check if this was a steering kill — re-spawn with resume
|
|
1279
1307
|
if (procInfo?._steeringMessage) {
|
|
@@ -1401,6 +1429,7 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
1401
1429
|
),
|
|
1402
1430
|
});
|
|
1403
1431
|
|
|
1432
|
+
steeringAckStdout = '';
|
|
1404
1433
|
// Live steering kills discard partial old output. Deferred checkpoint
|
|
1405
1434
|
// steering keeps the completed turn output so completion parsing still
|
|
1406
1435
|
// sees the original work if the follow-up only acknowledges steering.
|
|
@@ -1414,6 +1443,7 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
1414
1443
|
const chunk = data.toString();
|
|
1415
1444
|
realActivityMap.set(id, Date.now());
|
|
1416
1445
|
if (stdout.length < MAX_OUTPUT) stdout += chunk.slice(0, MAX_OUTPUT - stdout.length);
|
|
1446
|
+
if (steeringAckStdout.length < MAX_OUTPUT) steeringAckStdout += chunk.slice(0, MAX_OUTPUT - steeringAckStdout.length);
|
|
1417
1447
|
try { fs.appendFileSync(liveOutputPath, chunk); } catch { /* optional */ }
|
|
1418
1448
|
const resumeInfo = activeProcesses.get(id);
|
|
1419
1449
|
markRuntimeResumeOutputSeen(resumeInfo);
|
|
@@ -4719,6 +4749,7 @@ module.exports = {
|
|
|
4719
4749
|
parseConflictFiles, pruneAncestorDeps, preflightMergeSimulation, // exported for testing
|
|
4720
4750
|
isWorktreeRetryableError, removeStaleIndexLock, syncReusedWorktree, // exported for testing
|
|
4721
4751
|
_maxTurnsForType, buildProjectContext, normalizeAc, _buildAgentSpawnFlags, _classifyAgentFailure, // exported for testing
|
|
4752
|
+
promoteCheckpointSteeringForClose, // exported for testing
|
|
4722
4753
|
normalizePrBranch, resolvePrBranch, prCausePart, getPrCauseHead, getPrCauseBase, getPrAutomationCauseKey, getPrAutomationDispatchKey, // exported for testing
|
|
4723
4754
|
|
|
4724
4755
|
// Playbooks
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1803",
|
|
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"
|