@yemi33/minions 0.1.1751 → 0.1.1753
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 +12 -2
- package/dashboard/js/render-other.js +4 -3
- package/dashboard/js/render-prd.js +11 -0
- package/dashboard.js +23 -53
- package/engine/copilot-models.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1753 (2026-05-06)
|
|
4
|
+
|
|
5
|
+
### Other
|
|
6
|
+
- refactor(doc-chat): drop brittle regex action gate in favour of sysprompt
|
|
7
|
+
|
|
8
|
+
## 0.1.1752 (2026-05-06)
|
|
4
9
|
|
|
5
10
|
### Features
|
|
6
|
-
-
|
|
11
|
+
- bring PRD graph view to parity with list view
|
|
12
|
+
|
|
13
|
+
### Other
|
|
14
|
+
- Show Copilot MCPs in dashboard
|
|
15
|
+
|
|
16
|
+
## 0.1.1750 (2026-05-06)
|
|
7
17
|
|
|
8
18
|
### Fixes
|
|
9
19
|
- lock doc-chat into plain-response mode (no tool calls) (#2127)
|
|
@@ -85,17 +85,18 @@ function renderMcpServers(servers) {
|
|
|
85
85
|
const countEl = document.getElementById('mcp-count');
|
|
86
86
|
countEl.textContent = servers.length;
|
|
87
87
|
if (!servers.length) {
|
|
88
|
-
el.innerHTML = '<p class="empty">No MCP servers found. Add them to <code>~/.claude.json</code> and they\'ll appear here automatically.</p>';
|
|
88
|
+
el.innerHTML = '<p class="empty">No MCP servers found. Add them to <code>~/.claude.json</code> or <code>~/.copilot/mcp-config.json</code> and they\'ll appear here automatically.</p>';
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
el.innerHTML = '<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px">' +
|
|
92
92
|
servers.map(s =>
|
|
93
|
-
'<div style="font-size:11px;padding:5px 10px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text)" title="' + escHtml(s.args || s.command) + '">' +
|
|
93
|
+
'<div style="font-size:11px;padding:5px 10px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text)" title="' + escHtml([s.source, s.args || s.command].filter(Boolean).join(': ')) + '">' +
|
|
94
94
|
escHtml(s.name) +
|
|
95
|
+
(s.source ? ' <span style="color:var(--muted)">(' + escHtml(s.source) + ')</span>' : '') +
|
|
95
96
|
'</div>'
|
|
96
97
|
).join('') +
|
|
97
98
|
'</div>' +
|
|
98
|
-
'<p style="font-size:10px;color:var(--muted);margin:0">Synced from <code style="color:var(--blue)">~/.claude.json</code>
|
|
99
|
+
'<p style="font-size:10px;color:var(--muted);margin:0">Synced from <code style="color:var(--blue)">~/.claude.json</code> and <code style="color:var(--blue)">~/.copilot/mcp-config.json</code>.</p>';
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
function renderMetrics(metrics) {
|
|
@@ -406,12 +406,22 @@ function renderPrdProgress(prog) {
|
|
|
406
406
|
const agentDisplay = agentInfo ? (agentInfo.emoji || '') + ' ' + escHtml(agentInfo.name || agentId) : (agentId ? escHtml(agentId) : '');
|
|
407
407
|
const deps = (i.depends_on || []).join(', ');
|
|
408
408
|
const wipAnim = i.status === 'in-progress' ? 'animation:prdWipPulse 2s infinite;' : '';
|
|
409
|
+
const wiForCard = wi[i.id];
|
|
410
|
+
const wiIdBadge = wiForCard ? '<span style="font-size:8px;color:var(--muted);background:var(--surface);padding:1px 4px;border-radius:3px;border:1px solid var(--border)" title="Work item: ' + escHtml(wiForCard.id) + '">' + escHtml(wiForCard.id) + '</span>' : '';
|
|
411
|
+
const isDoneCard = i.status === 'done' || (wiForCard && wiForCard.status === 'done');
|
|
412
|
+
const reopenBtnGraph = isDoneCard
|
|
413
|
+
? '<span onclick="event.stopPropagation();prdItemReopen(\'' + src + '\',\'' + iid + '\')" style="font-size:8px;color:var(--blue);cursor:pointer;padding:1px 4px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:3px" title="Re-open: set to updated so engine re-dispatches on existing branch">re-open</span>'
|
|
414
|
+
: '';
|
|
415
|
+
const cardTitle = i.description ? escHtml(i.name + ' — ' + i.description) : escHtml(i.name || '');
|
|
409
416
|
html += '<div onclick="prdItemEdit(\'' + src + '\',\'' + iid + '\')" ' +
|
|
417
|
+
'title="' + cardTitle + '" ' +
|
|
410
418
|
'style="background:var(--surface2);border:1px solid var(--border);border-left:3px solid ' + borderColor + ';' + wipAnim +
|
|
411
419
|
'border-radius:4px;padding:6px 8px;margin-bottom:6px;cursor:pointer;font-size:11px">' +
|
|
412
420
|
'<div style="display:flex;align-items:center;gap:4px;margin-bottom:2px">' +
|
|
413
421
|
statusBadge(i.status, i.id) +
|
|
414
422
|
'<span style="font-weight:600;color:var(--text)">' + escHtml(i.id) + '</span>' +
|
|
423
|
+
wiIdBadge +
|
|
424
|
+
'<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="margin-left:auto;color:var(--red);cursor:pointer;font-size:10px;padding:0 4px;line-height:1" title="Remove item">x</span>' +
|
|
415
425
|
'</div>' +
|
|
416
426
|
'<div style="color:var(--text);font-size:11px;line-height:1.3;margin-bottom:3px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical">' + escHtml(i.name) + '</div>' +
|
|
417
427
|
'<div style="display:flex;gap:4px;flex-wrap:wrap;align-items:center">' +
|
|
@@ -436,6 +446,7 @@ function renderPrdProgress(prog) {
|
|
|
436
446
|
if (!canRetry) return '';
|
|
437
447
|
return '<span onclick="event.stopPropagation();prdItemRequeue(\'' + escHtml(rqId) + '\',\'' + escHtml(w ? (w._source || '') : '') + '\',\'' + escHtml(i.source || '') + '\')" style="font-size:8px;color:var(--green);cursor:pointer;padding:1px 4px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">retry</span>';
|
|
438
448
|
})() +
|
|
449
|
+
reopenBtnGraph +
|
|
439
450
|
(deps ? '<span style="font-size:8px;color:var(--muted)" title="Depends on: ' + escHtml(deps) + '">deps: ' + escHtml(deps) + '</span>' : '') +
|
|
440
451
|
(function() {
|
|
441
452
|
var w = wi[i.id];
|
package/dashboard.js
CHANGED
|
@@ -721,17 +721,24 @@ function getDiskVersion() {
|
|
|
721
721
|
return _diskVersionCache;
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
+
function readMcpServersFromConfig(configPath, source) {
|
|
725
|
+
const data = safeJsonObj(configPath);
|
|
726
|
+
const servers = data.mcpServers || {};
|
|
727
|
+
return Object.entries(servers).map(([name, cfg]) => ({
|
|
728
|
+
name,
|
|
729
|
+
source,
|
|
730
|
+
command: cfg.command || cfg.url || '',
|
|
731
|
+
args: (cfg.args || []).slice(-1)[0] || '',
|
|
732
|
+
}));
|
|
733
|
+
}
|
|
734
|
+
|
|
724
735
|
function getMcpServers() {
|
|
725
736
|
try {
|
|
726
737
|
const home = os.homedir();
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
name,
|
|
732
|
-
command: cfg.command || '',
|
|
733
|
-
args: (cfg.args || []).slice(-1)[0] || '',
|
|
734
|
-
}));
|
|
738
|
+
return [
|
|
739
|
+
...readMcpServersFromConfig(path.join(home, '.claude.json'), 'Claude'),
|
|
740
|
+
...readMcpServersFromConfig(path.join(home, '.copilot', 'mcp-config.json'), 'Copilot'),
|
|
741
|
+
];
|
|
735
742
|
} catch { return []; }
|
|
736
743
|
}
|
|
737
744
|
|
|
@@ -1503,34 +1510,6 @@ function stripCCActionSyntax(text) {
|
|
|
1503
1510
|
return displayText.replace(/`{3,}\s*action\s*\r?\n[\s\S]*?`{3,}\n?/g, '').trim();
|
|
1504
1511
|
}
|
|
1505
1512
|
|
|
1506
|
-
function _messageRequestsOrchestration(message) {
|
|
1507
|
-
const text = String(message || '').toLowerCase();
|
|
1508
|
-
if (!text.trim()) return false;
|
|
1509
|
-
|
|
1510
|
-
const docTarget = '\\b(document|doc|text|selection|selected text|selected paragraph|selected section|paragraph|section|wording|copy|markdown|plan)\\b';
|
|
1511
|
-
const docEditVerb = '\\b(edit|rewrite|revise|update|change|rephrase|polish|format|shorten|expand|summarize|correct|add|write)\\b';
|
|
1512
|
-
const explicitDocEdit = new RegExp(`${docEditVerb}[\\s\\S]{0,120}${docTarget}|${docTarget}[\\s\\S]{0,120}${docEditVerb}`).test(text)
|
|
1513
|
-
|| /\bfix\b[\s\S]{0,80}\b(typo|typos|grammar|spelling|wording|copy|markdown)\b[\s\S]{0,80}\b(document|doc|text|selection|paragraph|section|plan)\b/.test(text);
|
|
1514
|
-
const actionTerm = '\\b(dispatch|delegate|assign|orchestrate|hand off|handoff|work item|ticket|agent|minions|watch|monitor|schedule|pipeline|meeting)\\b';
|
|
1515
|
-
const untrustedActionMention = new RegExp(
|
|
1516
|
-
`${docTarget}[\\s\\S]{0,120}\\b(says|contains|mentions|includes|reads|states|instructs|asks|tells|literal|literally)\\b[\\s\\S]{0,160}${actionTerm}`
|
|
1517
|
-
).test(text)
|
|
1518
|
-
|| new RegExp(`\\b(summarize|explain|quote|describe|analyze|extract)\\b[\\s\\S]{0,160}${docTarget}[\\s\\S]{0,160}${actionTerm}`).test(text);
|
|
1519
|
-
const explicitFollowupAction = /\b(and|then|also)\b[\s\S]{0,80}\b(dispatch|delegate|assign|orchestrate|hand off|handoff|work item|ticket|agent|minions|watch|monitor|schedule|pipeline|meeting)\b/.test(text);
|
|
1520
|
-
if (untrustedActionMention && !explicitFollowupAction) return false;
|
|
1521
|
-
|
|
1522
|
-
const dispatchAction = /\b(dispatch|delegate|assign|orchestrate|hand off|handoff)\b[\s\S]{0,120}\b(agent|dallas|ripley|lambert|rebecca|ralph|work item|task|fix|implement|explore|investigate|audit|review|test|verify|build)\b/.test(text);
|
|
1523
|
-
const workItemAction = /\b(create|open|file|add)\b[\s\S]{0,80}\b(work item|task|ticket)\b/.test(text);
|
|
1524
|
-
const stateAction = /\b(create|add|set up|start)\b[\s\S]{0,80}\b(watch|monitor|schedule|pipeline|meeting)\b/.test(text)
|
|
1525
|
-
|| /\b(watch|monitor|keep an eye on)\b[\s\S]{0,100}\b(pr|pull request|work item|build)\b/.test(text)
|
|
1526
|
-
|| /\b(cancel|retry|reopen|archive|pause|approve|reject|execute|resume|steer)\b[\s\S]{0,100}\b(plan|work item|agent|pr|pull request|schedule|pipeline)\b/.test(text);
|
|
1527
|
-
const agentEngineeringAction = /\b(minions|agent|dallas|ripley|lambert|rebecca|ralph)\b[\s\S]{0,120}\b(fix|debug|repair|investigate|audit|review|test|verify|build|refactor|implement)\b/.test(text)
|
|
1528
|
-
|| /\b(fix|debug|repair|investigate|audit|review|test|verify|build|refactor|implement)\b[\s\S]{0,120}\b(minions|agent|dallas|ripley|lambert|rebecca|ralph)\b/.test(text);
|
|
1529
|
-
const explicitActionIntent = dispatchAction || workItemAction || stateAction || agentEngineeringAction;
|
|
1530
|
-
if (explicitDocEdit && !explicitActionIntent) return false;
|
|
1531
|
-
return explicitActionIntent;
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
1513
|
function _escapeRegExp(str) {
|
|
1535
1514
|
return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1536
1515
|
}
|
|
@@ -2510,13 +2489,11 @@ function contentFingerprint(str) {
|
|
|
2510
2489
|
return str.length + ':' + str.charCodeAt(0) + ':' + str.charCodeAt(mid) + ':' + str.charCodeAt(str.length - 1);
|
|
2511
2490
|
}
|
|
2512
2491
|
|
|
2513
|
-
function _parseDocChatResultText(text
|
|
2492
|
+
function _parseDocChatResultText(text) {
|
|
2514
2493
|
const docDelimiter = findDocChatDocumentDelimiter(text);
|
|
2515
2494
|
if (docDelimiter) {
|
|
2516
2495
|
const answerPart = text.slice(0, docDelimiter.index).trim();
|
|
2517
|
-
const parsedActions =
|
|
2518
|
-
? parseCCActions(answerPart)
|
|
2519
|
-
: { text: stripCCActionSyntax(answerPart), actions: [] };
|
|
2496
|
+
const parsedActions = parseCCActions(answerPart);
|
|
2520
2497
|
const { text: answer, actions } = parsedActions;
|
|
2521
2498
|
let content = text.slice(docDelimiter.index + docDelimiter.length).trim();
|
|
2522
2499
|
content = content.replace(/^```\w*\n?/, '').replace(/\n?```$/, '').trim();
|
|
@@ -2527,9 +2504,7 @@ function _parseDocChatResultText(text, { allowActions = false } = {}) {
|
|
|
2527
2504
|
...(parsedActions._actionParseError ? { actionParseError: parsedActions._actionParseError } : {}),
|
|
2528
2505
|
};
|
|
2529
2506
|
}
|
|
2530
|
-
const parsedActions =
|
|
2531
|
-
? parseCCActions(text)
|
|
2532
|
-
: { text: stripCCActionSyntax(text), actions: [] };
|
|
2507
|
+
const parsedActions = parseCCActions(text);
|
|
2533
2508
|
const { text: stripped, actions } = parsedActions;
|
|
2534
2509
|
return {
|
|
2535
2510
|
answer: stripped,
|
|
@@ -2539,8 +2514,8 @@ function _parseDocChatResultText(text, { allowActions = false } = {}) {
|
|
|
2539
2514
|
};
|
|
2540
2515
|
}
|
|
2541
2516
|
|
|
2542
|
-
function _docChatDisplayText(text
|
|
2543
|
-
return _parseDocChatResultText(text
|
|
2517
|
+
function _docChatDisplayText(text) {
|
|
2518
|
+
return _parseDocChatResultText(text).answer;
|
|
2544
2519
|
}
|
|
2545
2520
|
|
|
2546
2521
|
function _formatDocChatContext({ document, title, filePath, selection, canEdit, isJson, docUnchanged }) {
|
|
@@ -2636,8 +2611,6 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
2636
2611
|
// Skip persistDocSessions() here — the post-call cleanup below handles persistence.
|
|
2637
2612
|
}
|
|
2638
2613
|
|
|
2639
|
-
const allowActions = _messageRequestsOrchestration(message);
|
|
2640
|
-
|
|
2641
2614
|
const runOnce = async () => {
|
|
2642
2615
|
const { extraContext } = _buildDocChatPass({
|
|
2643
2616
|
docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession,
|
|
@@ -2684,7 +2657,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
2684
2657
|
return _docChatFailureResponse('doc-chat', filePath, result, sessionPreserved);
|
|
2685
2658
|
}
|
|
2686
2659
|
|
|
2687
|
-
return _parseDocChatResultText(result.text
|
|
2660
|
+
return _parseDocChatResultText(result.text);
|
|
2688
2661
|
}
|
|
2689
2662
|
|
|
2690
2663
|
async function ccDocCallStreaming({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, onAbortReady, onChunk, onToolUse, onRetry }) {
|
|
@@ -2695,8 +2668,6 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
2695
2668
|
docSessions.delete(sessionKey);
|
|
2696
2669
|
}
|
|
2697
2670
|
|
|
2698
|
-
const allowActions = _messageRequestsOrchestration(message);
|
|
2699
|
-
|
|
2700
2671
|
const runOnce = async () => {
|
|
2701
2672
|
const { extraContext } = _buildDocChatPass({
|
|
2702
2673
|
docSlice, title, filePath, selection, canEdit, isJson, sessionKey, freshSession,
|
|
@@ -2713,7 +2684,7 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
2713
2684
|
systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
|
|
2714
2685
|
...(model ? { model } : {}),
|
|
2715
2686
|
onAbortReady,
|
|
2716
|
-
onChunk: (text) => { if (onChunk) onChunk(_docChatDisplayText(text
|
|
2687
|
+
onChunk: (text) => { if (onChunk) onChunk(_docChatDisplayText(text)); },
|
|
2717
2688
|
onToolUse,
|
|
2718
2689
|
onRetry,
|
|
2719
2690
|
});
|
|
@@ -2742,7 +2713,7 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
2742
2713
|
return _docChatFailureResponse('doc-chat-stream', filePath, result, sessionPreserved);
|
|
2743
2714
|
}
|
|
2744
2715
|
|
|
2745
|
-
return _parseDocChatResultText(result.text
|
|
2716
|
+
return _parseDocChatResultText(result.text);
|
|
2746
2717
|
}
|
|
2747
2718
|
|
|
2748
2719
|
// -- POST helpers --
|
|
@@ -7428,7 +7399,6 @@ module.exports = {
|
|
|
7428
7399
|
_meetingParticipantsFromAction: meetingParticipantsFromAction,
|
|
7429
7400
|
parsePinnedEntries,
|
|
7430
7401
|
_parseDocChatResultText,
|
|
7431
|
-
_messageRequestsOrchestration,
|
|
7432
7402
|
_formatDocChatContext,
|
|
7433
7403
|
_linkPullRequestForTracking: linkPullRequestForTracking,
|
|
7434
7404
|
_resolveSkillReadPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1753",
|
|
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"
|