@yemi33/minions 0.1.258 → 0.1.260
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 +5 -1
- package/dashboard/js/command-center.js +2 -2
- package/dashboard.js +2 -0
- package/engine/llm.js +17 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.260 (2026-04-03)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- real-time token streaming for CC via partial JSON extraction
|
|
4
7
|
|
|
5
8
|
### Fixes
|
|
9
|
+
- CC stream clears ccInFlight on client disconnect + defensive thinking.remove
|
|
6
10
|
- remove last evaluate references — eval loop now creates review items
|
|
7
11
|
|
|
8
12
|
## 0.1.257 (2026-04-03)
|
|
@@ -192,7 +192,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
192
192
|
|
|
193
193
|
// Create streaming message bubble
|
|
194
194
|
clearInterval(ccTimer);
|
|
195
|
-
thinking.remove();
|
|
195
|
+
try { thinking.remove(); } catch { /* may already be removed */ }
|
|
196
196
|
const streamDiv = document.createElement('div');
|
|
197
197
|
streamDiv.className = 'cc-msg assistant';
|
|
198
198
|
streamDiv.innerHTML = '<span style="color:var(--muted);font-size:11px">Thinking...</span>';
|
|
@@ -236,7 +236,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
236
236
|
}
|
|
237
237
|
} catch (e) {
|
|
238
238
|
clearInterval(ccTimer);
|
|
239
|
-
thinking.remove();
|
|
239
|
+
try { thinking.remove(); } catch { /* may already be removed */ }
|
|
240
240
|
const retryId = 'cc-retry-' + Date.now();
|
|
241
241
|
ccAddMessage('assistant', '<span style="color:var(--red)">Error: ' + escHtml(e.message) + '</span>' +
|
|
242
242
|
'<button id="' + retryId + '" onclick="ccRetryLast()" style="margin-top:6px;padding:4px 12px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--blue);cursor:pointer;font-size:11px">Retry</button>');
|
package/dashboard.js
CHANGED
|
@@ -2993,6 +2993,8 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
2993
2993
|
ccInFlightSince = Date.now();
|
|
2994
2994
|
|
|
2995
2995
|
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' });
|
|
2996
|
+
// Clear ccInFlight if client disconnects mid-stream
|
|
2997
|
+
req.on('close', () => { ccInFlight = false; ccInFlightSince = 0; });
|
|
2996
2998
|
|
|
2997
2999
|
try {
|
|
2998
3000
|
// Session management — same as non-streaming path
|
package/engine/llm.js
CHANGED
|
@@ -139,6 +139,7 @@ function callLLMStreaming(promptText, sysPromptText, { timeout = 120000, label =
|
|
|
139
139
|
let stderr = '';
|
|
140
140
|
let lineBuf = '';
|
|
141
141
|
|
|
142
|
+
let lastTextSent = '';
|
|
142
143
|
proc.stdout.on('data', d => {
|
|
143
144
|
const chunk = d.toString();
|
|
144
145
|
stdout += chunk;
|
|
@@ -153,11 +154,26 @@ function callLLMStreaming(promptText, sysPromptText, { timeout = 120000, label =
|
|
|
153
154
|
const obj = JSON.parse(trimmed);
|
|
154
155
|
if (obj.type === 'assistant' && obj.message?.content) {
|
|
155
156
|
for (const block of obj.message.content) {
|
|
156
|
-
if (block.type === 'text' && block.text
|
|
157
|
+
if (block.type === 'text' && block.text && block.text !== lastTextSent) {
|
|
158
|
+
lastTextSent = block.text;
|
|
159
|
+
onChunk(block.text);
|
|
160
|
+
}
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
163
|
} catch { /* incomplete JSON or non-JSON line */ }
|
|
160
164
|
}
|
|
165
|
+
// Also try to extract partial text from incomplete line buffer (real-time streaming)
|
|
166
|
+
// Claude CLI writes large JSON objects incrementally — extract "text":"..." as it grows
|
|
167
|
+
try {
|
|
168
|
+
const textMatch = lineBuf.match(/"text"\s*:\s*"((?:[^"\\]|\\.)*)$/);
|
|
169
|
+
if (textMatch && textMatch[1].length > 20 && textMatch[1] !== lastTextSent) {
|
|
170
|
+
// Unescape basic JSON escapes for display
|
|
171
|
+
const partial = textMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
|
172
|
+
if (partial.length > lastTextSent.length) {
|
|
173
|
+
onChunk(partial);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch { /* best-effort partial extraction */ }
|
|
161
177
|
});
|
|
162
178
|
proc.stderr.on('data', d => { stderr += d.toString(); });
|
|
163
179
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.260",
|
|
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"
|