@yemi33/minions 0.1.2129 → 0.1.2131
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.
|
@@ -136,7 +136,11 @@ function _ccMergeStreamText(prev, incoming) {
|
|
|
136
136
|
if (next === current) return current;
|
|
137
137
|
if (next.startsWith(current)) return next;
|
|
138
138
|
if (current.startsWith(next)) return current;
|
|
139
|
-
|
|
139
|
+
// Overlap >= 3 only — a 1- or 2-char tail/head match is statistically a
|
|
140
|
+
// false positive (e.g. trailing 's' or '.' against a leading capital
|
|
141
|
+
// letter) and welds back-to-back assistant messages into `...prev.next...`
|
|
142
|
+
// with no separator (W-mq1jwwqo000f20d9 — CC chunk welding fix).
|
|
143
|
+
for (var overlap = Math.min(current.length, next.length); overlap >= 3; overlap--) {
|
|
140
144
|
if (current.slice(-overlap) === next.slice(0, overlap)) {
|
|
141
145
|
return current + next.slice(overlap);
|
|
142
146
|
}
|
package/dashboard/js/refresh.js
CHANGED
|
@@ -101,6 +101,36 @@ function _targetTypeLabel(type) {
|
|
|
101
101
|
return _WATCH_TARGET_LABELS[type] || (type || '');
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// W-mq1j5f9z00030b8f — `teams-channel` target is `{teamId, channelId}` (object);
|
|
105
|
+
// other targetTypes use strings. Avoid `String(target)` → "[object Object]";
|
|
106
|
+
// route all target rendering here so future object-target plugins inherit safety.
|
|
107
|
+
function _formatWatchTarget(target, targetType) {
|
|
108
|
+
if (target == null || target === '') return '';
|
|
109
|
+
if (typeof target === 'string') return target;
|
|
110
|
+
if (typeof target !== 'object') return String(target);
|
|
111
|
+
if (targetType === 'teams-channel'
|
|
112
|
+
&& typeof target.teamId === 'string' && target.teamId
|
|
113
|
+
&& typeof target.channelId === 'string' && target.channelId) {
|
|
114
|
+
var team = target.teamId.slice(0, 8) + '…';
|
|
115
|
+
var chPart = target.channelId.split(':')[1] || target.channelId;
|
|
116
|
+
var ch = chPart.slice(0, 12) + '…';
|
|
117
|
+
return 'Team ' + team + ' > Channel ' + ch;
|
|
118
|
+
}
|
|
119
|
+
var json;
|
|
120
|
+
try { json = JSON.stringify(target); } catch (_) { return '[unserializable target]'; }
|
|
121
|
+
if (json == null) return '';
|
|
122
|
+
return json.length > 60 ? json.slice(0, 57) + '…' : json;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// W-mq1j5f9z00030b8f — title fallback chain: title → description → formatted target → "(no target)".
|
|
126
|
+
function _watchTitleFallback(w) {
|
|
127
|
+
if (!w) return '(no target)';
|
|
128
|
+
if (w.title) return w.title;
|
|
129
|
+
if (w.description) return w.description;
|
|
130
|
+
var formatted = _formatWatchTarget(w.target, w.targetType);
|
|
131
|
+
return formatted || '(no target)';
|
|
132
|
+
}
|
|
133
|
+
|
|
104
134
|
function _intervalToHuman(ms) {
|
|
105
135
|
if (!ms) return 'default';
|
|
106
136
|
const sec = Math.floor(ms / 1000);
|
|
@@ -170,7 +200,7 @@ function renderWatches(watchesData, opts) {
|
|
|
170
200
|
|
|
171
201
|
html += '<tr style="cursor:pointer" onclick="if(shouldIgnoreSelectionClick(event))return;openWatchDetail(\'' + escHtml(w.id) + '\')">' +
|
|
172
202
|
'<td><span class="pr-id">' + escHtml(w.id) + '</span></td>' +
|
|
173
|
-
'<td style="max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(w
|
|
203
|
+
'<td style="max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(_watchTitleFallback(w)) + '">' + escHtml(_formatWatchTarget(w.target, w.targetType) || _watchTitleFallback(w)) + '</td>' +
|
|
174
204
|
'<td><span class="dispatch-type explore">' + escHtml(targetLabel) + '</span></td>' +
|
|
175
205
|
'<td><span style="font-size:var(--text-base);color:var(--blue)">' + escHtml(condLabel) + '</span></td>' +
|
|
176
206
|
'<td><span style="font-size:var(--text-sm)">' + actionLabel + '</span></td>' +
|
|
@@ -250,7 +280,7 @@ function _renderWatchRequiresDetail(requires) {
|
|
|
250
280
|
var rows = requires.map(function(r, i) {
|
|
251
281
|
return '<div style="margin-top:4px;padding:6px 8px;background:var(--surface2);border-radius:4px;font-size:var(--text-base)">' +
|
|
252
282
|
'<span style="color:var(--muted)">[' + (i + 1) + ']</span> ' +
|
|
253
|
-
escHtml(r && r.target ? r.target : '?') +
|
|
283
|
+
escHtml(r && r.target ? (_formatWatchTarget(r.target, r.targetType) || '?') : '?') +
|
|
254
284
|
' <span class="dispatch-type explore">' + escHtml(r && r.targetType ? r.targetType : '?') + '</span>' +
|
|
255
285
|
' <span style="color:var(--blue)">' + escHtml(_conditionLabel(r && r.condition ? r.condition : '?')) + '</span>' +
|
|
256
286
|
'</div>';
|
|
@@ -300,7 +330,7 @@ function openWatchDetail(id) {
|
|
|
300
330
|
var condLabel = _conditionLabel(w.condition);
|
|
301
331
|
|
|
302
332
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: watch description/target/id)
|
|
303
|
-
document.getElementById('modal-title').innerHTML = escHtml(w
|
|
333
|
+
document.getElementById('modal-title').innerHTML = escHtml(_watchTitleFallback(w)) +
|
|
304
334
|
' <div style="display:flex;gap:4px;margin-top:4px">' +
|
|
305
335
|
(w.status === 'active' ? '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--yellow)" onclick="toggleWatchPause(\'' + escHtml(w.id) + '\',true);closeModal()">Pause</button>' : '') +
|
|
306
336
|
(w.status === 'paused' ? '<button class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 10px;color:var(--green)" onclick="toggleWatchPause(\'' + escHtml(w.id) + '\',false);closeModal()">Resume</button>' : '') +
|
|
@@ -309,7 +339,7 @@ function openWatchDetail(id) {
|
|
|
309
339
|
|
|
310
340
|
var body = '<div style="display:flex;flex-direction:column;gap:10px;font-size:var(--text-md);line-height:1.6">' +
|
|
311
341
|
'<div><strong style="color:var(--muted)">ID:</strong> ' + escHtml(w.id) + '</div>' +
|
|
312
|
-
'<div><strong style="color:var(--muted)">Target:</strong> ' + escHtml(w.target) + '</div>' +
|
|
342
|
+
'<div><strong style="color:var(--muted)">Target:</strong> ' + escHtml(_formatWatchTarget(w.target, w.targetType)) + '</div>' +
|
|
313
343
|
'<div><strong style="color:var(--muted)">Target Type:</strong> <span class="dispatch-type explore">' + escHtml(targetLabel) + '</span></div>' +
|
|
314
344
|
'<div><strong style="color:var(--muted)">Condition:</strong> <span style="color:var(--blue)">' + escHtml(condLabel) + '</span></div>' +
|
|
315
345
|
'<div><strong style="color:var(--muted)">Check Interval:</strong> ' + escHtml(_intervalToHuman(w.interval)) + '</div>' +
|
|
@@ -791,4 +821,7 @@ window.MinionsWatches = {
|
|
|
791
821
|
_updateRequireConditionOptions: _updateRequireConditionOptions,
|
|
792
822
|
// P-w15f1d4b — Phase 7.2: history table helper exposed for testability.
|
|
793
823
|
_renderWatchHistoryDetail: _renderWatchHistoryDetail,
|
|
824
|
+
// W-mq1j5f9z00030b8f — target / title fallback helpers exposed for unit coverage.
|
|
825
|
+
_formatWatchTarget: _formatWatchTarget,
|
|
826
|
+
_watchTitleFallback: _watchTitleFallback,
|
|
794
827
|
};
|
|
@@ -1080,6 +1080,12 @@ function createStreamConsumer(ctx) {
|
|
|
1080
1080
|
let copilotMessageBuffer = '';
|
|
1081
1081
|
let terminalText = '';
|
|
1082
1082
|
let taskCompleteSummary = '';
|
|
1083
|
+
// Tracks whether a non-tool `assistant.message` has already pushed terminal
|
|
1084
|
+
// text in this stream. Used to insert a `\n\n` paragraph break between
|
|
1085
|
+
// back-to-back terminating messages so consumers don't render the welded
|
|
1086
|
+
// form `...prev.next...`. First push is NEVER prefixed (would leave every
|
|
1087
|
+
// reply with a leading blank line). Reset by reset() on stream restart.
|
|
1088
|
+
let _hadPriorAssistantMessage = false;
|
|
1083
1089
|
|
|
1084
1090
|
function _captureTaskComplete(summary, success = true, { clearBuffer = false } = {}) {
|
|
1085
1091
|
if (typeof summary !== 'string' || !summary) return;
|
|
@@ -1131,8 +1137,17 @@ function createStreamConsumer(ctx) {
|
|
|
1131
1137
|
// the terminal answer. A non-tool assistant.message overrides any
|
|
1132
1138
|
// streamed deltas (Copilot's authoritative final text for the turn).
|
|
1133
1139
|
if (content && !hasTools) {
|
|
1134
|
-
|
|
1135
|
-
|
|
1140
|
+
// Second-and-later terminating message in a single turn: prefix the
|
|
1141
|
+
// pushed text with `\n\n` so the dashboard merge sees a clean
|
|
1142
|
+
// paragraph boundary instead of welding `<prev>.<next>` together
|
|
1143
|
+
// (W-mq1jwwqo000f20d9 — CC chunk welding fix). The first push must
|
|
1144
|
+
// NOT be prefixed or every reply starts with a blank line. Tool-use
|
|
1145
|
+
// boundaries are skipped — those get rendered as visible chips
|
|
1146
|
+
// client-side and already act as natural separators.
|
|
1147
|
+
const pushed = _hadPriorAssistantMessage ? '\n\n' + content : content;
|
|
1148
|
+
terminalText = _hadPriorAssistantMessage ? terminalText + '\n\n' + content : content;
|
|
1149
|
+
ctx.pushText(pushed);
|
|
1150
|
+
_hadPriorAssistantMessage = true;
|
|
1136
1151
|
}
|
|
1137
1152
|
copilotMessageBuffer = '';
|
|
1138
1153
|
}
|
|
@@ -1168,6 +1183,7 @@ function createStreamConsumer(ctx) {
|
|
|
1168
1183
|
copilotMessageBuffer = '';
|
|
1169
1184
|
terminalText = '';
|
|
1170
1185
|
taskCompleteSummary = '';
|
|
1186
|
+
_hadPriorAssistantMessage = false;
|
|
1171
1187
|
}
|
|
1172
1188
|
|
|
1173
1189
|
return { consume, reset };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2131",
|
|
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"
|