@yemi33/minions 0.1.1787 → 0.1.1789

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.1789 (2026-05-08)
4
+
5
+ ### Other
6
+ - Fix Claude CC resume bookkeeping
7
+
8
+ ## 0.1.1788 (2026-05-08)
9
+
10
+ ### Other
11
+ - Fix Copilot CC session persistence
12
+
3
13
  ## 0.1.1787 (2026-05-08)
4
14
 
5
15
  ### Features
package/dashboard.js CHANGED
@@ -1434,6 +1434,21 @@ function _ccRuntimeNeedsResumeCarryover(runtimeName) {
1434
1434
  }
1435
1435
  }
1436
1436
 
1437
+ const CC_RESUME_BOOKKEEPING_GUARD = [
1438
+ 'System note for this resumed Minions Command Center request:',
1439
+ 'Some runtimes insert synthetic resume bookkeeping turns such as `Continue from where you left off.` followed by `No response requested.`',
1440
+ 'Do not treat those bookkeeping turns as user requests when answering questions about what the user asked or what happened in the conversation.',
1441
+ ].join('\n');
1442
+
1443
+ function _ccRuntimeNeedsResumeBookkeepingGuard(runtimeName) {
1444
+ try {
1445
+ const runtime = resolveRuntime(runtimeName);
1446
+ return !!runtime?.capabilities?.resumeBookkeepingTurn;
1447
+ } catch {
1448
+ return false;
1449
+ }
1450
+ }
1451
+
1437
1452
  function _joinCcPromptParts(...parts) {
1438
1453
  return parts.filter(Boolean).join('\n\n---\n\n');
1439
1454
  }
@@ -3058,13 +3073,16 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
3058
3073
 
3059
3074
  const existing = resolveSession(store, sessionKey);
3060
3075
  let sessionId = existing ? existing.sessionId : null;
3061
- const resumeNeedsCarryover = !!sessionId && _ccRuntimeNeedsResumeCarryover(shared.resolveCcCli(CONFIG.engine));
3076
+ const currentRuntime = shared.resolveCcCli(CONFIG.engine);
3077
+ const resumeNeedsCarryover = !!sessionId && _ccRuntimeNeedsResumeCarryover(currentRuntime);
3078
+ const resumeNeedsBookkeepingGuard = !!sessionId && _ccRuntimeNeedsResumeBookkeepingGuard(currentRuntime);
3062
3079
  const resumeHasOutOfBandCarryover = !!sessionId && _transcriptHasCarryoverContext(transcript, { outOfBandOnly: true, currentMessage: message });
3063
3080
  const freshNeedsCarryover = _transcriptHasCarryoverContext(transcript, { currentMessage: message });
3064
3081
 
3065
- function buildPrompt({ includePreamble = true, includeCarryover = false, outOfBandOnly = false } = {}) {
3082
+ function buildPrompt({ includePreamble = true, includeCarryover = false, includeResumeGuard = false, outOfBandOnly = false } = {}) {
3066
3083
  const parts = (!skipStatePreamble && includePreamble) ? [`## Current Minions State (${new Date().toISOString().slice(0, 16)})\n\n${buildCCStatePreamble()}`] : [];
3067
3084
  if (extraContext) parts.push(extraContext);
3085
+ if (includeResumeGuard) parts.push(CC_RESUME_BOOKKEEPING_GUARD);
3068
3086
  if (includeCarryover) {
3069
3087
  const carryover = _buildTranscriptCarryover(transcript, { currentMessage: message, outOfBandOnly });
3070
3088
  if (carryover) parts.push(carryover);
@@ -3079,6 +3097,7 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
3079
3097
  if (sessionId && maxTurns > 1) {
3080
3098
  const p1 = llm.callLLM(buildPrompt({
3081
3099
  includePreamble: false,
3100
+ includeResumeGuard: resumeNeedsBookkeepingGuard,
3082
3101
  includeCarryover: resumeNeedsCarryover || resumeHasOutOfBandCarryover,
3083
3102
  outOfBandOnly: !resumeNeedsCarryover,
3084
3103
  }), '', {
@@ -3165,13 +3184,16 @@ async function ccCallStreaming(message, { store = 'cc', sessionKey, extraContext
3165
3184
 
3166
3185
  const existing = resolveSession(store, sessionKey);
3167
3186
  let sessionId = existing ? existing.sessionId : null;
3168
- const resumeNeedsCarryover = !!sessionId && _ccRuntimeNeedsResumeCarryover(shared.resolveCcCli(CONFIG.engine));
3187
+ const currentRuntime = shared.resolveCcCli(CONFIG.engine);
3188
+ const resumeNeedsCarryover = !!sessionId && _ccRuntimeNeedsResumeCarryover(currentRuntime);
3189
+ const resumeNeedsBookkeepingGuard = !!sessionId && _ccRuntimeNeedsResumeBookkeepingGuard(currentRuntime);
3169
3190
  const resumeHasOutOfBandCarryover = !!sessionId && _transcriptHasCarryoverContext(transcript, { outOfBandOnly: true, currentMessage: message });
3170
3191
  const freshNeedsCarryover = _transcriptHasCarryoverContext(transcript, { currentMessage: message });
3171
3192
 
3172
- function buildPrompt({ includePreamble = true, includeCarryover = false, outOfBandOnly = false } = {}) {
3193
+ function buildPrompt({ includePreamble = true, includeCarryover = false, includeResumeGuard = false, outOfBandOnly = false } = {}) {
3173
3194
  const parts = (!skipStatePreamble && includePreamble) ? [`## Current Minions State (${new Date().toISOString().slice(0, 16)})\n\n${buildCCStatePreamble()}`] : [];
3174
3195
  if (extraContext) parts.push(extraContext);
3196
+ if (includeResumeGuard) parts.push(CC_RESUME_BOOKKEEPING_GUARD);
3175
3197
  if (includeCarryover) {
3176
3198
  const carryover = _buildTranscriptCarryover(transcript, { currentMessage: message, outOfBandOnly });
3177
3199
  if (carryover) parts.push(carryover);
@@ -3185,6 +3207,7 @@ async function ccCallStreaming(message, { store = 'cc', sessionKey, extraContext
3185
3207
  if (sessionId && maxTurns > 1) {
3186
3208
  const p1 = llm.callLLMStreaming(buildPrompt({
3187
3209
  includePreamble: false,
3210
+ includeResumeGuard: resumeNeedsBookkeepingGuard,
3188
3211
  includeCarryover: resumeNeedsCarryover || resumeHasOutOfBandCarryover,
3189
3212
  outOfBandOnly: !resumeNeedsCarryover,
3190
3213
  }), '', {
@@ -6708,9 +6731,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6708
6731
  const wasResume = !!tabSessionId;
6709
6732
  const sessionId = tabSessionId || null;
6710
6733
  const resumeNeedsCarryover = wasResume && _ccRuntimeNeedsResumeCarryover(currentRuntime);
6734
+ const resumeNeedsBookkeepingGuard = wasResume && _ccRuntimeNeedsResumeBookkeepingGuard(currentRuntime);
6711
6735
  const resumeHasOutOfBandCarryover = wasResume && _transcriptHasCarryoverContext(body.transcript, { outOfBandOnly: true, currentMessage: body.message });
6712
6736
  const preamble = wasResume ? '' : buildCCStatePreamble();
6713
6737
  const includeFullCarryover = sessionReset || resumeNeedsCarryover;
6738
+ const resumeGuard = resumeNeedsBookkeepingGuard ? CC_RESUME_BOOKKEEPING_GUARD : '';
6714
6739
  const carryover = (includeFullCarryover || resumeHasOutOfBandCarryover)
6715
6740
  ? _buildTranscriptCarryover(body.transcript, {
6716
6741
  previousRuntime: sessionReset ? previousRuntime : null,
@@ -6718,7 +6743,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6718
6743
  outOfBandOnly: !includeFullCarryover,
6719
6744
  })
6720
6745
  : '';
6721
- const prompt = _joinCcPromptParts(preamble, carryover, body.message);
6746
+ const prompt = _joinCcPromptParts(preamble, resumeGuard, carryover, body.message);
6722
6747
 
6723
6748
  const { trackEngineUsage: trackUsage } = require('./engine/llm');
6724
6749
  const streamModel = CONFIG.engine?.ccModel || shared.ENGINE_DEFAULTS.ccModel;
@@ -8462,6 +8487,7 @@ module.exports = {
8462
8487
  _buildTranscriptCarryover,
8463
8488
  _transcriptHasCarryoverContext,
8464
8489
  _ccRuntimeNeedsResumeCarryover,
8490
+ _ccRuntimeNeedsResumeBookkeepingGuard,
8465
8491
  _joinCcPromptParts,
8466
8492
  _captureApiRoutesMeta,
8467
8493
  _formatCcApiRoutesIndex,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-08T01:35:12.713Z"
4
+ "cachedAt": "2026-05-08T07:37:12.713Z"
5
5
  }
package/engine/llm.js CHANGED
@@ -22,7 +22,7 @@ const { resolveRuntime } = require('./runtimes');
22
22
 
23
23
  const MINIONS_DIR = shared.MINIONS_DIR;
24
24
  const ENGINE_DIR = path.join(MINIONS_DIR, 'engine');
25
- const COPILOT_TASK_COMPLETE_GRACE_MS = 3000;
25
+ const COPILOT_TASK_COMPLETE_GRACE_MS = 15000;
26
26
  const MISSING_RUNTIME_EXIT_CODE = 78;
27
27
  // When the spawned process emits 'exit' but 'close' is delayed (a detached
28
28
  // grandchild inherited stdio), wait this long for trailing stdout data to
@@ -719,6 +719,9 @@ const capabilities = {
719
719
  sessionPersistenceControl: true,
720
720
  // Claude resume reliably restores prior turns; do not duplicate browser transcript.
721
721
  resumePromptCarryover: false,
722
+ // Claude CLI injects a synthetic "Continue from where you left off." meta
723
+ // turn on --resume; CC prompts must tell the model not to treat it as user intent.
724
+ resumeBookkeepingTurn: true,
722
725
  // Adapter implements createStreamConsumer(ctx) — required by llm.js accumulator
723
726
  streamConsumer: true,
724
727
  };
@@ -817,11 +817,15 @@ function createStreamConsumer(ctx) {
817
817
  // inspect...") is progress text only — terminal text comes from non-tool
818
818
  // assistant messages or trailing deltas.
819
819
  let copilotMessageBuffer = '';
820
+ let terminalText = '';
820
821
 
821
822
  function _captureTaskComplete(summary, success = true) {
822
823
  if (typeof summary !== 'string' || !summary) return;
823
824
  copilotMessageBuffer = '';
824
- ctx.pushText(summary);
825
+ if (!terminalText) {
826
+ terminalText = summary;
827
+ ctx.pushText(summary);
828
+ }
825
829
  ctx.notifyTaskComplete(summary, success !== false);
826
830
  }
827
831
 
@@ -830,6 +834,10 @@ function createStreamConsumer(ctx) {
830
834
 
831
835
  if (obj.type === 'result' && typeof obj.sessionId === 'string') {
832
836
  ctx.setSessionId(obj.sessionId);
837
+ // The result event is the first Copilot event that contains the resumable
838
+ // sessionId. Do not mark the earlier assistant.message as terminal or
839
+ // Minions can resolve before session persistence data is available.
840
+ if (terminalText) ctx.setText(terminalText);
833
841
  }
834
842
 
835
843
  if (obj.type === 'session.task_complete') {
@@ -859,7 +867,10 @@ function createStreamConsumer(ctx) {
859
867
  // Tool-request narration is progress text only — don't let it become
860
868
  // the terminal answer. A non-tool assistant.message overrides any
861
869
  // streamed deltas (Copilot's authoritative final text for the turn).
862
- if (content && !hasTools) ctx.setText(content);
870
+ if (content && !hasTools) {
871
+ terminalText = content;
872
+ ctx.pushText(content);
873
+ }
863
874
  copilotMessageBuffer = '';
864
875
  }
865
876
  if (Array.isArray(data.toolRequests)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1787",
3
+ "version": "0.1.1789",
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"