@yemi33/minions 0.1.37 → 0.1.39
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 +20 -0
- package/dashboard/js/render-prs.js +51 -0
- package/dashboard/layout.html +1 -0
- package/dashboard/pages/inbox.html +0 -4
- package/dashboard/pages/prs.html +3 -1
- package/dashboard/pages/schedule.html +0 -4
- package/dashboard/pages/tools.html +8 -0
- package/dashboard-build.js +1 -1
- package/dashboard.js +39 -1
- package/engine.js +10 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.39 (2026-03-29)
|
|
4
|
+
|
|
5
|
+
### Engine
|
|
6
|
+
- engine.js
|
|
7
|
+
|
|
8
|
+
### Dashboard
|
|
9
|
+
- dashboard.js
|
|
10
|
+
- dashboard/js/render-prs.js
|
|
11
|
+
- dashboard/pages/prs.html
|
|
12
|
+
|
|
13
|
+
## 0.1.38 (2026-03-29)
|
|
14
|
+
|
|
15
|
+
### Dashboard
|
|
16
|
+
- dashboard-build.js
|
|
17
|
+
- dashboard.js
|
|
18
|
+
- dashboard/layout.html
|
|
19
|
+
- dashboard/pages/inbox.html
|
|
20
|
+
- dashboard/pages/schedule.html
|
|
21
|
+
- dashboard/pages/tools.html
|
|
22
|
+
|
|
3
23
|
## 0.1.37 (2026-03-28)
|
|
4
24
|
|
|
5
25
|
### Dashboard
|
|
@@ -92,3 +92,54 @@ function openModal(i) {
|
|
|
92
92
|
if (card) clearNotifBadge(card);
|
|
93
93
|
document.getElementById('modal').classList.add('open');
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
function openAddPrModal() {
|
|
97
|
+
const projOpts = (typeof cmdProjects !== 'undefined' ? cmdProjects : []).map(p =>
|
|
98
|
+
'<option value="' + escHtml(p) + '">' + escHtml(p) + '</option>'
|
|
99
|
+
).join('');
|
|
100
|
+
const inputStyle = 'display:block;width:100%;margin-top:4px;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-size:var(--text-md);font-family:inherit';
|
|
101
|
+
|
|
102
|
+
document.getElementById('modal-title').textContent = 'Link Pull Request';
|
|
103
|
+
document.getElementById('modal-body').innerHTML =
|
|
104
|
+
'<div style="display:flex;flex-direction:column;gap:10px">' +
|
|
105
|
+
'<label style="color:var(--text);font-size:var(--text-md)">PR URL <input id="pr-link-url" style="' + inputStyle + '" placeholder="https://github.com/org/repo/pull/123"></label>' +
|
|
106
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Title <input id="pr-link-title" style="' + inputStyle + '" placeholder="Short description (optional — auto-detected from URL)"></label>' +
|
|
107
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Project <select id="pr-link-project" style="' + inputStyle + '"><option value="">Auto / Central</option>' + projOpts + '</select></label>' +
|
|
108
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Context <textarea id="pr-link-context" rows="3" style="' + inputStyle + ';resize:vertical" placeholder="Why are you linking this? What should agents know about it?"></textarea></label>' +
|
|
109
|
+
'<label style="display:flex;align-items:center;gap:8px;color:var(--text);font-size:var(--text-md);margin-top:4px;cursor:pointer">' +
|
|
110
|
+
'<input type="checkbox" id="pr-link-observe" style="width:16px;height:16px;accent-color:var(--blue)">' +
|
|
111
|
+
'<span>Auto-observe <span style="color:var(--muted);font-weight:400">(monitor builds, resolve comments, fix failures)</span></span>' +
|
|
112
|
+
'</label>' +
|
|
113
|
+
'<div style="font-size:11px;color:var(--muted);margin-top:-4px;padding-left:24px">Off = context only (e.g. teammate\'s PR). On = agents actively monitor and fix issues.</div>' +
|
|
114
|
+
'<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:8px">' +
|
|
115
|
+
'<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
|
|
116
|
+
'<button onclick="_submitLinkPr()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Link PR</button>' +
|
|
117
|
+
'</div>' +
|
|
118
|
+
'</div>';
|
|
119
|
+
document.getElementById('modal').classList.add('open');
|
|
120
|
+
setTimeout(() => document.getElementById('pr-link-url')?.focus(), 100);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function _submitLinkPr() {
|
|
124
|
+
const url = document.getElementById('pr-link-url')?.value?.trim();
|
|
125
|
+
if (!url) { alert('PR URL is required'); return; }
|
|
126
|
+
const title = document.getElementById('pr-link-title')?.value?.trim() || '';
|
|
127
|
+
const project = document.getElementById('pr-link-project')?.value || '';
|
|
128
|
+
const context = document.getElementById('pr-link-context')?.value || '';
|
|
129
|
+
const autoObserve = document.getElementById('pr-link-observe')?.checked || false;
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const res = await fetch('/api/pull-requests/link', {
|
|
133
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
134
|
+
body: JSON.stringify({ url, title, project, context, autoObserve })
|
|
135
|
+
});
|
|
136
|
+
const data = await res.json();
|
|
137
|
+
if (res.ok) {
|
|
138
|
+
try { closeModal(); } catch {}
|
|
139
|
+
refresh();
|
|
140
|
+
try { showToast('cmd-toast', 'PR ' + (data.id || '') + ' linked' + (autoObserve ? ' (auto-observe on)' : ''), true); } catch {}
|
|
141
|
+
} else {
|
|
142
|
+
alert('Failed: ' + (data.error || 'unknown'));
|
|
143
|
+
}
|
|
144
|
+
} catch (e) { alert('Error: ' + e.message); }
|
|
145
|
+
}
|
package/dashboard/layout.html
CHANGED
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
<a class="sidebar-link" data-page="prs" href="/prs">Pull Requests <span class="sidebar-count" id="sidebar-pr"></span></a>
|
|
64
64
|
<a class="sidebar-link" data-page="plans" href="/plans">Plans</a>
|
|
65
65
|
<a class="sidebar-link" data-page="inbox" href="/inbox">Notes & KB</a>
|
|
66
|
+
<a class="sidebar-link" data-page="tools" href="/tools">Skills & MCP</a>
|
|
66
67
|
<a class="sidebar-link" data-page="schedule" href="/schedule">Schedules</a>
|
|
67
68
|
<a class="sidebar-link" data-page="engine" href="/engine">Engine</a>
|
|
68
69
|
</nav>
|
|
@@ -11,7 +11,3 @@
|
|
|
11
11
|
<div class="kb-tabs" id="kb-tabs"></div>
|
|
12
12
|
<div class="kb-list" id="kb-list"><p class="empty">No knowledge entries yet. Notes are classified here after consolidation.</p></div>
|
|
13
13
|
</section>
|
|
14
|
-
<section>
|
|
15
|
-
<h2>Minions Skills <span class="count" id="skills-count">0</span></h2>
|
|
16
|
-
<div id="skills-list"><p class="empty">No skills yet. Agents create these when they discover repeatable workflows.</p></div>
|
|
17
|
-
</section>
|
package/dashboard/pages/prs.html
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<section class="pr-panel" id="pr-section">
|
|
2
|
-
<h2>Pull Requests <span class="count" id="pr-count">0</span
|
|
2
|
+
<h2>Pull Requests <span class="count" id="pr-count">0</span>
|
|
3
|
+
<button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:8px" onclick="openAddPrModal()">+ Link PR</button>
|
|
4
|
+
</h2>
|
|
3
5
|
<div id="pr-content"><p class="pr-empty">No pull requests yet.</p></div>
|
|
4
6
|
</section>
|
|
@@ -4,7 +4,3 @@
|
|
|
4
4
|
</h2>
|
|
5
5
|
<div id="scheduled-content"><p class="empty">No scheduled tasks. Add one to automate recurring work.</p></div>
|
|
6
6
|
</section>
|
|
7
|
-
<section>
|
|
8
|
-
<h2>MCP Servers <span class="count" id="mcp-count">0</span></h2>
|
|
9
|
-
<div id="mcp-list"><p class="empty">No MCP servers synced.</p></div>
|
|
10
|
-
</section>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<section>
|
|
2
|
+
<h2>Minions Skills <span class="count" id="skills-count">0</span></h2>
|
|
3
|
+
<div id="skills-list"><p class="empty">No skills yet. Agents create these when they discover repeatable workflows.</p></div>
|
|
4
|
+
</section>
|
|
5
|
+
<section>
|
|
6
|
+
<h2>MCP Servers <span class="count" id="mcp-count">0</span></h2>
|
|
7
|
+
<div id="mcp-list"><p class="empty">No MCP servers synced.</p></div>
|
|
8
|
+
</section>
|
package/dashboard-build.js
CHANGED
|
@@ -20,7 +20,7 @@ function buildDashboardHtml() {
|
|
|
20
20
|
const layout = safeRead(layoutPath);
|
|
21
21
|
const css = safeRead(path.join(dashDir, 'styles.css'));
|
|
22
22
|
|
|
23
|
-
const pages = ['home', 'work', 'prd', 'prs', 'plans', 'inbox', 'schedule', 'engine'];
|
|
23
|
+
const pages = ['home', 'work', 'prd', 'prs', 'plans', 'inbox', 'tools', 'schedule', 'engine'];
|
|
24
24
|
let pageHtml = '';
|
|
25
25
|
for (const p of pages) {
|
|
26
26
|
const content = safeRead(path.join(dashDir, 'pages', p + '.html'));
|
package/dashboard.js
CHANGED
|
@@ -63,7 +63,7 @@ function buildDashboardHtml() {
|
|
|
63
63
|
const css = safeRead(path.join(dashDir, 'styles.css'));
|
|
64
64
|
|
|
65
65
|
// Assemble page fragments
|
|
66
|
-
const pages = ['home', 'work', 'prd', 'prs', 'plans', 'inbox', 'schedule', 'engine'];
|
|
66
|
+
const pages = ['home', 'work', 'prd', 'prs', 'plans', 'inbox', 'tools', 'schedule', 'engine'];
|
|
67
67
|
let pageHtml = '';
|
|
68
68
|
for (const p of pages) {
|
|
69
69
|
const content = safeRead(path.join(dashDir, 'pages', p + '.html'));
|
|
@@ -2916,6 +2916,44 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
2916
2916
|
{ method: 'POST', path: '/api/prd/regenerate', desc: 'Regenerate PRD from revised source plan', params: 'file', handler: handlePrdRegenerate },
|
|
2917
2917
|
|
|
2918
2918
|
// Agents
|
|
2919
|
+
{ method: 'POST', path: '/api/pull-requests/link', desc: 'Manually link an external PR for tracking', params: 'url, title?, project?, autoObserve?, context?', handler: async (req, res) => {
|
|
2920
|
+
const body = await readBody(req);
|
|
2921
|
+
const { url, title, project: projectName, autoObserve, context } = body;
|
|
2922
|
+
if (!url) return jsonReply(res, 400, { error: 'url required' });
|
|
2923
|
+
|
|
2924
|
+
// Determine project
|
|
2925
|
+
reloadConfig();
|
|
2926
|
+
const projects = shared.getProjects(CONFIG);
|
|
2927
|
+
const targetProject = projectName ? projects.find(p => p.name?.toLowerCase() === projectName.toLowerCase()) : projects[0];
|
|
2928
|
+
const prPath = targetProject ? shared.projectPrPath(targetProject) : path.join(MINIONS_DIR, 'pull-requests.json');
|
|
2929
|
+
const prs = JSON.parse(safeRead(prPath) || '[]');
|
|
2930
|
+
|
|
2931
|
+
// Extract PR number from URL
|
|
2932
|
+
const prNumMatch = url.match(/\/pull\/(\d+)|pullrequest\/(\d+)/);
|
|
2933
|
+
const prNum = prNumMatch ? (prNumMatch[1] || prNumMatch[2]) : Date.now().toString().slice(-6);
|
|
2934
|
+
const prId = 'PR-' + prNum;
|
|
2935
|
+
|
|
2936
|
+
if (prs.some(p => p.id === prId || p.url === url)) return jsonReply(res, 400, { error: 'PR already tracked' });
|
|
2937
|
+
|
|
2938
|
+
prs.push({
|
|
2939
|
+
id: prId,
|
|
2940
|
+
title: (title || 'Linked PR #' + prNum).slice(0, 120),
|
|
2941
|
+
agent: 'human',
|
|
2942
|
+
branch: '',
|
|
2943
|
+
reviewStatus: autoObserve ? 'pending' : 'none',
|
|
2944
|
+
status: autoObserve ? 'active' : 'linked',
|
|
2945
|
+
created: new Date().toISOString().slice(0, 10),
|
|
2946
|
+
url,
|
|
2947
|
+
prdItems: [],
|
|
2948
|
+
_manual: true,
|
|
2949
|
+
_autoObserve: !!autoObserve,
|
|
2950
|
+
_context: context || '',
|
|
2951
|
+
});
|
|
2952
|
+
safeWrite(prPath, prs);
|
|
2953
|
+
invalidateStatusCache();
|
|
2954
|
+
return jsonReply(res, 200, { ok: true, id: prId });
|
|
2955
|
+
}},
|
|
2956
|
+
|
|
2919
2957
|
{ method: 'POST', path: '/api/agents/steer', desc: 'Inject steering message into a running agent', params: 'agent, message', handler: async (req, res) => {
|
|
2920
2958
|
const body = await readBody(req);
|
|
2921
2959
|
const { agent: agentId, message } = body;
|
package/engine.js
CHANGED
|
@@ -592,16 +592,23 @@ function buildAgentContext(agentId, config, project) {
|
|
|
592
592
|
context += `## Recently Completed\n\n${recentCompleted.join('\n')}\n\n`;
|
|
593
593
|
}
|
|
594
594
|
|
|
595
|
-
// Active PRs across projects — coordination awareness
|
|
595
|
+
// Active + linked PRs across projects — coordination awareness
|
|
596
596
|
const projects = getProjects(config);
|
|
597
597
|
const allPrs = [];
|
|
598
598
|
for (const p of projects) {
|
|
599
|
-
const prs = getPrs(p).filter(pr => pr.status === 'active');
|
|
599
|
+
const prs = getPrs(p).filter(pr => pr.status === 'active' || pr.status === 'linked');
|
|
600
600
|
for (const pr of prs) allPrs.push({ ...pr, _project: p.name });
|
|
601
601
|
}
|
|
602
|
+
// Also check central pull-requests.json
|
|
603
|
+
try {
|
|
604
|
+
const centralPrs = safeJson(path.join(MINIONS_DIR, 'pull-requests.json')) || [];
|
|
605
|
+
for (const pr of centralPrs.filter(pr => pr.status === 'active' || pr.status === 'linked')) {
|
|
606
|
+
if (!allPrs.some(p => p.id === pr.id)) allPrs.push({ ...pr, _project: 'central' });
|
|
607
|
+
}
|
|
608
|
+
} catch {}
|
|
602
609
|
if (allPrs.length > 0) {
|
|
603
610
|
const prLines = allPrs.map(pr =>
|
|
604
|
-
`- **${pr.id}** (${pr._project}): ${(pr.title || '').slice(0, 80)} [${pr.reviewStatus || 'pending'}${pr.buildStatus === 'failing' ? ', BUILD FAILING' : ''}]${pr.branch ? ' branch: `' + pr.branch + '`' : ''}`
|
|
611
|
+
`- **${pr.id}** (${pr._project}): ${(pr.title || '').slice(0, 80)} [${pr.status === 'linked' ? 'context-only' : (pr.reviewStatus || 'pending')}${pr.buildStatus === 'failing' ? ', BUILD FAILING' : ''}]${pr.branch ? ' branch: `' + pr.branch + '`' : ''}${pr._context ? ' — ' + pr._context.slice(0, 100) : ''}`
|
|
605
612
|
);
|
|
606
613
|
context += `## Active Pull Requests\n\n${prLines.join('\n')}\n\n`;
|
|
607
614
|
}
|
package/package.json
CHANGED