@yemi33/minions 0.1.1836 → 0.1.1838

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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1838 (2026-05-10)
4
+
5
+ ### Features
6
+ - remove dead savePipelineRuns() in engine/pipeline.js (#2282)
7
+
8
+ ## 0.1.1837 (2026-05-10)
9
+
10
+ ### Features
11
+ - wire X-CC-Turn-Id + mtime snapshot for "Document saved" chip
12
+
3
13
  ## 0.1.1836 (2026-05-10)
4
14
 
5
15
  ### Other
package/dashboard.js CHANGED
@@ -1693,6 +1693,25 @@ function _buildSyntheticActionResultsForTurn(turnId, message, requestedAt) {
1693
1693
  return { actions, results };
1694
1694
  }
1695
1695
 
1696
+ // Cheap mtime+size snapshot used by doc-chat to detect whether CC's `Edit` /
1697
+ // `Write` tool calls actually changed the target file during a turn. A diff
1698
+ // triggers a "Document saved" chip via the same _ccTurnCreations surface used
1699
+ // by mutating /api/* endpoints.
1700
+ function _snapshotDocFile(fullPath) {
1701
+ if (!fullPath) return null;
1702
+ try {
1703
+ const st = fs.statSync(fullPath);
1704
+ return { mtimeMs: st.mtimeMs, size: st.size };
1705
+ } catch { return { mtimeMs: 0, size: 0 }; } // missing file → all changes look like edits
1706
+ }
1707
+
1708
+ function _docFileChanged(before, fullPath) {
1709
+ if (!fullPath) return false;
1710
+ const after = _snapshotDocFile(fullPath);
1711
+ if (!before || !after) return false;
1712
+ return before.mtimeMs !== after.mtimeMs || before.size !== after.size;
1713
+ }
1714
+
1696
1715
  function _ccTurnEntryToActionType(kind) {
1697
1716
  switch (kind) {
1698
1717
  case 'work-item': return 'dispatch';
@@ -2815,7 +2834,7 @@ function _makeDocChatStreamStripper(onChunk) {
2815
2834
  }
2816
2835
 
2817
2836
  // Doc-specific wrapper — adds document context, parses ---DOCUMENT---
2818
- async function ccDocCall({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, transcript, onAbortReady }) {
2837
+ async function ccDocCall({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, transcript, onAbortReady, systemPrompt = DOC_CHAT_SYSTEM_PROMPT }) {
2819
2838
  const sessionKey = filePath || title;
2820
2839
  const docSlice = String(document || '');
2821
2840
 
@@ -2835,13 +2854,10 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
2835
2854
  store: 'doc', sessionKey,
2836
2855
  extraContext, label: 'doc-chat',
2837
2856
  timeout: DOC_CHAT_TIMEOUT_MS,
2838
- // Match Command Center's full tool surface and turn budget so doc-chat
2839
- // can take action (read/write/edit/dispatch) instead of being limited
2840
- // to Q&A. The doc-chat sysprompt scopes orchestration to human message
2841
- // intent (explicit dispatch or medium/larger work), and ---DOCUMENT---
2842
- // remains the only whole-file document edit channel.
2857
+ // Match Command Center's full tool surface so doc-chat can take action
2858
+ // (read/write/edit/dispatch) instead of being limited to Q&A.
2843
2859
  allowedTools: 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch',
2844
- systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
2860
+ systemPrompt,
2845
2861
  transcript,
2846
2862
  ...(model ? { model } : {}),
2847
2863
  onAbortReady,
@@ -2885,7 +2901,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
2885
2901
  return { answer: result.text, toolUses: Array.isArray(result.toolUses) ? result.toolUses : [] };
2886
2902
  }
2887
2903
 
2888
- async function ccDocCallStreaming({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, transcript, onAbortReady, onChunk, onToolUse, onRetry }) {
2904
+ async function ccDocCallStreaming({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, transcript, onAbortReady, onChunk, onToolUse, onRetry, systemPrompt = DOC_CHAT_SYSTEM_PROMPT }) {
2889
2905
  const sessionKey = filePath || title;
2890
2906
  const docSlice = String(document || '');
2891
2907
  const streamStripper = _makeDocChatStreamStripper(onChunk);
@@ -2902,11 +2918,9 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
2902
2918
  store: 'doc', sessionKey,
2903
2919
  extraContext, label: 'doc-chat',
2904
2920
  timeout: DOC_CHAT_TIMEOUT_MS,
2905
- // Match Command Center's full tool surface — see ccDocCall for
2906
- // rationale. Both wrappers must share the same policy so the streaming
2907
- // variant doesn't diverge from the non-streaming one.
2921
+ // Match Command Center's full tool surface — see ccDocCall for rationale.
2908
2922
  allowedTools: 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch',
2909
- systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
2923
+ systemPrompt,
2910
2924
  transcript,
2911
2925
  ...(model ? { model } : {}),
2912
2926
  onAbortReady,
@@ -5013,6 +5027,14 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5013
5027
  }
5014
5028
  }
5015
5029
 
5030
+ // Per-turn correlation: render the doc-chat sysprompt with a fresh
5031
+ // {{cc_turn_id}} so any /api/* calls CC makes during the turn surface
5032
+ // as chips, plus snapshot the target file so we can detect Edit/Write
5033
+ // tool changes and emit a "Document saved" chip.
5034
+ const ccTurnId = 'cct-' + shared.uid();
5035
+ const turnSystemPrompt = renderDocChatSystemPromptForTurn(ccTurnId);
5036
+ const docFileBefore = _snapshotDocFile(fullPath);
5037
+
5016
5038
  let { answer, partial, warning, toolUses, error: ccError } = await ccDocCall({
5017
5039
  message: body.message, document: currentContent, title: body.title,
5018
5040
  filePath: body.filePath, selection: body.selection, canEdit, isJson,
@@ -5020,17 +5042,24 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5020
5042
  freshSession: !!body.freshSession,
5021
5043
  transcript: body.transcript,
5022
5044
  onAbortReady: (abort) => { _docAbort = abort; },
5045
+ systemPrompt: turnSystemPrompt,
5023
5046
  });
5024
- // CC now mutates files via the Edit/Write tools and dispatches via direct
5025
- // /api/* calls (correlated by X-CC-Turn-Id). No server-side parsing of
5026
- // ===ACTIONS=== or ---DOCUMENT--- — _finalizeDocChatEdit just confirms
5027
- // the file on disk changed during the turn.
5028
5047
  const finalize = _finalizeDocChatEdit({
5029
5048
  filePath: body.filePath, fullPath, isJson, canEdit,
5030
5049
  originalContent: currentContent, delimiterContent: null,
5031
5050
  });
5051
+ // Record a document-saved entry under this turn ID if the file mtime/size
5052
+ // changed during the call — surfaces as a "Document saved" chip.
5053
+ if (canEdit && _docFileChanged(docFileBefore, fullPath)) {
5054
+ _recordCcTurnCreation(ccTurnId, { kind: 'document-saved', path: body.filePath });
5055
+ }
5056
+ const _synthetic = _buildSyntheticActionResultsForTurn(ccTurnId, body.message, new Date().toISOString());
5032
5057
  const payload = _buildDocChatResponsePayload({
5033
- answer, actions: [], actionResults: [], actionFeedback: null, actionParseError: null, ccError, partial, warning, toolUses, finalize,
5058
+ answer,
5059
+ actions: _synthetic.actions,
5060
+ actionResults: _synthetic.results,
5061
+ actionFeedback: null, actionParseError: null,
5062
+ ccError, partial, warning, toolUses, finalize,
5034
5063
  });
5035
5064
  _docDone = true;
5036
5065
  return jsonReply(res, 200, payload);
@@ -5107,6 +5136,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5107
5136
 
5108
5137
  try {
5109
5138
 
5139
+ // Per-turn correlation: see handleDocChat for the matching pattern.
5140
+ const ccTurnId = 'cct-' + shared.uid();
5141
+ const turnSystemPrompt = renderDocChatSystemPromptForTurn(ccTurnId);
5142
+ const docFileBefore = _snapshotDocFile(fullPath);
5143
+
5110
5144
  let { answer, partial, warning, toolUses, error: ccError } = await ccDocCallStreaming({
5111
5145
  message: body.message, document: currentContent, title: body.title,
5112
5146
  filePath: body.filePath, selection: body.selection, canEdit, isJson,
@@ -5117,13 +5151,22 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5117
5151
  onChunk: (text) => { writeDocEvent({ type: 'chunk', text }); },
5118
5152
  onToolUse: (name, input) => { writeDocEvent({ type: 'tool', name, input: _lightToolInput(input) }); },
5119
5153
  onRetry: (attempt) => { writeDocEvent({ type: 'progress', attempt }); },
5154
+ systemPrompt: turnSystemPrompt,
5120
5155
  });
5121
5156
  const finalize = _finalizeDocChatEdit({
5122
5157
  filePath: body.filePath, fullPath, isJson, canEdit,
5123
5158
  originalContent: currentContent, delimiterContent: null,
5124
5159
  });
5160
+ if (canEdit && _docFileChanged(docFileBefore, fullPath)) {
5161
+ _recordCcTurnCreation(ccTurnId, { kind: 'document-saved', path: body.filePath });
5162
+ }
5163
+ const _streamSynthetic = _buildSyntheticActionResultsForTurn(ccTurnId, body.message, new Date().toISOString());
5125
5164
  const payload = _buildDocChatResponsePayload({
5126
- answer, actions: [], actionResults: [], actionFeedback: null, actionParseError: null, ccError, partial, warning, toolUses, finalize,
5165
+ answer,
5166
+ actions: _streamSynthetic.actions,
5167
+ actionResults: _streamSynthetic.results,
5168
+ actionFeedback: null, actionParseError: null,
5169
+ ccError, partial, warning, toolUses, finalize,
5127
5170
  });
5128
5171
  const { answer: finalAnswer, ...donePayload } = payload;
5129
5172
  writeDocEvent({
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-10T02:24:14.319Z"
4
+ "cachedAt": "2026-05-10T02:49:08.142Z"
5
5
  }
@@ -73,10 +73,6 @@ function getPipelineRuns() {
73
73
  return safeJson(PIPELINE_RUNS_PATH) || {};
74
74
  }
75
75
 
76
- function savePipelineRuns(runs) {
77
- safeWrite(PIPELINE_RUNS_PATH, runs);
78
- }
79
-
80
76
  function getActiveRun(pipelineId) {
81
77
  const runs = getPipelineRuns();
82
78
  const pipelineRuns = runs[pipelineId] || [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1836",
3
+ "version": "0.1.1838",
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"