@yemi33/minions 0.1.683 → 0.1.685

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,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.685 (2026-04-09)
4
+
5
+ ### Features
6
+ - collapsible doc-chat thread in modal
7
+
8
+ ### Fixes
9
+ - link work item artifacts to KB entries, not raw archive copies
10
+
3
11
  ## 0.1.683 (2026-04-09)
4
12
 
5
13
  ### Features
@@ -98,11 +98,11 @@ function _initQaSession() {
98
98
  });
99
99
  }
100
100
  if (prior.filePath) _modalFilePath = prior.filePath;
101
- document.getElementById('qa-clear-btn').style.display = 'block';
101
+ _showThreadWrap();
102
102
  } else {
103
103
  _qaHistory = [];
104
104
  document.getElementById('modal-qa-thread').innerHTML = '';
105
- document.getElementById('qa-clear-btn').style.display = 'none';
105
+ _hideThreadWrap();
106
106
  }
107
107
  }
108
108
 
@@ -111,7 +111,7 @@ function clearQaConversation() {
111
111
  _qaQueue = [];
112
112
  _qaProcessing = false;
113
113
  document.getElementById('modal-qa-thread').innerHTML = '';
114
- document.getElementById('qa-clear-btn').style.display = 'none';
114
+ _hideThreadWrap();
115
115
  if (_qaSessionKey) _qaSessions.delete(_qaSessionKey);
116
116
  }
117
117
 
@@ -146,6 +146,7 @@ function modalSend() {
146
146
  qHtml += '</div>';
147
147
  thread.innerHTML += qHtml;
148
148
  thread.scrollTop = thread.scrollHeight;
149
+ _showThreadWrap();
149
150
 
150
151
  // Clear input immediately so user can type next message
151
152
  input.value = '';
@@ -334,4 +335,27 @@ function qaAbort() {
334
335
  }
335
336
  }
336
337
 
337
- window.MinionsQA = { showModalQa, modalAskAboutSelection, clearQaSelection, clearQaConversation, modalSend, qaAbort };
338
+ function toggleDocChat() {
339
+ var wrap = document.getElementById('modal-qa-thread-wrap');
340
+ var expandBar = document.getElementById('qa-expand-bar');
341
+ if (!wrap) return;
342
+ var isVisible = wrap.style.display !== 'none';
343
+ wrap.style.display = isVisible ? 'none' : '';
344
+ if (expandBar) expandBar.style.display = isVisible ? '' : 'none';
345
+ }
346
+
347
+ function _showThreadWrap() {
348
+ var wrap = document.getElementById('modal-qa-thread-wrap');
349
+ var expandBar = document.getElementById('qa-expand-bar');
350
+ if (wrap) wrap.style.display = '';
351
+ if (expandBar) expandBar.style.display = 'none';
352
+ }
353
+
354
+ function _hideThreadWrap() {
355
+ var wrap = document.getElementById('modal-qa-thread-wrap');
356
+ var expandBar = document.getElementById('qa-expand-bar');
357
+ if (wrap) wrap.style.display = 'none';
358
+ if (expandBar) expandBar.style.display = 'none';
359
+ }
360
+
361
+ window.MinionsQA = { showModalQa, modalAskAboutSelection, clearQaSelection, clearQaConversation, modalSend, qaAbort, toggleDocChat };
@@ -458,8 +458,17 @@ function openWorkItemDetail(id) {
458
458
  if (arts.sourcePlan) artPills += '<span onclick="planView(\'' + escHtml(arts.sourcePlan) + '\')" style="' + pillStyle + '">📋 Source Plan</span> ';
459
459
  if (arts.notes && arts.notes.length > 0) arts.notes.forEach(function(n) {
460
460
  var noteFile = (n && typeof n === 'object') ? (n.file || n) : String(n || '');
461
- var noteLabel = noteFile.replace(/\.md$/, '').slice(0, 30);
462
- artPills += '<span onclick="openInboxNote(\'' + escHtml(noteFile) + '\')" style="' + pillStyle + '">📝 ' + escHtml(noteLabel) + '</span> ';
461
+ // KB entries prefixed with 'kb:category/file'
462
+ if (noteFile.startsWith('kb:')) {
463
+ var kbParts = noteFile.slice(3).split('/');
464
+ var kbCat = kbParts[0];
465
+ var kbFile = kbParts.slice(1).join('/');
466
+ var kbLabel = kbFile.replace(/\.md$/, '').slice(0, 30);
467
+ artPills += '<span onclick="kbOpenItem(\'' + escHtml(kbCat) + '\',\'' + escHtml(kbFile) + '\')" style="' + pillStyle + '">📚 ' + escHtml(kbLabel) + '</span> ';
468
+ } else {
469
+ var noteLabel = noteFile.replace(/\.md$/, '').slice(0, 30);
470
+ artPills += '<span onclick="openInboxNote(\'' + escHtml(noteFile) + '\')" style="' + pillStyle + '">📝 ' + escHtml(noteLabel) + '</span> ';
471
+ }
463
472
  });
464
473
  if (arts.skills && arts.skills.length > 0) arts.skills.forEach(function(s) { artPills += '<span onclick="openSkill(\'' + escHtml(s) + '\',\'minions\',\'\')" style="' + pillStyle + '">⚙ ' + escHtml(s) + '</span> '; });
465
474
  if (artPills) html += field('Artifacts', '<div style="display:flex;flex-wrap:wrap;gap:4px">' + artPills + '</div>');
@@ -503,17 +512,10 @@ function viewAgentOutput(logPath) {
503
512
  }
504
513
 
505
514
  function openInboxNote(filename) {
506
- var isArchive = filename.startsWith('archive/');
507
- var baseName = isArchive ? filename.replace('archive/', '') : filename;
508
- // Try inbox first
509
- var idx = (inboxData || []).findIndex(function(item) { return item.name === baseName; });
515
+ var idx = (inboxData || []).findIndex(function(item) { return item.name === filename; });
510
516
  if (idx >= 0) { openModal(idx); return; }
511
- // Archived or not found in inbox — show label indicating it was consolidated
512
- document.getElementById('modal-title').textContent = baseName.replace(/\.md$/, '');
513
- document.getElementById('modal-body').innerHTML = '<p style="color:var(--muted)">This note was consolidated into the Knowledge Base.' +
514
- (isArchive ? ' <span style="font-size:10px">(archived: ' + escHtml(baseName) + ')</span>' : '') +
515
- '</p><div style="margin-top:8px"><button class="pr-pager-btn" onclick="closeModal();switchPage(\'inbox\')">Go to Notes & KB</button></div>';
516
- document.getElementById('modal').classList.add('open');
517
+ closeModal();
518
+ switchPage('inbox');
517
519
  }
518
520
 
519
521
  window.MinionsWork = { wiRow, renderWorkItems, editWorkItem, submitWorkItemEdit, deleteWorkItem, archiveWorkItem, toggleWorkItemArchive, retryWorkItem, wiPrev, wiNext, feedbackWorkItem, submitFeedback, openCreateWorkItemModal, openWorkItemDetail, openAllWorkItems, viewAgentOutput, openInboxNote };
@@ -108,9 +108,15 @@
108
108
  </div>
109
109
  <div class="modal-body" id="modal-body"></div>
110
110
  <div class="modal-qa" id="modal-qa" style="display:none">
111
- <div style="display:flex;align-items:center;justify-content:space-between;min-height:0">
112
- <div class="modal-qa-thread" id="modal-qa-thread" style="flex:1"></div>
113
- <button id="qa-clear-btn" style="display:none;background:none;border:none;color:var(--muted);font-size:10px;cursor:pointer;padding:2px 6px;white-space:nowrap;align-self:flex-start" onclick="clearQaConversation()" title="Clear conversation">Clear chat</button>
111
+ <div id="modal-qa-thread-wrap" style="display:none">
112
+ <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px">
113
+ <button id="qa-clear-btn" style="background:none;border:none;color:var(--muted);font-size:10px;cursor:pointer;padding:2px 6px" onclick="clearQaConversation()" title="Clear conversation">Clear</button>
114
+ <button id="qa-toggle-btn" style="background:none;border:none;color:var(--muted);font-size:10px;cursor:pointer;padding:2px 6px" onclick="toggleDocChat()" title="Collapse thread">&#x25BC; Collapse</button>
115
+ </div>
116
+ <div class="modal-qa-thread" id="modal-qa-thread"></div>
117
+ </div>
118
+ <div id="qa-expand-bar" style="display:none;margin-bottom:4px">
119
+ <button style="background:none;border:none;color:var(--muted);font-size:10px;cursor:pointer;padding:2px 6px" onclick="toggleDocChat()">&#x25B2; Show thread</button>
114
120
  </div>
115
121
  <div class="modal-qa-selection-pill" id="modal-qa-pill" style="display:none">
116
122
  <span class="pill-label">Selection:</span>
@@ -118,7 +124,7 @@
118
124
  <button class="pill-clear" onclick="clearQaSelection()" title="Clear selection">&times;</button>
119
125
  </div>
120
126
  <div class="modal-qa-input-wrap">
121
- <input type="text" class="modal-qa-input" id="modal-qa-input" placeholder="Ask about this document..." onkeydown="if(event.key==='Enter')modalSend()">
127
+ <input type="text" class="modal-qa-input" id="modal-qa-input" placeholder="Ask about this document (or select text first)..." onkeydown="if(event.key==='Enter')modalSend()">
122
128
  <button class="modal-qa-btn" id="modal-send-btn" onclick="modalSend()">Send</button>
123
129
  </div>
124
130
  </div>
package/engine/queries.js CHANGED
@@ -592,10 +592,12 @@ function getKnowledgeBaseEntries() {
592
592
  const title = titleMatch ? titleMatch[1].trim() : f.replace(/\.md$/, '');
593
593
  const agentMatch = f.match(/^\d{4}-\d{2}-\d{2}-(\w+)-/);
594
594
  const dateMatch = f.match(/^(\d{4}-\d{2}-\d{2})/);
595
+ const sourceMatch = content.match(/^source:\s*(.+)/m);
595
596
  entries.push({
596
597
  cat, file: f, title,
597
598
  agent: agentMatch ? agentMatch[1] : '',
598
599
  date: dateMatch ? dateMatch[1] : '',
600
+ source: sourceMatch ? sourceMatch[1].trim() : '',
599
601
  preview: content.slice(0, 200),
600
602
  size: content.length,
601
603
  });
@@ -719,7 +721,8 @@ function getWorkItems(config) {
719
721
  }
720
722
  const _agentDirCache = {};
721
723
  const _inboxFiles = safeReadDir(INBOX_DIR);
722
- const _archiveFiles = safeReadDir(ARCHIVE_DIR);
724
+ // Use cached KB entries (includes source frontmatter field)
725
+ const _kbEntries = getKnowledgeBaseEntries();
723
726
  for (const item of allItems) {
724
727
  const arts = {};
725
728
  const agentId = item.dispatched_to || item.agent;
@@ -733,11 +736,14 @@ function getWorkItems(config) {
733
736
  const matchLog = _agentDirCache[agentId].find(f => f.includes(dispatchId));
734
737
  if (matchLog) arts.outputLog = agentId + '/' + matchLog;
735
738
  }
736
- // Inbox + archive notes match by agent ID + work item ID in filename
739
+ // Notes: check inbox first, then KB (consolidated destination) via source field
737
740
  const itemId = item.id || '___';
738
- const matchNotes = _inboxFiles.filter(f => f.includes(agentId) && f.includes(itemId));
739
- const matchArchive = _archiveFiles.filter(f => f.includes(agentId) && f.includes(itemId));
740
- const allNotes = [...matchNotes, ...matchArchive.map(f => 'archive/' + f)];
741
+ const matchInbox = _inboxFiles.filter(f => f.includes(agentId) && f.includes(itemId));
742
+ const matchKb = _kbEntries.filter(kb => kb.source && kb.source.includes(agentId) && kb.source.includes(itemId));
743
+ const allNotes = [
744
+ ...matchInbox,
745
+ ...matchKb.map(kb => 'kb:' + kb.cat + '/' + kb.file),
746
+ ];
741
747
  if (allNotes.length > 0) arts.notes = allNotes;
742
748
  }
743
749
  if (item.branch || item.featureBranch) arts.branch = item.branch || item.featureBranch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.683",
3
+ "version": "0.1.685",
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"