@yemi33/minions 0.1.1785 → 0.1.1787

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.1787 (2026-05-08)
4
+
5
+ ### Features
6
+ - show Doc Chat dispatch feedback (#2173)
7
+
3
8
  ## 0.1.1785 (2026-05-08)
4
9
 
5
10
  ### Features
@@ -331,9 +331,38 @@ function _qaBuildAssistantHtml(text, opts) {
331
331
  const pad = opts?.isError ? '' : 'padding-right:24px;';
332
332
  return '<div class="modal-qa-a" style="' + style + '">' +
333
333
  (opts?.isError ? '' : llmCopyBtn()) +
334
- body +
335
- '<div style="font-size:9px;color:var(--muted);margin-top:4px;text-align:right;' + pad + '">' + opts.elapsed + 's</div>' +
336
- '</div>';
334
+ body +
335
+ '<div style="font-size:9px;color:var(--muted);margin-top:4px;text-align:right;' + pad + '">' + opts.elapsed + 's</div>' +
336
+ '</div>';
337
+ }
338
+
339
+ const QA_WORK_ITEM_ACTION_TYPES = new Set(['dispatch', 'fix', 'implement', 'explore', 'review', 'test']);
340
+
341
+ function _qaActionFeedbackHandled(action, actionResult) {
342
+ const type = String(actionResult?.type || action?.type || '');
343
+ return QA_WORK_ITEM_ACTION_TYPES.has(type) && !!(actionResult?.ok || actionResult?.error);
344
+ }
345
+
346
+ function _qaRunHandledActionSideEffects(action, actionResult) {
347
+ const type = String(actionResult?.type || action?.type || '');
348
+ if (!QA_WORK_ITEM_ACTION_TYPES.has(type)) return;
349
+ if (typeof wakeEngine === 'function') wakeEngine();
350
+ if (typeof refresh === 'function') refresh();
351
+ }
352
+
353
+ function _qaBuildActionFeedbackHtml(actionFeedback) {
354
+ if (!Array.isArray(actionFeedback) || actionFeedback.length === 0) return '';
355
+ return actionFeedback.map(function(item) {
356
+ const type = escHtml(item.type || 'dispatch');
357
+ const baseStyle = 'padding:4px 10px;border-radius:4px;font-size:10px;align-self:flex-start;border:1px dashed var(--border);margin:4px 0;';
358
+ if (item.error) {
359
+ return '<div class="modal-qa-action-feedback" style="' + baseStyle + 'color:var(--red)">&#10007; ' + type + ' failed: ' + escHtml(item.error) + '</div>';
360
+ }
361
+ const label = escHtml(item.id || item.duplicateOf || '');
362
+ const duplicate = item.duplicate ? ' <span style="color:var(--orange)">already exists</span>' : '';
363
+ const warning = item.warning ? '<div style="font-size:10px;color:var(--muted);margin-top:2px">' + escHtml(item.warning) + '</div>' : '';
364
+ return '<div class="modal-qa-action-feedback" style="' + baseStyle + 'color:' + (item.duplicate ? 'var(--orange)' : 'var(--green)') + '">&#10003; ' + type + ': <strong>' + label + '</strong>' + duplicate + warning + '</div>';
365
+ }).join('');
337
366
  }
338
367
 
339
368
  function _qaBuildLiveProgressHtml(loadingId, label, elapsedSeconds, streamedText, toolsUsed, queueCount) {
@@ -718,6 +747,7 @@ async function _processQaMessage(message, selection, opts) {
718
747
  bodyText += '\n\n_Tools that ran before the failure: ' + names + more + ' \u2014 files or state may have been modified._';
719
748
  }
720
749
  const answerHtml = _qaBuildAssistantHtml(bodyText, { borderColor, elapsed: qaElapsed });
750
+ const actionFeedbackHtml = _qaBuildActionFeedbackHtml(evt.actionFeedback);
721
751
  // On any runtime failure, surface the raw error so users can debug it
722
752
  // directly instead of guessing what the friendly summary was hiding.
723
753
  const rawErrorHtml = evt.error ? _qaBuildRawErrorHtml(evt.error) : '';
@@ -725,6 +755,7 @@ async function _processQaMessage(message, selection, opts) {
725
755
  const loadingEl = tmp.querySelector('#' + loadingId);
726
756
  if (loadingEl) loadingEl.remove();
727
757
  _qaInsertBeforeQueued(tmp, answerHtml);
758
+ if (actionFeedbackHtml) _qaInsertBeforeQueued(tmp, actionFeedbackHtml);
728
759
  if (rawErrorHtml) _qaInsertBeforeQueued(tmp, rawErrorHtml);
729
760
  });
730
761
 
@@ -732,8 +763,17 @@ async function _processQaMessage(message, selection, opts) {
732
763
  runtime.history.push({ role: 'user', text: message });
733
764
  runtime.history.push({ role: 'assistant', text: bodyText || finalText || '' });
734
765
  if (evt.actions && evt.actions.length > 0) {
766
+ const actionResults = Array.isArray(evt.actionResults) ? evt.actionResults : [];
735
767
  if (evt.actionResults && typeof _tagServerExecuted === 'function') _tagServerExecuted(evt.actions, evt.actionResults);
736
- for (const action of evt.actions) await ccExecuteAction(action);
768
+ for (let ai = 0; ai < evt.actions.length; ai++) {
769
+ const action = evt.actions[ai];
770
+ const actionResult = actionResults[ai];
771
+ if (_qaActionFeedbackHandled(action, actionResult)) {
772
+ _qaRunHandledActionSideEffects(action, actionResult);
773
+ continue;
774
+ }
775
+ await ccExecuteAction(action);
776
+ }
737
777
  const actionContext = _qaSummarizeActionContext(evt.actions, evt.actionResults);
738
778
  if (actionContext) runtime.history.push({ role: 'action', text: actionContext });
739
779
  } else if (evt.actionParseError) {
@@ -81,6 +81,15 @@ function _getPipelineEmptyRunCopy(pipeline) {
81
81
  return 'No runs yet. Use Run Now to start this pipeline.';
82
82
  }
83
83
 
84
+ function _getPipelineDisplayTitle(pipeline) {
85
+ var title = pipeline && pipeline.title != null ? String(pipeline.title).trim() : '';
86
+ if (title && title.toLowerCase() !== 'undefined' && title.toLowerCase() !== 'null') return title;
87
+ var id = pipeline && pipeline.id != null ? String(pipeline.id).trim() : '';
88
+ var human = id.replace(/[_-]+/g, ' ').replace(/\s+/g, ' ').trim();
89
+ if (human) return human.charAt(0).toUpperCase() + human.slice(1);
90
+ return 'Untitled pipeline';
91
+ }
92
+
84
93
  /**
85
94
  * Render clickable artifact links for a pipeline stage.
86
95
  * Each artifact type gets an icon and navigates to the relevant detail view.
@@ -301,6 +310,7 @@ function renderPipelines(pipelines) {
301
310
  if ((p.stages || []).length > 0) {
302
311
  progressHtml = _buildNodeChain(p.stages || [], displayRun, { compact: true, pipeline: p });
303
312
  }
313
+ var displayTitle = _getPipelineDisplayTitle(p);
304
314
 
305
315
  // Monitored resources (pipeline-level + stage-level, compact on card)
306
316
  var allResources = _collectMonitoredResources(p);
@@ -309,7 +319,7 @@ function renderPipelines(pipelines) {
309
319
  return '<div class="pipeline-card" onclick="if(shouldIgnoreSelectionClick(event))return;openPipelineDetail(\'' + escHtml(p.id) + '\')">' +
310
320
  '<div class="pipeline-card-header">' +
311
321
  '<div class="pipeline-card-main">' +
312
- '<strong class="pipeline-card-title">' + escHtml(p.title || p.id) + '</strong>' +
322
+ '<strong class="pipeline-card-title">' + escHtml(displayTitle) + '</strong>' +
313
323
  '<div class="pipeline-card-meta">' +
314
324
  '<span>' + escHtml(p.id) + '</span>' +
315
325
  '<span>' + escHtml(_getPipelineStageLabel(p)) + '</span>' +
@@ -332,6 +342,7 @@ function openPipelineDetail(id) {
332
342
  _stopPipelinePoll();
333
343
  var p = _pipelinesData.find(function(x) { return x.id === id; });
334
344
  if (!p) { alert('Pipeline not found'); return; }
345
+ var displayTitle = _getPipelineDisplayTitle(p);
335
346
 
336
347
  var html = '<div style="display:flex;flex-direction:column;gap:12px">';
337
348
 
@@ -426,7 +437,7 @@ function openPipelineDetail(id) {
426
437
 
427
438
  html += '</div>';
428
439
 
429
- document.getElementById('modal-title').textContent = 'Pipeline: ' + p.title;
440
+ document.getElementById('modal-title').textContent = 'Pipeline: ' + displayTitle;
430
441
  document.getElementById('modal-body').innerHTML = html;
431
442
  document.getElementById('modal').classList.add('open');
432
443
 
@@ -663,6 +674,7 @@ async function _submitCreatePipeline() {
663
674
  function openEditPipelineModal(id) {
664
675
  var p = _pipelinesData.find(function(x) { return x.id === id; });
665
676
  if (!p) return;
677
+ var displayTitle = _getPipelineDisplayTitle(p);
666
678
  var 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';
667
679
  var pillStyle = 'display:inline-block;padding:4px 10px;margin:2px;border:1px solid var(--border);border-radius:12px;cursor:pointer;font-size:11px;color:var(--text);background:var(--bg);user-select:none;transition:all 0.15s';
668
680
  var linkStyle = 'font-size:10px;color:var(--blue);cursor:pointer;text-decoration:underline;margin-right:8px';
@@ -686,7 +698,7 @@ function openEditPipelineModal(id) {
686
698
 
687
699
  window._editPipelineId = id;
688
700
 
689
- document.getElementById('modal-title').textContent = 'Edit Pipeline: ' + p.title;
701
+ document.getElementById('modal-title').textContent = 'Edit Pipeline: ' + displayTitle;
690
702
  document.getElementById('modal-body').innerHTML =
691
703
  '<div style="display:flex;flex-direction:column;gap:10px">' +
692
704
  '<div style="color:var(--muted);font-size:11px">ID: <strong style="color:var(--text)">' + escHtml(id) + '</strong></div>' +
package/dashboard.js CHANGED
@@ -2837,6 +2837,31 @@ async function executeDocChatActions(actions, { filePath = null } = {}) {
2837
2837
  return executeCCActions(actions, { source: 'doc-chat', inferredProject: _inferDocChatProject(filePath) });
2838
2838
  }
2839
2839
 
2840
+ const DOC_CHAT_WORK_ITEM_ACTION_TYPES = new Set(['dispatch', 'fix', 'implement', 'explore', 'review', 'test']);
2841
+
2842
+ function _buildDocChatActionFeedback(actions, actionResults) {
2843
+ if (!Array.isArray(actions) || !Array.isArray(actionResults)) return [];
2844
+ const feedback = [];
2845
+ for (let i = 0; i < actions.length && i < actionResults.length; i++) {
2846
+ const action = actions[i] || {};
2847
+ const result = actionResults[i] || {};
2848
+ const type = String(result.type || action.type || '').trim();
2849
+ if (!DOC_CHAT_WORK_ITEM_ACTION_TYPES.has(type)) continue;
2850
+ if (result.error) {
2851
+ feedback.push({ type, error: String(result.error) });
2852
+ continue;
2853
+ }
2854
+ const id = result.id || result.duplicateOf;
2855
+ if (!result.ok || !id) continue;
2856
+ const item = { type, id: String(id), ok: true };
2857
+ if (result.duplicate) item.duplicate = true;
2858
+ if (result.duplicateOf) item.duplicateOf = String(result.duplicateOf);
2859
+ if (result.warning) item.warning = String(result.warning);
2860
+ feedback.push(item);
2861
+ }
2862
+ return feedback;
2863
+ }
2864
+
2840
2865
  // ── Shared LLM call core — used by CC panel and doc modals ──────────────────
2841
2866
 
2842
2867
  // Session store for doc modals — keyed by filePath or title, persisted to disk.
@@ -3447,6 +3472,7 @@ function _buildDocChatResponsePayload({
3447
3472
  answer,
3448
3473
  actions,
3449
3474
  actionResults,
3475
+ actionFeedback,
3450
3476
  actionParseError,
3451
3477
  ccError,
3452
3478
  partial,
@@ -3463,6 +3489,7 @@ function _buildDocChatResponsePayload({
3463
3489
  answer: finalAnswer,
3464
3490
  actions,
3465
3491
  ...(actionResults ? { actionResults } : {}),
3492
+ ...(Array.isArray(actionFeedback) && actionFeedback.length ? { actionFeedback } : {}),
3466
3493
  ...(actionParseError ? { actionParseError } : {}),
3467
3494
  ...(ccError && !suppressPostPatchError ? { error: ccError } : {}),
3468
3495
  ...(partial && !suppressPostPatchError ? { partial: true, warning } : {}),
@@ -5835,12 +5862,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5835
5862
  onAbortReady: (abort) => { _docAbort = abort; },
5836
5863
  });
5837
5864
  const actionResults = await executeDocChatActions(actions, { filePath: body.filePath });
5865
+ const actionFeedback = _buildDocChatActionFeedback(actions, actionResults);
5838
5866
  const finalize = _finalizeDocChatEdit({
5839
5867
  filePath: body.filePath, fullPath, isJson, canEdit,
5840
5868
  originalContent: currentContent, delimiterContent: content,
5841
5869
  });
5842
5870
  const payload = _buildDocChatResponsePayload({
5843
- answer, actions, actionResults, actionParseError, ccError, partial, warning, toolUses, finalize,
5871
+ answer, actions, actionResults, actionFeedback, actionParseError, ccError, partial, warning, toolUses, finalize,
5844
5872
  });
5845
5873
  _docDone = true;
5846
5874
  return jsonReply(res, 200, payload);
@@ -5929,12 +5957,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5929
5957
  onRetry: (attempt) => { writeDocEvent({ type: 'progress', attempt }); },
5930
5958
  });
5931
5959
  const actionResults = await executeDocChatActions(actions, { filePath: body.filePath });
5960
+ const actionFeedback = _buildDocChatActionFeedback(actions, actionResults);
5932
5961
  const finalize = _finalizeDocChatEdit({
5933
5962
  filePath: body.filePath, fullPath, isJson, canEdit,
5934
5963
  originalContent: currentContent, delimiterContent: content,
5935
5964
  });
5936
5965
  const payload = _buildDocChatResponsePayload({
5937
- answer, actions, actionResults, actionParseError, ccError, partial, warning, toolUses, finalize,
5966
+ answer, actions, actionResults, actionFeedback, actionParseError, ccError, partial, warning, toolUses, finalize,
5938
5967
  });
5939
5968
  const { answer: finalAnswer, ...donePayload } = payload;
5940
5969
  writeDocEvent({
@@ -8400,6 +8429,7 @@ module.exports = {
8400
8429
  _meetingParticipantsFromAction: meetingParticipantsFromAction,
8401
8430
  parsePinnedEntries,
8402
8431
  _parseDocChatResultText,
8432
+ _buildDocChatActionFeedback,
8403
8433
  _formatDocChatContext,
8404
8434
  _isCompletedMeetingJson,
8405
8435
  _finalizeDocChatEdit,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-08T01:28:01.692Z"
4
+ "cachedAt": "2026-05-08T01:35:12.713Z"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1785",
3
+ "version": "0.1.1787",
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"