@yemi33/minions 0.1.39 → 0.1.41

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.41 (2026-03-29)
4
+
5
+ ### Engine
6
+ - engine/queries.js
7
+
8
+ ## 0.1.40 (2026-03-29)
9
+
10
+ ### Dashboard
11
+ - dashboard.js
12
+ - dashboard/js/render-plans.js
13
+ - dashboard/pages/plans.html
14
+
3
15
  ## 0.1.39 (2026-03-29)
4
16
 
5
17
  ### Engine
@@ -1,5 +1,51 @@
1
1
  // render-plans.js — Plan rendering functions extracted from dashboard.html
2
2
 
3
+ function openCreatePlanModal() {
4
+ const projOpts = (typeof cmdProjects !== 'undefined' ? cmdProjects : []).map(p =>
5
+ '<option value="' + escHtml(p) + '">' + escHtml(p) + '</option>'
6
+ ).join('');
7
+ 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';
8
+
9
+ document.getElementById('modal-title').textContent = 'Create Plan';
10
+ document.getElementById('modal-body').innerHTML =
11
+ '<div style="display:flex;flex-direction:column;gap:10px">' +
12
+ '<label style="color:var(--text);font-size:var(--text-md)">Title <input id="plan-new-title" style="' + inputStyle + '" placeholder="e.g. Add user authentication with JWT"></label>' +
13
+ '<label style="color:var(--text);font-size:var(--text-md)">Project <select id="plan-new-project" style="' + inputStyle + '"><option value="">Auto</option>' + projOpts + '</select></label>' +
14
+ '<label style="color:var(--text);font-size:var(--text-md)">Plan Content <textarea id="plan-new-content" rows="12" style="' + inputStyle + ';resize:vertical;font-family:monospace;font-size:12px" placeholder="Write your plan in markdown...\n\nDescribe what needs to be built, the approach, requirements, and any constraints.\n\nThe squad will convert this into a PRD with structured work items."></textarea></label>' +
15
+ '<div style="font-size:11px;color:var(--muted)">After creating, click Execute on the plan card to have an agent convert it into a PRD with work items.</div>' +
16
+ '<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
17
+ '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
18
+ '<button onclick="_submitCreatePlan()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Create Plan</button>' +
19
+ '</div>' +
20
+ '</div>';
21
+ document.getElementById('modal').classList.add('open');
22
+ setTimeout(() => document.getElementById('plan-new-title')?.focus(), 100);
23
+ }
24
+
25
+ async function _submitCreatePlan() {
26
+ const title = document.getElementById('plan-new-title')?.value?.trim();
27
+ const content = document.getElementById('plan-new-content')?.value?.trim();
28
+ if (!title) { alert('Title is required'); return; }
29
+ if (!content) { alert('Plan content is required'); return; }
30
+ const project = document.getElementById('plan-new-project')?.value || '';
31
+
32
+ try {
33
+ const res = await fetch('/api/plans/create', {
34
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify({ title, content, project })
36
+ });
37
+ const data = await res.json();
38
+ if (res.ok) {
39
+ try { closeModal(); } catch {}
40
+ refreshPlans();
41
+ refresh();
42
+ try { showToast('cmd-toast', 'Plan "' + data.file + '" created — click Execute to convert to PRD', true); } catch {}
43
+ } else {
44
+ alert('Failed: ' + (data.error || 'unknown'));
45
+ }
46
+ } catch (e) { alert('Error: ' + e.message); }
47
+ }
48
+
3
49
  async function refreshPlans() {
4
50
  try {
5
51
  const plans = await fetch('/api/plans').then(r => r.json());
@@ -1,4 +1,6 @@
1
1
  <section>
2
- <h2>Plans <span class="count" id="plans-count">0</span></h2>
2
+ <h2>Plans <span class="count" id="plans-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="openCreatePlanModal()">+ New Plan</button>
4
+ </h2>
3
5
  <div id="plans-list"><p class="empty">No plans yet. Use /plan in the command center to create one.</p></div>
4
6
  </section>
package/dashboard.js CHANGED
@@ -2954,6 +2954,27 @@ What would you like to discuss or change? When you're happy, say "approve" and I
2954
2954
  return jsonReply(res, 200, { ok: true, id: prId });
2955
2955
  }},
2956
2956
 
2957
+ { method: 'POST', path: '/api/plans/create', desc: 'Create a plan from user-provided content', params: 'title, content, project?', handler: async (req, res) => {
2958
+ const body = await readBody(req);
2959
+ const { title, content, project: projectName } = body;
2960
+ if (!title || !content) return jsonReply(res, 400, { error: 'title and content required' });
2961
+
2962
+ const plansDir = path.join(MINIONS_DIR, 'plans');
2963
+ if (!fs.existsSync(plansDir)) fs.mkdirSync(plansDir, { recursive: true });
2964
+ const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50);
2965
+ const date = new Date().toISOString().slice(0, 10);
2966
+ const filename = `${slug}-${date}.md`;
2967
+ const filePath = shared.uniquePath(path.join(plansDir, filename));
2968
+
2969
+ const header = `# ${title}\n\n` +
2970
+ (projectName ? `**Project:** ${projectName}\n` : '') +
2971
+ `**Created:** ${date}\n**By:** human teammate\n\n---\n\n`;
2972
+ safeWrite(filePath, header + content);
2973
+
2974
+ invalidateStatusCache();
2975
+ return jsonReply(res, 200, { ok: true, file: path.basename(filePath) });
2976
+ }},
2977
+
2957
2978
  { method: 'POST', path: '/api/agents/steer', desc: 'Inject steering message into a running agent', params: 'agent, message', handler: async (req, res) => {
2958
2979
  const body = await readBody(req);
2959
2980
  const { agent: agentId, message } = body;
package/engine/queries.js CHANGED
@@ -266,6 +266,17 @@ function getPullRequests(config) {
266
266
  allPrs.push(pr);
267
267
  }
268
268
  }
269
+ // Also read central pull-requests.json (for manually linked PRs without a project)
270
+ const centralPath = path.join(MINIONS_DIR, 'pull-requests.json');
271
+ const centralPrs = safeJson(centralPath);
272
+ if (centralPrs) {
273
+ for (const pr of centralPrs) {
274
+ if (!allPrs.some(p => p.id === pr.id)) {
275
+ pr._project = 'central';
276
+ allPrs.push(pr);
277
+ }
278
+ }
279
+ }
269
280
  allPrs.sort((a, b) => (b.created || '').localeCompare(a.created || ''));
270
281
  return allPrs;
271
282
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
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"