@yemi33/minions 0.1.1773 → 0.1.1774
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 +9 -4
- package/dashboard.js +75 -41
- package/engine/copilot-models.json +1 -1
- package/engine/runtimes/copilot.js +59 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1774 (2026-05-07)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- suppress stale doc-chat model errors
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- yemi33/minions#2168
|
|
10
|
+
|
|
11
|
+
## 0.1.1772 (2026-05-07)
|
|
4
12
|
|
|
5
13
|
### Features
|
|
6
|
-
- fix doc chat sticky scroll (#2176)
|
|
7
|
-
- fix live output route and CLI docs (#2172)
|
|
8
|
-
- make API project resolution strict (#2169)
|
|
9
14
|
- fix copilot cc resume context (#2166)
|
|
10
15
|
|
|
11
16
|
## 0.1.1771 (2026-05-07)
|
package/dashboard.js
CHANGED
|
@@ -2721,23 +2721,19 @@ function _formatDocChatContext({ document, title, filePath, selection, canEdit,
|
|
|
2721
2721
|
return context;
|
|
2722
2722
|
}
|
|
2723
2723
|
|
|
2724
|
-
// Map
|
|
2724
|
+
// Map runtime failures to user-facing messages.
|
|
2725
2725
|
// sessionPreserved=true means ccCall preserved the session — user can retry immediately.
|
|
2726
2726
|
// toolUses=[] from result.toolUses lets the message warn that tools may have already
|
|
2727
2727
|
// modified files/state before the failure — the user shouldn't assume nothing happened.
|
|
2728
|
-
// errorMessage is the runtime adapter's own
|
|
2729
|
-
// authoritative
|
|
2730
|
-
// dashboard falls back to generic copy only when the adapter didn't supply one.
|
|
2728
|
+
// errorMessage is the runtime adapter's own text from parseError; when present it
|
|
2729
|
+
// is authoritative and is shown directly rather than replaced with dashboard copy.
|
|
2731
2730
|
function _docChatErrorMessage(errorClass, sessionPreserved = false, toolUses = [], errorMessage = null) {
|
|
2732
2731
|
const tools = Array.isArray(toolUses) ? toolUses : [];
|
|
2733
2732
|
const toolHint = tools.length > 0
|
|
2734
2733
|
? ` (${tools.length} tool${tools.length === 1 ? '' : 's'} ran before the failure: ${tools.slice(0, 5).map(t => t.name).join(', ')}${tools.length > 5 ? '…' : ''} — files or state may have been modified.)`
|
|
2735
2734
|
: '';
|
|
2736
|
-
|
|
2737
|
-
if (
|
|
2738
|
-
if (errorClass === 'budget-exceeded') return (errorMessage || 'Runtime budget exceeded — check your account or quota.') + toolHint;
|
|
2739
|
-
if (errorClass === 'crash') return (errorMessage || 'Runtime crashed unexpectedly. Try again.') + toolHint;
|
|
2740
|
-
if (errorClass === 'unknown-model') return (errorMessage || 'Configured model is not valid for the active runtime. Update engine.ccModel or engine.defaultModel.') + toolHint;
|
|
2735
|
+
const directError = typeof errorMessage === 'string' ? errorMessage.trim() : '';
|
|
2736
|
+
if (directError) return directError + toolHint;
|
|
2741
2737
|
if (sessionPreserved) return 'Temporary connection issue — your conversation is intact, send your message again.' + toolHint;
|
|
2742
2738
|
if (tools.length > 0) return 'The agent stopped responding before producing a final answer.' + toolHint;
|
|
2743
2739
|
return 'Failed to process request. Try again.';
|
|
@@ -2746,14 +2742,26 @@ function _docChatErrorMessage(errorClass, sessionPreserved = false, toolUses = [
|
|
|
2746
2742
|
// Secondary note rendered alongside a recovered partial answer — distinct from the
|
|
2747
2743
|
// hard-failure message because the answer/actions/document-edit DID land. The user
|
|
2748
2744
|
// just needs to know the run wasn't clean.
|
|
2749
|
-
function _docChatPartialWarning(errorClass) {
|
|
2750
|
-
|
|
2751
|
-
if (
|
|
2752
|
-
if (errorClass === 'budget-exceeded') return 'Note: runtime budget exceeded — answer recovered, but further calls may fail.';
|
|
2753
|
-
if (errorClass === 'crash') return 'Note: runtime crashed before clean exit, but a complete response was recovered.';
|
|
2745
|
+
function _docChatPartialWarning(errorClass, errorMessage = null) {
|
|
2746
|
+
const directError = typeof errorMessage === 'string' ? errorMessage.trim() : '';
|
|
2747
|
+
if (directError) return `Note: ${directError}`;
|
|
2754
2748
|
return 'Note: the agent exited unexpectedly. A complete response was recovered — verify any saved files or dispatched actions.';
|
|
2755
2749
|
}
|
|
2756
2750
|
|
|
2751
|
+
function _docChatResultHasVisibleError(result) {
|
|
2752
|
+
if (!result) return false;
|
|
2753
|
+
if (result.errorClass) return true;
|
|
2754
|
+
if (typeof result.errorMessage === 'string' && result.errorMessage.trim()) return true;
|
|
2755
|
+
// stderr without a classified/runtime error is often CLI diagnostics; hard
|
|
2756
|
+
// failures with no answer still surface stderr through _docChatFailureResponse.
|
|
2757
|
+
return false;
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
function _docChatResultLooksSuccessful(result) {
|
|
2761
|
+
if (!result || !result.text) return false;
|
|
2762
|
+
return result.code === 0 || !_docChatResultHasVisibleError(result);
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2757
2765
|
// Build the doc-chat extraContext for a single ccCall pass — refreshed on retry
|
|
2758
2766
|
// so a fresh-session retry includes the full document instead of relying on the
|
|
2759
2767
|
// dead session's prior turn for context.
|
|
@@ -2830,7 +2838,7 @@ function _recoverPartialDocChatResponse(result, sessionKey) {
|
|
|
2830
2838
|
return {
|
|
2831
2839
|
...parsed,
|
|
2832
2840
|
partial: true,
|
|
2833
|
-
warning: _docChatPartialWarning(result.errorClass),
|
|
2841
|
+
warning: _docChatPartialWarning(result.errorClass, result.errorMessage || result.stderr || null),
|
|
2834
2842
|
toolUses: Array.isArray(result.toolUses) ? result.toolUses : [],
|
|
2835
2843
|
// Recovery path still attaches the raw runtime failure — the answer landed
|
|
2836
2844
|
// despite a non-zero exit; users still benefit from seeing why.
|
|
@@ -2838,6 +2846,41 @@ function _recoverPartialDocChatResponse(result, sessionKey) {
|
|
|
2838
2846
|
};
|
|
2839
2847
|
}
|
|
2840
2848
|
|
|
2849
|
+
function _shouldSuppressDocChatPostPatchError(ccError, finalize) {
|
|
2850
|
+
if (!finalize || finalize.edited !== true) return false;
|
|
2851
|
+
if (!ccError || ccError.errorClass !== 'unknown-model') return false;
|
|
2852
|
+
return String(ccError.runtime || '').toLowerCase() === 'copilot';
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
function _buildDocChatResponsePayload({
|
|
2856
|
+
answer,
|
|
2857
|
+
actions,
|
|
2858
|
+
actionResults,
|
|
2859
|
+
actionParseError,
|
|
2860
|
+
ccError,
|
|
2861
|
+
partial,
|
|
2862
|
+
warning,
|
|
2863
|
+
toolUses,
|
|
2864
|
+
finalize,
|
|
2865
|
+
} = {}) {
|
|
2866
|
+
const final = finalize || { edited: false, content: null, answerSuffix: '' };
|
|
2867
|
+
const suppressPostPatchError = _shouldSuppressDocChatPostPatchError(ccError, final);
|
|
2868
|
+
const visibleAnswer = suppressPostPatchError && !partial ? 'Updated the document.' : answer;
|
|
2869
|
+
const finalAnswer = final.answerSuffix ? visibleAnswer + final.answerSuffix : visibleAnswer;
|
|
2870
|
+
return {
|
|
2871
|
+
ok: !(ccError && !suppressPostPatchError),
|
|
2872
|
+
answer: finalAnswer,
|
|
2873
|
+
actions,
|
|
2874
|
+
...(actionResults ? { actionResults } : {}),
|
|
2875
|
+
...(actionParseError ? { actionParseError } : {}),
|
|
2876
|
+
...(ccError && !suppressPostPatchError ? { error: ccError } : {}),
|
|
2877
|
+
...(partial && !suppressPostPatchError ? { partial: true, warning } : {}),
|
|
2878
|
+
...(Array.isArray(toolUses) && toolUses.length ? { toolUses } : {}),
|
|
2879
|
+
edited: final.edited,
|
|
2880
|
+
...(final.edited && final.content !== null ? { content: final.content } : {}),
|
|
2881
|
+
};
|
|
2882
|
+
}
|
|
2883
|
+
|
|
2841
2884
|
|
|
2842
2885
|
// True when the file is a meeting JSON whose status forbids edits. Loaded
|
|
2843
2886
|
// fresh on each call because meeting status can change while a doc-chat is
|
|
@@ -2990,7 +3033,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
2990
3033
|
// bleed into future interactions under the same key.
|
|
2991
3034
|
docSessions.delete(sessionKey);
|
|
2992
3035
|
schedulePersistDocSessions();
|
|
2993
|
-
} else if (result
|
|
3036
|
+
} else if (_docChatResultLooksSuccessful(result) && result.sessionId) {
|
|
2994
3037
|
// Store doc hash for next call's unchanged check
|
|
2995
3038
|
const session = resolveSession('doc', sessionKey);
|
|
2996
3039
|
if (session) session._docHash = initialPass.docHash;
|
|
@@ -3000,7 +3043,7 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
|
|
|
3000
3043
|
return { answer: result.text || result.stderr || 'Minions runtime is not installed or configured.', content: null, actions: [] };
|
|
3001
3044
|
}
|
|
3002
3045
|
|
|
3003
|
-
if (
|
|
3046
|
+
if (!_docChatResultLooksSuccessful(result)) {
|
|
3004
3047
|
// Try to salvage a parseable answer / action / document edit before failing.
|
|
3005
3048
|
const recovered = _recoverPartialDocChatResponse(result, sessionKey);
|
|
3006
3049
|
if (recovered) return recovered;
|
|
@@ -3051,7 +3094,7 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
3051
3094
|
if (freshSession && sessionKey) {
|
|
3052
3095
|
docSessions.delete(sessionKey);
|
|
3053
3096
|
schedulePersistDocSessions();
|
|
3054
|
-
} else if (result
|
|
3097
|
+
} else if (_docChatResultLooksSuccessful(result) && result.sessionId) {
|
|
3055
3098
|
const session = resolveSession('doc', sessionKey);
|
|
3056
3099
|
if (session) session._docHash = initialPass.docHash;
|
|
3057
3100
|
}
|
|
@@ -3060,7 +3103,7 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
|
|
|
3060
3103
|
return { answer: result.text || result.stderr || 'Minions runtime is not installed or configured.', content: null, actions: [] };
|
|
3061
3104
|
}
|
|
3062
3105
|
|
|
3063
|
-
if (
|
|
3106
|
+
if (!_docChatResultLooksSuccessful(result)) {
|
|
3064
3107
|
const recovered = _recoverPartialDocChatResponse(result, sessionKey);
|
|
3065
3108
|
if (recovered) return recovered;
|
|
3066
3109
|
const sessionPreserved = !!(resolveSession('doc', sessionKey)?.sessionId);
|
|
@@ -5201,20 +5244,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
5201
5244
|
filePath: body.filePath, fullPath, isJson, canEdit,
|
|
5202
5245
|
originalContent: currentContent, delimiterContent: content,
|
|
5203
5246
|
});
|
|
5204
|
-
const
|
|
5205
|
-
|
|
5206
|
-
return jsonReply(res, 200, {
|
|
5207
|
-
ok: !ccError,
|
|
5208
|
-
answer: finalAnswer,
|
|
5209
|
-
actions,
|
|
5210
|
-
...(actionResults ? { actionResults } : {}),
|
|
5211
|
-
...(actionParseError ? { actionParseError } : {}),
|
|
5212
|
-
...(ccError ? { error: ccError } : {}),
|
|
5213
|
-
...(partial ? { partial: true, warning } : {}),
|
|
5214
|
-
...(Array.isArray(toolUses) && toolUses.length ? { toolUses } : {}),
|
|
5215
|
-
edited: finalize.edited,
|
|
5216
|
-
...(finalize.edited && finalize.content !== null ? { content: finalize.content } : {}),
|
|
5247
|
+
const payload = _buildDocChatResponsePayload({
|
|
5248
|
+
answer, actions, actionResults, actionParseError, ccError, partial, warning, toolUses, finalize,
|
|
5217
5249
|
});
|
|
5250
|
+
_docDone = true;
|
|
5251
|
+
return jsonReply(res, 200, payload);
|
|
5218
5252
|
} finally { _docAbort = null; _docDone = true; docChatInFlight.delete(docKey); }
|
|
5219
5253
|
} catch (e) { return jsonReply(res, e.statusCode || 500, { error: e.message }); }
|
|
5220
5254
|
}
|
|
@@ -5303,18 +5337,14 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
5303
5337
|
filePath: body.filePath, fullPath, isJson, canEdit,
|
|
5304
5338
|
originalContent: currentContent, delimiterContent: content,
|
|
5305
5339
|
});
|
|
5306
|
-
const
|
|
5340
|
+
const payload = _buildDocChatResponsePayload({
|
|
5341
|
+
answer, actions, actionResults, actionParseError, ccError, partial, warning, toolUses, finalize,
|
|
5342
|
+
});
|
|
5343
|
+
const { answer: finalAnswer, ...donePayload } = payload;
|
|
5307
5344
|
writeDocEvent({
|
|
5308
5345
|
type: 'done',
|
|
5309
5346
|
text: finalAnswer,
|
|
5310
|
-
|
|
5311
|
-
...(actionResults ? { actionResults } : {}),
|
|
5312
|
-
...(actionParseError ? { actionParseError } : {}),
|
|
5313
|
-
...(ccError ? { error: ccError } : {}),
|
|
5314
|
-
...(partial ? { partial: true, warning } : {}),
|
|
5315
|
-
...(Array.isArray(toolUses) && toolUses.length ? { toolUses } : {}),
|
|
5316
|
-
edited: finalize.edited,
|
|
5317
|
-
...(finalize.edited && finalize.content !== null ? { content: finalize.content } : {}),
|
|
5347
|
+
...donePayload,
|
|
5318
5348
|
});
|
|
5319
5349
|
_docStreamEnded = true;
|
|
5320
5350
|
res.end();
|
|
@@ -7753,6 +7783,10 @@ module.exports = {
|
|
|
7753
7783
|
_docChatPartialWarning,
|
|
7754
7784
|
_docChatFailureResponse,
|
|
7755
7785
|
_recoverPartialDocChatResponse,
|
|
7786
|
+
_docChatResultHasVisibleError,
|
|
7787
|
+
_docChatResultLooksSuccessful,
|
|
7788
|
+
_shouldSuppressDocChatPostPatchError,
|
|
7789
|
+
_buildDocChatResponsePayload,
|
|
7756
7790
|
_linkPullRequestForTracking: linkPullRequestForTracking,
|
|
7757
7791
|
_resolveSkillReadPath,
|
|
7758
7792
|
DOC_CHAT_DOCUMENT_DELIMITER,
|
|
@@ -634,25 +634,77 @@ function parseStreamChunk(line) {
|
|
|
634
634
|
|
|
635
635
|
// ── Error Normalization ─────────────────────────────────────────────────────
|
|
636
636
|
|
|
637
|
-
function
|
|
637
|
+
function _collectErrorSignal(rawOutput) {
|
|
638
638
|
const text = rawOutput == null ? '' : String(rawOutput);
|
|
639
|
+
if (!text) return '';
|
|
640
|
+
|
|
641
|
+
const signals = [];
|
|
642
|
+
let sawJsonLine = false;
|
|
643
|
+
for (const rawLine of text.split('\n')) {
|
|
644
|
+
const line = rawLine.trim();
|
|
645
|
+
if (!line) continue;
|
|
646
|
+
if (!line.startsWith('{')) {
|
|
647
|
+
signals.push(line);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
let obj;
|
|
652
|
+
try { obj = JSON.parse(line); } catch { continue; }
|
|
653
|
+
if (!obj || typeof obj !== 'object') continue;
|
|
654
|
+
sawJsonLine = true;
|
|
655
|
+
|
|
656
|
+
const type = String(obj.type || '');
|
|
657
|
+
const subtype = String(obj.subtype || '');
|
|
658
|
+
const eventType = String(obj.event?.type || '');
|
|
659
|
+
const isErrorEvent = type === 'error'
|
|
660
|
+
|| eventType === 'error'
|
|
661
|
+
|| subtype.startsWith('error')
|
|
662
|
+
|| obj.is_error === true
|
|
663
|
+
|| obj.error != null
|
|
664
|
+
|| obj.data?.error != null;
|
|
665
|
+
if (!isErrorEvent) continue;
|
|
666
|
+
|
|
667
|
+
for (const value of [
|
|
668
|
+
obj.error,
|
|
669
|
+
obj.message,
|
|
670
|
+
obj.stderr,
|
|
671
|
+
obj.result,
|
|
672
|
+
obj.data?.error,
|
|
673
|
+
obj.data?.message,
|
|
674
|
+
obj.data?.stderr,
|
|
675
|
+
obj.event?.error,
|
|
676
|
+
obj.event?.message,
|
|
677
|
+
subtype,
|
|
678
|
+
]) {
|
|
679
|
+
if (typeof value === 'string' && value.trim()) signals.push(value.trim());
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (signals.length > 0) return signals.join('\n');
|
|
684
|
+
return sawJsonLine ? '' : text;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function parseError(rawOutput) {
|
|
688
|
+
const text = _collectErrorSignal(rawOutput);
|
|
639
689
|
if (!text) return { message: '', code: null, retriable: true };
|
|
640
690
|
const lower = text.toLowerCase();
|
|
641
691
|
|
|
642
|
-
|
|
643
|
-
|
|
692
|
+
const hasExplicitAuthFailure = /not authenticated|copilot login|please.*log.*in|\bunauthorized\b/i.test(text);
|
|
693
|
+
const hasAuthStatusCode = /\b(?:http(?:\/\d(?:\.\d)?)?|status(?:\s+code)?|statuscode|response(?:\s+status)?|api(?:\s+(?:error|response|status))?)\s*[:=]?\s*(?:401|403)\b|\b(?:401\s+unauthorized|403\s+forbidden)\b/i.test(text);
|
|
694
|
+
if (hasExplicitAuthFailure || hasAuthStatusCode) {
|
|
695
|
+
return { message: text, code: 'auth-failure', retriable: false };
|
|
644
696
|
}
|
|
645
697
|
if (/rate limit|too many requests|\b429\b/i.test(text)) {
|
|
646
|
-
return { message:
|
|
698
|
+
return { message: text, code: 'rate-limit', retriable: true };
|
|
647
699
|
}
|
|
648
700
|
if (/unknown model|model not found|model.*invalid|invalid model/i.test(text)) {
|
|
649
|
-
return { message:
|
|
701
|
+
return { message: text, code: 'unknown-model', retriable: false };
|
|
650
702
|
}
|
|
651
703
|
if (/budget.*exceed|premium.*limit.*reach|quota.*exceed/i.test(lower)) {
|
|
652
|
-
return { message:
|
|
704
|
+
return { message: text, code: 'budget-exceeded', retriable: false };
|
|
653
705
|
}
|
|
654
706
|
if (/internal error|panic|uncaught|copilot.*crashed|fatal: copilot/i.test(lower)) {
|
|
655
|
-
return { message:
|
|
707
|
+
return { message: text, code: 'crash', retriable: true };
|
|
656
708
|
}
|
|
657
709
|
return { message: '', code: null, retriable: true };
|
|
658
710
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1774",
|
|
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"
|