@yemi33/minions 0.1.482 → 0.1.483

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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.483 (2026-04-07)
4
+
5
+ ### Fixes
6
+ - harden bug filing — proper escaping, error handling, direct UI button
7
+
3
8
  ## 0.1.482 (2026-04-07)
4
9
 
5
10
  ### Features
@@ -639,12 +639,12 @@ async function ccExecuteAction(action) {
639
639
  break;
640
640
  }
641
641
  case 'file-bug': {
642
- const res = await _ccFetch('/api/issues/create', { title: action.title, description: action.description, project: action.project, labels: action.labels });
642
+ const res = await _ccFetch('/api/issues/create', { title: action.title, description: action.description, labels: action.labels });
643
643
  const d = await res.json();
644
644
  if (d.url) {
645
645
  status.innerHTML = '&#128027; Bug filed: <a href="' + escHtml(d.url) + '" target="_blank" style="color:var(--blue)">' + escHtml(action.title) + '</a>';
646
646
  } else {
647
- status.innerHTML = '&#128027; Bug filed: <strong>' + escHtml(action.title) + '</strong>';
647
+ status.innerHTML = '&#128027; Bug filed: <strong>' + escHtml(action.title) + '</strong> — <a href="https://github.com/yemi33/minions/issues" target="_blank" style="color:var(--blue)">view issues</a>';
648
648
  }
649
649
  status.style.color = 'var(--green)';
650
650
  break;
@@ -199,4 +199,42 @@ function renderMd(s) {
199
199
  return '<div class="md-content">' + html + '</div>';
200
200
  }
201
201
 
202
- window.MinionsUtils = { wakeEngine, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, llmCopyBtn, copyLlmText };
202
+ function openBugReport() {
203
+ document.getElementById('modal-title').textContent = 'Report a Bug';
204
+ document.getElementById('modal-body').innerHTML =
205
+ '<div style="display:flex;flex-direction:column;gap:12px">' +
206
+ '<p style="color:var(--muted);font-size:12px;margin:0">File a bug on the Minions repo (yemi33/minions).</p>' +
207
+ '<label style="color:var(--text);font-size:var(--text-md)">Title' +
208
+ '<input id="bug-title" style="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)" placeholder="Short description of the bug"></label>' +
209
+ '<label style="color:var(--text);font-size:var(--text-md)">Description' +
210
+ '<textarea id="bug-desc" rows="6" style="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);resize:vertical;font-family:inherit" placeholder="Steps to reproduce, expected vs actual behavior..."></textarea></label>' +
211
+ '<div style="display:flex;justify-content:flex-end;gap:8px">' +
212
+ '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
213
+ '<button onclick="submitBugReport()" style="padding:6px 16px;background:var(--red);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">File Bug</button>' +
214
+ '</div>' +
215
+ '</div>';
216
+ document.getElementById('modal').classList.add('open');
217
+ }
218
+
219
+ async function submitBugReport() {
220
+ var title = document.getElementById('bug-title')?.value?.trim();
221
+ var desc = document.getElementById('bug-desc')?.value?.trim();
222
+ if (!title) { alert('Title is required'); return; }
223
+ try { closeModal(); } catch {}
224
+ showToast('cmd-toast', 'Filing bug...', true);
225
+ try {
226
+ var res = await fetch('/api/issues/create', {
227
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
228
+ body: JSON.stringify({ title: title, description: desc || '' })
229
+ });
230
+ var d = await res.json();
231
+ if (!res.ok) throw new Error(d.error || 'Failed');
232
+ if (d.url) {
233
+ showToast('cmd-toast', 'Bug filed — <a href="' + d.url + '" target="_blank" style="color:var(--blue)">view issue</a>', true);
234
+ } else {
235
+ showToast('cmd-toast', 'Bug filed', true);
236
+ }
237
+ } catch (e) { showToast('cmd-toast', 'Error: ' + e.message, false); }
238
+ }
239
+
240
+ window.MinionsUtils = { wakeEngine, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, llmCopyBtn, copyLlmText, openBugReport, submitBugReport };
@@ -16,6 +16,7 @@
16
16
  <span id="version-banner" style="font-size:9px;color:var(--muted)"></span>
17
17
  <div class="timestamp" id="ts">—</div>
18
18
  <button onclick="toggleCommandCenter()" style="background:none;border:none;cursor:pointer;font-size:12px;color:var(--blue);padding:4px 10px;line-height:1;font-weight:700;border:1px solid var(--blue);border-radius:4px" title="Command Center" id="cc-toggle-btn">Command Center</button>
19
+ <button onclick="openBugReport()" style="background:none;border:none;cursor:pointer;font-size:11px;color:var(--muted);padding:4px 8px;line-height:1;border:1px solid var(--border);border-radius:4px" title="Report a bug in Minions">Report Bug</button>
19
20
  <button onclick="openSettings()" style="background:none;border:none;cursor:pointer;font-size:18px;color:var(--muted);padding:4px;line-height:1" title="Settings">&#9881;</button>
20
21
  </div>
21
22
  </header>
package/dashboard.js CHANGED
@@ -576,7 +576,7 @@ Available action types:
576
576
  - **link-pr**: Link an external PR for tracking. Fields: url (PR URL), title (optional), project (optional), autoObserve (bool, default true)
577
577
  - **archive-meeting**: Archive a completed meeting. Fields: id (meeting ID)
578
578
  - **update-routing**: Update the routing table. Fields: content (full routing.md content)
579
- - **file-bug**: File a bug on the Minions repo (yemi33/minions). Fields: title (short bug title), description (markdown body with repro steps, expected vs actual behavior), labels (optional array, defaults to ["bug"]). Use when the user says "file a bug", "create an issue", "report this", etc. This is for bugs in Minions itself, not the user's project.
579
+ - **file-bug**: File a bug on the Minions repo (yemi33/minions). Fields: title (short bug title), description (markdown body), labels (optional array, defaults to ["bug"]). Trigger phrases: "file a bug", "file an issue", "report a bug", "create an issue", "this is a bug", "log a bug". This is for bugs in Minions itself, not the user's project. When filing, include repro steps and relevant context from the conversation in the description. If the user hasn't provided repro steps, ask before filing.
580
580
 
581
581
  ## Rules
582
582
 
@@ -3190,15 +3190,40 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3190
3190
  const body = await readBody(req);
3191
3191
  if (!body.title) return jsonReply(res, 400, { error: 'title required' });
3192
3192
 
3193
+ // Check gh CLI is available
3194
+ try { shared.exec('gh --version', { encoding: 'utf-8', timeout: 5000, windowsHide: true }); }
3195
+ catch { return jsonReply(res, 500, { error: 'gh CLI not installed. Run: npm install -g gh' }); }
3196
+
3193
3197
  const repo = 'yemi33/minions';
3194
3198
  const labels = (body.labels || ['bug']).join(',');
3195
3199
  const bugBody = (body.description || '') + '\n\n---\n_Filed via Minions dashboard_';
3196
3200
 
3197
- const cmd = `gh issue create --repo "${repo}" --title "${body.title.replace(/"/g, '\\"')}" --body "${bugBody.replace(/"/g, '\\"')}" --label "${labels}" 2>&1`;
3198
- const result = shared.exec(cmd, { encoding: 'utf-8', timeout: 30000, windowsHide: true });
3199
- const urlMatch = result.match(/https:\/\/github\.com\/\S+/);
3200
- return jsonReply(res, 200, { ok: true, url: urlMatch ? urlMatch[0] : null, output: result.trim() });
3201
- } catch (e) { return jsonReply(res, 500, { error: e.message }); }
3201
+ // Write body to temp file to avoid shell escaping issues with quotes, backticks, newlines
3202
+ const tmpBody = path.join(ENGINE_DIR, 'tmp', `bug-body-${Date.now()}.md`);
3203
+ safeWrite(tmpBody, bugBody);
3204
+ const safeTitle = body.title.replace(/["`$\\]/g, '');
3205
+ try {
3206
+ const cmd = `gh issue create --repo "${repo}" --title "${safeTitle}" --body-file "${tmpBody}" --label "${labels}" 2>&1`;
3207
+ const result = shared.exec(cmd, { encoding: 'utf-8', timeout: 30000, windowsHide: true });
3208
+ shared.safeUnlink(tmpBody);
3209
+ // Detect gh errors in output
3210
+ if (result.includes('authentication') || result.includes('auth login')) {
3211
+ return jsonReply(res, 401, { error: 'GitHub auth required. Run: gh auth login' });
3212
+ }
3213
+ const urlMatch = result.match(/https:\/\/github\.com\/\S+/);
3214
+ if (!urlMatch) {
3215
+ return jsonReply(res, 500, { error: 'Issue may not have been created: ' + result.trim().slice(0, 200) });
3216
+ }
3217
+ return jsonReply(res, 200, { ok: true, url: urlMatch[0], output: result.trim() });
3218
+ } catch (e) {
3219
+ shared.safeUnlink(tmpBody);
3220
+ throw e;
3221
+ }
3222
+ } catch (e) {
3223
+ const msg = e.message || '';
3224
+ if (msg.includes('ENOENT') || msg.includes('not found')) return jsonReply(res, 500, { error: 'gh CLI not found. Install from https://cli.github.com/' });
3225
+ return jsonReply(res, 500, { error: msg });
3226
+ }
3202
3227
  }
3203
3228
 
3204
3229
  async function handleCommandCenterNewSession(req, res) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.482",
3
+ "version": "0.1.483",
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"