@yemi33/minions 0.1.1838 → 0.1.1839

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.1839 (2026-05-10)
4
+
5
+ ### Other
6
+ - refactor(cc): simplify CC migration code per /simplify review
7
+
3
8
  ## 0.1.1838 (2026-05-10)
4
9
 
5
10
  ### Features
package/dashboard.js CHANGED
@@ -1592,21 +1592,20 @@ const DOC_CHAT_SYSTEM_PROMPT_RAW = (() => {
1592
1592
  }
1593
1593
  })();
1594
1594
 
1595
- const DOC_CHAT_SYSTEM_PROMPT = DOC_CHAT_SYSTEM_PROMPT_RAW
1596
- .replace(/\{\{minions_dir\}\}/g, MINIONS_DIR);
1595
+ const DOC_CHAT_SYSTEM_PROMPT = shared.renderCcSystemPrompt(DOC_CHAT_SYSTEM_PROMPT_RAW, { liveRoot: MINIONS_DIR });
1597
1596
 
1598
1597
  function renderDocChatSystemPromptForTurn(turnId) {
1599
- return DOC_CHAT_SYSTEM_PROMPT_RAW
1600
- .replace(/\{\{minions_dir\}\}/g, MINIONS_DIR)
1601
- .replace(/\{\{cc_turn_id\}\}/g, String(turnId || ''))
1602
- .replace(/\{\{dashboard_port\}\}/g, String(PORT));
1598
+ return shared.renderCcSystemPrompt(DOC_CHAT_SYSTEM_PROMPT_RAW, {
1599
+ liveRoot: MINIONS_DIR,
1600
+ turnId: turnId || '',
1601
+ dashboardPort: PORT,
1602
+ });
1603
1603
  }
1604
1604
 
1605
1605
  // Per-CC-turn correlation. CC's tool calls (Bash curl to /api/...) attach an
1606
- // X-CC-Turn-Id header; the mutating endpoints record creations into this map
1607
- // keyed by the turn ID so the CC handler can surface them as confirmation
1608
- // chips in the user's reply. Complements (and will eventually replace) the
1609
- // ===ACTIONS=== protocol — both currently active during transition.
1606
+ // X-CC-Turn-Id header; mutating endpoints record their creations into this
1607
+ // map keyed by the turn ID so the CC handler can surface them as confirmation
1608
+ // chips in the user's reply.
1610
1609
  const _ccTurnCreations = new Map();
1611
1610
  const CC_TURN_CREATION_TTL_MS = (() => {
1612
1611
  const env = parseInt(process.env.CC_TURN_CREATION_TTL_MS || '', 10);
@@ -1649,10 +1648,17 @@ function _readCcTurnIdHeader(req) {
1649
1648
  return trimmed;
1650
1649
  }
1651
1650
 
1652
- // Build synthetic action results from the turn map so the existing renderer
1653
- // (_ccActionContextSuffix in dashboard/js/command-center.js) shows the same
1654
- // "Dispatched: <id>" chip whether the work item was created by a direct CC API
1655
- // call or by the (now-removed) ===ACTIONS=== executor.
1651
+ // Mutating endpoint helper: records the creation under the request's CC turn
1652
+ // ID if one was sent, otherwise no-ops. Keeps the wiring at each handler down
1653
+ // to a single line.
1654
+ function recordCcTurnIfPresent(req, entry) {
1655
+ const turnId = _readCcTurnIdHeader(req);
1656
+ if (turnId) _recordCcTurnCreation(turnId, entry);
1657
+ }
1658
+
1659
+ // Build action results from the turn map so the existing renderer
1660
+ // (_ccActionContextSuffix in dashboard/js/command-center.js) shows a
1661
+ // "Dispatched: <id>" chip for each direct CC API call.
1656
1662
  function _buildSyntheticActionResultsForTurn(turnId, message, requestedAt) {
1657
1663
  const entries = _consumeCcTurnCreations(turnId);
1658
1664
  if (entries.length === 0) return { actions: [], results: [] };
@@ -1696,19 +1702,22 @@ function _buildSyntheticActionResultsForTurn(turnId, message, requestedAt) {
1696
1702
  // Cheap mtime+size snapshot used by doc-chat to detect whether CC's `Edit` /
1697
1703
  // `Write` tool calls actually changed the target file during a turn. A diff
1698
1704
  // triggers a "Document saved" chip via the same _ccTurnCreations surface used
1699
- // by mutating /api/* endpoints.
1705
+ // by mutating /api/* endpoints. Missing files snapshot as null so callers can
1706
+ // distinguish "file existed and was edited" from "file was deleted/never
1707
+ // existed" — only the former should surface a chip.
1700
1708
  function _snapshotDocFile(fullPath) {
1701
1709
  if (!fullPath) return null;
1702
1710
  try {
1703
1711
  const st = fs.statSync(fullPath);
1704
1712
  return { mtimeMs: st.mtimeMs, size: st.size };
1705
- } catch { return { mtimeMs: 0, size: 0 }; } // missing file → all changes look like edits
1713
+ } catch { return null; }
1706
1714
  }
1707
1715
 
1708
1716
  function _docFileChanged(before, fullPath) {
1709
1717
  if (!fullPath) return false;
1710
1718
  const after = _snapshotDocFile(fullPath);
1711
- if (!before || !after) return false;
1719
+ if (!after) return false; // file gone or never existed — don't fire a chip
1720
+ if (!before) return true; // file created during the turn = a save
1712
1721
  return before.mtimeMs !== after.mtimeMs || before.size !== after.size;
1713
1722
  }
1714
1723
 
@@ -2893,11 +2902,10 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
2893
2902
  return _docChatFailureResponse('doc-chat', filePath, result, sessionPreserved);
2894
2903
  }
2895
2904
 
2896
- // No more ===ACTIONS=== / ---DOCUMENT--- parsing CC's text answer is the
2897
- // visible reply; file edits land via Edit/Write tools (validated in
2898
- // _finalizeDocChatEdit by re-reading disk); state mutations land via direct
2899
- // /api/* calls (correlated by X-CC-Turn-Id, surfaced as synthetic chips
2900
- // server-side).
2905
+ // CC's text answer is the visible reply. File edits land via the Edit/Write
2906
+ // tools (verified by _finalizeDocChatEdit re-reading disk); state mutations
2907
+ // land via direct /api/* calls (correlated by X-CC-Turn-Id, surfaced as
2908
+ // chips server-side).
2901
2909
  return { answer: result.text, toolUses: Array.isArray(result.toolUses) ? result.toolUses : [] };
2902
2910
  }
2903
2911
 
@@ -2955,11 +2963,10 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
2955
2963
  return _docChatFailureResponse('doc-chat-stream', filePath, result, sessionPreserved);
2956
2964
  }
2957
2965
 
2958
- // No more ===ACTIONS=== / ---DOCUMENT--- parsing CC's text answer is the
2959
- // visible reply; file edits land via Edit/Write tools (validated in
2960
- // _finalizeDocChatEdit by re-reading disk); state mutations land via direct
2961
- // /api/* calls (correlated by X-CC-Turn-Id, surfaced as synthetic chips
2962
- // server-side).
2966
+ // CC's text answer is the visible reply. File edits land via the Edit/Write
2967
+ // tools (verified by _finalizeDocChatEdit re-reading disk); state mutations
2968
+ // land via direct /api/* calls (correlated by X-CC-Turn-Id, surfaced as
2969
+ // chips server-side).
2963
2970
  return { answer: result.text, toolUses: Array.isArray(result.toolUses) ? result.toolUses : [] };
2964
2971
  }
2965
2972
 
@@ -3641,13 +3648,7 @@ const server = http.createServer(async (req, res) => {
3641
3648
  const duplicateId = createResult.duplicateOf || createResult.item?.id;
3642
3649
  return jsonReply(res, 200, { ok: true, id: duplicateId, duplicate: true, duplicateOf: duplicateId });
3643
3650
  }
3644
- // CC turn-ID correlation: record direct API creations so the CC handler
3645
- // can surface a "Dispatched: <id>" chip in the assistant reply without
3646
- // CC needing to also emit an ===ACTIONS=== block.
3647
- const _ccTurn = _readCcTurnIdHeader(req);
3648
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, {
3649
- kind: 'work-item', id, title: item.title, project: item.project || null,
3650
- });
3651
+ recordCcTurnIfPresent(req, { kind: 'work-item', id, title: item.title, project: item.project || null });
3651
3652
  return jsonReply(res, 200, { ok: true, id });
3652
3653
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
3653
3654
  }
@@ -3704,8 +3705,7 @@ const server = http.createServer(async (req, res) => {
3704
3705
  const content = `# ${body.title}\n\n**By:** ${author}\n**Date:** ${today}\n\n${body.what}\n${body.why ? '\n**Why:** ' + body.why + '\n' : ''}`;
3705
3706
  safeWrite(shared.uniquePath(path.join(inboxDir, filename)), content);
3706
3707
  invalidateStatusCache();
3707
- const _ccTurn = _readCcTurnIdHeader(req);
3708
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, { kind: 'note', title: body.title.trim() });
3708
+ recordCcTurnIfPresent(req, { kind: 'note', title: body.title.trim() });
3709
3709
  return jsonReply(res, 200, { ok: true });
3710
3710
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
3711
3711
  }
@@ -3719,8 +3719,7 @@ const server = http.createServer(async (req, res) => {
3719
3719
  // Write as a work item with type 'plan' — user must explicitly execute plan-to-prd after reviewing
3720
3720
  const wiPath = path.join(MINIONS_DIR, 'work-items.json');
3721
3721
  mutateWorkItems(wiPath, items => { items.push(planWorkItem.item); });
3722
- const _ccTurn = _readCcTurnIdHeader(req);
3723
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, {
3722
+ recordCcTurnIfPresent(req, {
3724
3723
  kind: 'plan', id: planWorkItem.id, title: planWorkItem.item?.title || body.title.trim(), project: planWorkItem.item?.project || null,
3725
3724
  });
3726
3725
  return jsonReply(res, 200, { ok: true, id: planWorkItem.id, agent: body.agent || '' });
@@ -5669,10 +5668,9 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5669
5668
  }
5670
5669
  const wasResume = !!(body.sessionId && body.sessionId === ccSession.sessionId && ccSessionValid());
5671
5670
 
5672
- // Per-turn correlation: CC includes X-CC-Turn-Id when calling /api/*
5673
- // mutating endpoints; the turn map collects creations so we can surface
5674
- // them as confirmation chips alongside any (now-legacy) ===ACTIONS===
5675
- // results.
5671
+ // Per-turn correlation: CC includes X-CC-Turn-Id on its /api/* tool
5672
+ // calls; the turn map collects creations so we surface them as
5673
+ // confirmation chips in the assistant reply.
5676
5674
  const ccTurnId = 'cct-' + shared.uid();
5677
5675
  const turnSystemPrompt = renderCcSystemPromptForTurn(ccTurnId);
5678
5676
  const result = await ccCall(body.message, { store: 'cc', transcript: body.transcript, systemPrompt: turnSystemPrompt });
@@ -5928,9 +5926,8 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5928
5926
  const streamModel = CONFIG.engine?.ccModel || shared.ENGINE_DEFAULTS.ccModel;
5929
5927
  const streamEffort = CONFIG.engine?.ccEffort || shared.ENGINE_DEFAULTS.ccEffort;
5930
5928
  const ccMaxTurns = CONFIG.engine?.ccMaxTurns || shared.ENGINE_DEFAULTS.ccMaxTurns;
5931
- // Per-turn correlation header: CC threads X-CC-Turn-Id when calling
5932
- // /api/* endpoints; matching creations get surfaced as confirmation
5933
- // chips alongside any (legacy) ===ACTIONS=== executor results.
5929
+ // Per-turn correlation header: CC threads X-CC-Turn-Id on its /api/*
5930
+ // tool calls; matching creations get surfaced as confirmation chips.
5934
5931
  const ccTurnId = 'cct-' + shared.uid();
5935
5932
  const turnSystemPrompt = renderCcSystemPromptForTurn(ccTurnId);
5936
5933
  let toolUses = [];
@@ -6279,8 +6276,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6279
6276
  try {
6280
6277
  const watch = watchesMod.createWatch({ target, targetType, condition, interval, owner, description, project, notify, stopAfter, onNotMet });
6281
6278
  invalidateStatusCache();
6282
- const _ccTurn = _readCcTurnIdHeader(req);
6283
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, {
6279
+ recordCcTurnIfPresent(req, {
6284
6280
  kind: 'watch', id: watch?.id || null, title: `Watch ${target}` + (condition ? ` (${condition})` : ''), project: project || null,
6285
6281
  });
6286
6282
  return jsonReply(res, 200, { ok: true, watch });
@@ -7237,8 +7233,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
7237
7233
  safeWrite(filePath, header + content);
7238
7234
  queries.invalidateKnowledgeBaseCache();
7239
7235
  invalidateStatusCache();
7240
- const _ccTurn = _readCcTurnIdHeader(req);
7241
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, { kind: 'knowledge', title, path: filePath });
7236
+ recordCcTurnIfPresent(req, { kind: 'knowledge', title, path: filePath });
7242
7237
  return jsonReply(res, 200, { ok: true, path: filePath });
7243
7238
  }},
7244
7239
  { method: 'POST', path: '/api/knowledge/sweep', desc: 'Trigger async KB sweep (returns 202)', handler: handleKnowledgeSweep },
@@ -7671,7 +7666,7 @@ module.exports = {
7671
7666
  _inferDocChatProject,
7672
7667
  _linkPullRequestForTracking: linkPullRequestForTracking,
7673
7668
  _resolveSkillReadPath,
7674
- // Per-CC-turn correlation surface (replaces ===ACTIONS=== protocol)
7669
+ // Per-CC-turn correlation surface
7675
7670
  _ccTurnCreations,
7676
7671
  _recordCcTurnCreation,
7677
7672
  _consumeCcTurnCreations,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-10T02:49:08.142Z"
4
+ "cachedAt": "2026-05-10T02:54:40.580Z"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1838",
3
+ "version": "0.1.1839",
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"