@yemi33/minions 0.1.1772 → 0.1.1773
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 +4 -1
- package/README.md +10 -0
- package/bin/minions.js +15 -1
- package/dashboard/js/modal-qa.js +37 -4
- package/dashboard.js +35 -4
- package/engine/copilot-models.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1773 (2026-05-07)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
|
+
- fix doc chat sticky scroll (#2176)
|
|
7
|
+
- fix live output route and CLI docs (#2172)
|
|
8
|
+
- make API project resolution strict (#2169)
|
|
6
9
|
- fix copilot cc resume context (#2166)
|
|
7
10
|
|
|
8
11
|
## 0.1.1771 (2026-05-07)
|
package/README.md
CHANGED
|
@@ -127,21 +127,31 @@ minions work "Explore the codebase and document the architecture"
|
|
|
127
127
|
| `minions init` | Bootstrap `~/.minions/` with default agents and config |
|
|
128
128
|
| `minions update` | Update to latest version (npm update + apply) |
|
|
129
129
|
| `minions version` | Show installed vs package version |
|
|
130
|
+
| `minions doctor` | Check prerequisites and runtime health |
|
|
130
131
|
| `minions scan [dir] [depth]` | Scan for git repos and multi-select to add (default: ~, depth 3) |
|
|
131
132
|
| `minions add <dir>` | Link a single project (auto-detects settings from git, prompts to confirm) |
|
|
132
133
|
| `minions remove <dir-or-name> [--keep-data \| --purge --force]` | Unlink a project: cancels pending work items, drains dispatch + kills active agents, cleans worktrees, disables linked schedules, archives `projects/<name>/` to `projects/.archived/<name>-YYYYMMDD/`. Use `--keep-data` to leave the data dir in place, or `--purge --force` to delete it. |
|
|
133
134
|
| `minions list` | List all linked projects with descriptions |
|
|
135
|
+
| `minions restart` | Start engine and dashboard together (recommended after reboot) |
|
|
134
136
|
| `minions start` | Start engine daemon (ticks every 60s, auto-syncs MCP servers) |
|
|
135
137
|
| `minions stop` | Stop the engine |
|
|
136
138
|
| `minions status` | Show agents, projects, dispatch queue, quality metrics |
|
|
137
139
|
| `minions pause` / `resume` | Pause/resume dispatching |
|
|
138
140
|
| `minions dispatch` | Force a dispatch cycle |
|
|
139
141
|
| `minions discover` | Dry-run work discovery |
|
|
142
|
+
| `minions queue` | Show dispatch queue (pending, active, completed) |
|
|
143
|
+
| `minions sources` | Show work source status per project |
|
|
140
144
|
| `minions work <title> [opts]` | Add to central work queue |
|
|
141
145
|
| `minions spawn <agent> <prompt>` | Manually spawn an agent |
|
|
142
146
|
| `minions plan <file\|text> [proj]` | Run a plan |
|
|
147
|
+
| `minions kill` | Kill all active agents and reset their dispatches to pending |
|
|
148
|
+
| `minions complete <dispatch-id>` | Manually mark a dispatch as completed |
|
|
149
|
+
| `minions config set-cli <R> [--model M]` | Persist the default runtime/model without starting the engine |
|
|
150
|
+
| `minions mcp-sync` | Sync MCP servers from `~/.claude.json` |
|
|
143
151
|
| `minions cleanup` | Run cleanup manually (temp files, worktrees, zombies) |
|
|
144
152
|
| `minions dash` | Open dashboard (starts if not already running, port 7331) |
|
|
153
|
+
| `minions nuke --confirm` | Factory reset runtime state and reset config to defaults |
|
|
154
|
+
| `minions uninstall --confirm` | Remove Minions state and uninstall the npm package |
|
|
145
155
|
|
|
146
156
|
You can also run scripts directly: `node ~/.minions/engine.js start`, `node ~/.minions/dashboard.js`, etc.
|
|
147
157
|
|
package/bin/minions.js
CHANGED
|
@@ -8,18 +8,29 @@
|
|
|
8
8
|
* minions add <project-dir> Link a project (interactive)
|
|
9
9
|
* minions remove <project-dir> Unlink a project
|
|
10
10
|
* minions list List linked projects
|
|
11
|
+
* minions update Update to latest version
|
|
12
|
+
* minions version Show installed and package versions
|
|
13
|
+
* minions doctor Check prerequisites and runtime health
|
|
14
|
+
* minions restart Start engine + dashboard
|
|
11
15
|
* minions start Start the engine
|
|
12
16
|
* minions stop Stop the engine
|
|
13
17
|
* minions status Show engine status
|
|
14
18
|
* minions pause / resume Pause/resume dispatching
|
|
19
|
+
* minions queue Show dispatch queue
|
|
20
|
+
* minions sources Show work source status
|
|
15
21
|
* minions dash Start the dashboard
|
|
16
22
|
* minions work <title> [opts-json] Add a work item
|
|
17
23
|
* minions spawn <agent> <prompt> Manually spawn an agent
|
|
18
24
|
* minions dispatch Force a dispatch cycle
|
|
19
25
|
* minions discover Dry-run work discovery
|
|
20
26
|
* minions cleanup Run cleanup manually
|
|
27
|
+
* minions kill Kill active agents and reset to pending
|
|
28
|
+
* minions complete <dispatch-id> Mark a dispatch completed
|
|
29
|
+
* minions config set-cli <R> [--model M] Persist default runtime/model
|
|
21
30
|
* minions plan <file|text> [proj] Run a plan
|
|
22
|
-
* minions
|
|
31
|
+
* minions mcp-sync Sync MCP servers from ~/.claude.json
|
|
32
|
+
* minions nuke --confirm Factory reset runtime state/config
|
|
33
|
+
* minions uninstall --confirm Remove Minions and uninstall package
|
|
23
34
|
*/
|
|
24
35
|
|
|
25
36
|
const fs = require('fs');
|
|
@@ -642,6 +653,9 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
|
642
653
|
minions plan <file|text> [proj] Run a plan
|
|
643
654
|
minions kill Kill all active agents and reset to pending
|
|
644
655
|
minions complete <dispatch-id> Manually mark a dispatch as completed
|
|
656
|
+
minions config set-cli <R> [--model M]
|
|
657
|
+
Persist default runtime/model without starting
|
|
658
|
+
minions mcp-sync Sync MCP servers from ~/.claude.json
|
|
645
659
|
minions cleanup Clean temp files, worktrees, zombies
|
|
646
660
|
minions nuke --confirm Factory reset (delete state, reset config to defaults)
|
|
647
661
|
minions uninstall --confirm Remove everything + uninstall npm package
|
package/dashboard/js/modal-qa.js
CHANGED
|
@@ -30,6 +30,32 @@ const QA_QUEUE_CAP = 10; // max queued messages
|
|
|
30
30
|
const QA_STREAM_STALL_MS = 6 * 60 * 1000; // allow the full doc-chat timeout before treating heartbeat-only streams as stalled
|
|
31
31
|
let _qaSessionKey = ''; // key for current conversation (title or filePath)
|
|
32
32
|
|
|
33
|
+
const QA_STICKY_BOTTOM_PX = 80;
|
|
34
|
+
let _qaThreadShouldFollow = true;
|
|
35
|
+
|
|
36
|
+
function _qaIsNearThreadBottom(thread) {
|
|
37
|
+
if (!thread) return true;
|
|
38
|
+
return thread.scrollHeight - thread.scrollTop - thread.clientHeight <= QA_STICKY_BOTTOM_PX;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function _qaShouldFollowThread(thread) {
|
|
42
|
+
return _qaThreadShouldFollow && _qaIsNearThreadBottom(thread);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function _qaSetThreadFollowFromScroll(thread) {
|
|
46
|
+
_qaThreadShouldFollow = _qaIsNearThreadBottom(thread);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function _qaScrollThreadToBottom(thread) {
|
|
50
|
+
if (!thread) return;
|
|
51
|
+
thread.scrollTop = thread.scrollHeight;
|
|
52
|
+
_qaThreadShouldFollow = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function _qaMaybeScrollThreadToBottom(thread, shouldFollow) {
|
|
56
|
+
if (shouldFollow) _qaScrollThreadToBottom(thread);
|
|
57
|
+
}
|
|
58
|
+
|
|
33
59
|
// Insert html at the bottom of the thread but above any pending "Queued: ..."
|
|
34
60
|
// strips, so queued messages always remain visually below the active progress
|
|
35
61
|
// UX / answer / errors.
|
|
@@ -47,7 +73,7 @@ function _renderQaUserMessage(thread, message, selection) {
|
|
|
47
73
|
}
|
|
48
74
|
qHtml += '</div>';
|
|
49
75
|
_qaInsertBeforeQueued(thread, qHtml);
|
|
50
|
-
thread
|
|
76
|
+
_qaScrollThreadToBottom(thread);
|
|
51
77
|
_showThreadWrap();
|
|
52
78
|
}
|
|
53
79
|
const _qaSessions = new Map(); // persist conversations across modal open/close {key → {history, threadHtml}}
|
|
@@ -91,6 +117,10 @@ function _qaThreadEl() {
|
|
|
91
117
|
return document.getElementById('modal-qa-thread');
|
|
92
118
|
}
|
|
93
119
|
|
|
120
|
+
document.addEventListener('scroll', function(e) {
|
|
121
|
+
if (e.target && e.target.id === 'modal-qa-thread') _qaSetThreadFollowFromScroll(e.target);
|
|
122
|
+
}, true);
|
|
123
|
+
|
|
94
124
|
function _qaThreadHtml() {
|
|
95
125
|
return (_qaThreadEl() || {}).innerHTML || '';
|
|
96
126
|
}
|
|
@@ -308,8 +338,9 @@ function _qaMutateThreadHtml(key, mutate) {
|
|
|
308
338
|
const wasCollapsed = _qaIsThreadCollapsed();
|
|
309
339
|
const thread = _qaThreadEl();
|
|
310
340
|
if (thread) {
|
|
341
|
+
const shouldFollow = _qaShouldFollowThread(thread);
|
|
311
342
|
thread.innerHTML = html;
|
|
312
|
-
thread
|
|
343
|
+
_qaMaybeScrollThreadToBottom(thread, shouldFollow);
|
|
313
344
|
}
|
|
314
345
|
if (wasCollapsed) _setQaThreadCollapsed(true);
|
|
315
346
|
else _showThreadWrap();
|
|
@@ -386,7 +417,7 @@ function _initQaSession() {
|
|
|
386
417
|
_showThreadWrap();
|
|
387
418
|
requestAnimationFrame(function() {
|
|
388
419
|
var thread = document.getElementById('modal-qa-thread');
|
|
389
|
-
|
|
420
|
+
_qaScrollThreadToBottom(thread);
|
|
390
421
|
});
|
|
391
422
|
if (_qaQueue.length > 0 && !_qaProcessing) {
|
|
392
423
|
setTimeout(_qaResumeQueuedMessages, 0);
|
|
@@ -394,6 +425,7 @@ function _initQaSession() {
|
|
|
394
425
|
} else {
|
|
395
426
|
_qaHistory = [];
|
|
396
427
|
document.getElementById('modal-qa-thread').innerHTML = '';
|
|
428
|
+
_qaThreadShouldFollow = true;
|
|
397
429
|
var wrap = document.getElementById('modal-qa-thread-wrap');
|
|
398
430
|
var expandBar = document.getElementById('qa-expand-bar');
|
|
399
431
|
if (wrap) wrap.style.display = 'none';
|
|
@@ -410,6 +442,7 @@ function clearQaConversation() {
|
|
|
410
442
|
_qaProcessing = false;
|
|
411
443
|
_qaAbortController = null;
|
|
412
444
|
document.getElementById('modal-qa-thread').innerHTML = '';
|
|
445
|
+
_qaThreadShouldFollow = true;
|
|
413
446
|
var wrap = document.getElementById('modal-qa-thread-wrap');
|
|
414
447
|
var expandBar = document.getElementById('qa-expand-bar');
|
|
415
448
|
if (wrap) wrap.style.display = 'none';
|
|
@@ -455,7 +488,7 @@ function modalSend() {
|
|
|
455
488
|
}
|
|
456
489
|
_qaQueue.push({ message, selection });
|
|
457
490
|
thread.insertAdjacentHTML('beforeend', _qaBuildQueuedHtml(message));
|
|
458
|
-
thread
|
|
491
|
+
_qaScrollThreadToBottom(thread);
|
|
459
492
|
_showThreadWrap();
|
|
460
493
|
_qaSaveActiveSessionState();
|
|
461
494
|
return;
|
package/dashboard.js
CHANGED
|
@@ -281,12 +281,23 @@ function createWorkItemWithDedup(wiPath, item, options = {}) {
|
|
|
281
281
|
return result || { created: false, item: null };
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
function formatUnknownProjectError(projectName, projects = []) {
|
|
285
|
+
const known = projects.map(p => p.name).filter(Boolean).join(', ') || '(none configured)';
|
|
286
|
+
return `Project "${projectName}" not found. Known projects: ${known}`;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function findProjectByName(projects, projectName) {
|
|
290
|
+
const name = String(projectName || '').trim().toLowerCase();
|
|
291
|
+
if (!name) return null;
|
|
292
|
+
return projects.find(p => p.name?.toLowerCase() === name) || null;
|
|
293
|
+
}
|
|
294
|
+
|
|
284
295
|
function resolveWorkItemsCreateTarget(projectName, projects = PROJECTS) {
|
|
285
296
|
const project = String(projectName || '').trim();
|
|
286
297
|
let targetProject = null;
|
|
287
298
|
if (project) {
|
|
288
|
-
targetProject = projects
|
|
289
|
-
if (!targetProject) return { error:
|
|
299
|
+
targetProject = findProjectByName(projects, project);
|
|
300
|
+
if (!targetProject) return { error: formatUnknownProjectError(project, projects) };
|
|
290
301
|
} else if (projects.length === 1) {
|
|
291
302
|
targetProject = projects[0];
|
|
292
303
|
}
|
|
@@ -326,7 +337,13 @@ function linkPullRequestForTracking({ url, title, project: projectName, autoObse
|
|
|
326
337
|
throw err;
|
|
327
338
|
}
|
|
328
339
|
const projects = shared.getProjects(config);
|
|
329
|
-
const
|
|
340
|
+
const explicitProjectName = String(projectName || '').trim();
|
|
341
|
+
const targetProject = explicitProjectName ? findProjectByName(projects, explicitProjectName) : (projects[0] || null);
|
|
342
|
+
if (explicitProjectName && !targetProject) {
|
|
343
|
+
const err = new Error(formatUnknownProjectError(explicitProjectName, projects));
|
|
344
|
+
err.statusCode = 400;
|
|
345
|
+
throw err;
|
|
346
|
+
}
|
|
330
347
|
const prPath = targetProject ? shared.projectPrPath(targetProject) : path.join(MINIONS_DIR, 'pull-requests.json');
|
|
331
348
|
|
|
332
349
|
const prNumMatch = url.match(/\/pull\/(\d+)|pullrequest\/(\d+)/);
|
|
@@ -7121,6 +7138,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7121
7138
|
if (!url) return jsonReply(res, 400, { error: 'url required' });
|
|
7122
7139
|
|
|
7123
7140
|
reloadConfig();
|
|
7141
|
+
const explicitProjectName = String(body.project || '').trim();
|
|
7142
|
+
if (explicitProjectName) {
|
|
7143
|
+
const projects = shared.getProjects(CONFIG);
|
|
7144
|
+
if (!findProjectByName(projects, explicitProjectName)) {
|
|
7145
|
+
return jsonReply(res, 400, { error: formatUnknownProjectError(explicitProjectName, projects) }, req);
|
|
7146
|
+
}
|
|
7147
|
+
}
|
|
7124
7148
|
const adoTarget = parseAdoPrMetadataTarget(url);
|
|
7125
7149
|
let initialPrData = null;
|
|
7126
7150
|
if (adoTarget) {
|
|
@@ -7130,7 +7154,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7130
7154
|
shared.log('warn', `ADO PR link metadata fetch failed for ${url}: ${e.message}`);
|
|
7131
7155
|
}
|
|
7132
7156
|
}
|
|
7133
|
-
|
|
7157
|
+
let linkResult;
|
|
7158
|
+
try {
|
|
7159
|
+
linkResult = linkPullRequestForTracking(body, CONFIG, { metadata: initialPrData });
|
|
7160
|
+
} catch (e) {
|
|
7161
|
+
return jsonReply(res, e.statusCode || 400, { error: e.message }, req);
|
|
7162
|
+
}
|
|
7163
|
+
const { id: prId, prPath, prNum, created, linked } = linkResult;
|
|
7134
7164
|
invalidateStatusCache();
|
|
7135
7165
|
jsonReply(res, 200, { ok: true, id: prId, created, linked });
|
|
7136
7166
|
|
|
@@ -7268,6 +7298,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7268
7298
|
{ method: 'POST', path: /^\/api\/agent\/([\w-]+)\/kill$/, desc: 'Kill a running agent: stop process, clear dispatch, reset work items to pending', handler: handleAgentKill },
|
|
7269
7299
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/live-stream(?:\?.*)?$/, desc: 'SSE real-time live output streaming', handler: handleAgentLiveStream },
|
|
7270
7300
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/live(?:\?.*)?$/, desc: 'Tail live output for a working agent', params: 'tail? (bytes, default 8192)', handler: handleAgentLive },
|
|
7301
|
+
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/live-output(?:\?.*)?$/, desc: 'Tail live output for a working agent (alias for /live)', params: 'tail? (bytes, default 8192)', handler: handleAgentLive },
|
|
7271
7302
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/output(?:\?.*)?$/, desc: 'Fetch final output.log for an agent', handler: handleAgentOutput },
|
|
7272
7303
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)$/, desc: 'Get detailed agent info', handler: handleAgentDetail },
|
|
7273
7304
|
{ method: 'GET', path: /^\/api\/dispatch\/([\w.-]+)\/completion-report$/, desc: 'Read structured completion report for a dispatch', handler: (req, res, match) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1773",
|
|
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"
|