@yemi33/minions 0.1.924 → 0.1.926

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,8 +1,9 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.924 (2026-04-13)
3
+ ## 0.1.926 (2026-04-13)
4
4
 
5
5
  ### Features
6
+ - doc-chat abort kills LLM process + queued messages auto-process
6
7
  - add /api/work-items/reopen endpoint and reopen-work-item CC action (#982)
7
8
  - CC tab unread dot + reopened badge on work items
8
9
  - fix dep re-merge failure on retry with existing commits (#977)
@@ -19,6 +20,7 @@
19
20
  - add red dot notification on CC tab when response completes (#934) (#946)
20
21
 
21
22
  ### Fixes
23
+ - doc-chat Stop button actually works — release server guard on disconnect
22
24
  - CC streaming auto-retries fresh session when resume fails
23
25
  - 429 retry on abort race applies to all sends, not just queued
24
26
  - show actionable failure context instead of Unknown error (#1003)
@@ -340,6 +340,9 @@ function qaAbort() {
340
340
  _qaAbortController.abort();
341
341
  _qaAbortController = null;
342
342
  }
343
+ // Force-reset processing state so UI isn't stuck if abort races with response
344
+ _qaProcessing = false;
345
+ // Don't clear _qaQueue — queued messages should auto-process after abort
343
346
  }
344
347
 
345
348
  function toggleDocChat() {
package/dashboard.js CHANGED
@@ -741,7 +741,7 @@ function updateSession(store, key, sessionId, existing) {
741
741
  * @param {number} opts.maxTurns - Max tool-use turns
742
742
  * @param {string} opts.allowedTools - Comma-separated tool list
743
743
  */
744
- async function ccCall(message, { store = 'cc', sessionKey, extraContext, label = 'command-center', timeout = 900000, maxTurns, allowedTools = 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch', skipStatePreamble = false, model } = {}) {
744
+ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label = 'command-center', timeout = 900000, maxTurns, allowedTools = 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch', skipStatePreamble = false, model, onAbortReady } = {}) {
745
745
  if (!maxTurns) maxTurns = CONFIG.engine?.ccMaxTurns || shared.ENGINE_DEFAULTS.ccMaxTurns;
746
746
  if (!model) model = CONFIG.engine?.ccModel || shared.ENGINE_DEFAULTS.ccModel;
747
747
  const ccEffort = CONFIG.engine?.ccEffort || shared.ENGINE_DEFAULTS.ccEffort;
@@ -759,9 +759,11 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
759
759
 
760
760
  // Attempt 1: resume existing session — skip preamble (session already has context)
761
761
  if (sessionId && maxTurns > 1) {
762
- result = await llm.callLLM(buildPrompt({ includePreamble: false }), '', {
762
+ const p1 = llm.callLLM(buildPrompt({ includePreamble: false }), '', {
763
763
  timeout, label, model, maxTurns, allowedTools, sessionId, effort: ccEffort, direct: true,
764
764
  });
765
+ if (onAbortReady) onAbortReady(p1.abort);
766
+ result = await p1;
765
767
  llm.trackEngineUsage(label, result.usage);
766
768
 
767
769
  if (result.text) {
@@ -792,9 +794,11 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
792
794
 
793
795
  // Attempt 2: fresh session (include preamble for full context)
794
796
  const freshPrompt = buildPrompt();
795
- result = await llm.callLLM(freshPrompt, CC_STATIC_SYSTEM_PROMPT, {
797
+ const p2 = llm.callLLM(freshPrompt, CC_STATIC_SYSTEM_PROMPT, {
796
798
  timeout, label, model, maxTurns, allowedTools, effort: ccEffort, direct: true,
797
799
  });
800
+ if (onAbortReady) onAbortReady(p2.abort);
801
+ result = await p2;
798
802
  llm.trackEngineUsage(label, result.usage);
799
803
 
800
804
  if (result.text) {
@@ -806,9 +810,11 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
806
810
  if (maxTurns <= 1) return result;
807
811
  console.log(`[${label}] Fresh call also failed (code=${result.code}, empty=${!result.text}), retrying once more...`);
808
812
  await new Promise(r => setTimeout(r, 2000));
809
- result = await llm.callLLM(freshPrompt, CC_STATIC_SYSTEM_PROMPT, {
813
+ const p3 = llm.callLLM(freshPrompt, CC_STATIC_SYSTEM_PROMPT, {
810
814
  timeout, label, model, maxTurns, allowedTools, effort: ccEffort, direct: true,
811
815
  });
816
+ if (onAbortReady) onAbortReady(p3.abort);
817
+ result = await p3;
812
818
  llm.trackEngineUsage(label, result.usage);
813
819
 
814
820
  if (result.text) {
@@ -818,7 +824,7 @@ async function ccCall(message, { store = 'cc', sessionKey, extraContext, label =
818
824
  }
819
825
 
820
826
  // Doc-specific wrapper — adds document context, parses ---DOCUMENT---
821
- async function ccDocCall({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession }) {
827
+ async function ccDocCall({ message, document, title, filePath, selection, canEdit, isJson, model, freshSession, onAbortReady }) {
822
828
  const sessionKey = filePath || title;
823
829
  const docSlice = document.slice(0, 20000);
824
830
 
@@ -850,6 +856,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
850
856
  maxTurns: canEdit ? 25 : 10,
851
857
  skipStatePreamble: true,
852
858
  ...(model ? { model } : {}),
859
+ onAbortReady,
853
860
  });
854
861
 
855
862
  if (freshSession && sessionKey) {
@@ -2935,6 +2942,9 @@ What would you like to discuss or change? When you're happy, say "approve" and I
2935
2942
  return jsonReply(res, 429, { error: 'This document is already being processed — wait for the current response.' });
2936
2943
  }
2937
2944
  docChatInFlight.add(docKey);
2945
+ // Kill LLM process + release guard if client disconnects (abort/navigation)
2946
+ let _docAbort = null;
2947
+ req.on('close', () => { docChatInFlight.delete(docKey); if (_docAbort) _docAbort(); });
2938
2948
 
2939
2949
  try {
2940
2950
  const canEdit = !!body.filePath;
@@ -2953,6 +2963,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
2953
2963
  filePath: body.filePath, selection: body.selection, canEdit, isJson,
2954
2964
  model: body.model || undefined,
2955
2965
  freshSession: !!body.freshSession,
2966
+ onAbortReady: (abort) => { _docAbort = abort; },
2956
2967
  });
2957
2968
 
2958
2969
  if (!content) return jsonReply(res, 200, { ok: true, answer, edited: false, actions });
package/engine/llm.js CHANGED
@@ -130,10 +130,13 @@ function _spawnProcess(promptText, sysPromptText, { direct, label, model, maxTur
130
130
  // ── Core LLM Call ───────────────────────────────────────────────────────────
131
131
 
132
132
  function callLLM(promptText, sysPromptText, { timeout = 120000, label = 'llm', model = 'sonnet', maxTurns = 1, allowedTools = '', sessionId = null, effort = null, direct = false } = {}) {
133
- return new Promise((resolve) => {
133
+ let _abort = null;
134
+ const promise = new Promise((resolve) => {
134
135
  const _startMs = Date.now();
135
136
  const { proc, cleanupFiles } = _spawnProcess(promptText, sysPromptText, { direct, label, model, maxTurns, allowedTools, effort, sessionId });
136
137
 
138
+ _abort = () => { shared.killImmediate(proc); };
139
+
137
140
  let stdout = '';
138
141
  let stderr = '';
139
142
  proc.stdout.on('data', d => { stdout += d.toString(); });
@@ -156,6 +159,8 @@ function callLLM(promptText, sysPromptText, { timeout = 120000, label = 'llm', m
156
159
  resolve({ text: '', usage: null, sessionId: null, code: 1, stderr: err.message, raw: '' });
157
160
  });
158
161
  });
162
+ promise.abort = () => { if (_abort) _abort(); };
163
+ return promise;
159
164
  }
160
165
 
161
166
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.924",
3
+ "version": "0.1.926",
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"