tuna-agent 0.1.82 → 0.1.84
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.
|
@@ -185,7 +185,22 @@ export class ClaudeCodeAdapter {
|
|
|
185
185
|
let firstChunkIso = '';
|
|
186
186
|
let turnAccumulatedText = '';
|
|
187
187
|
let messageCount = 0; // Track message_start events to detect new turns
|
|
188
|
-
let lastSentContent = ''; // Dedup: skip sending same message twice
|
|
188
|
+
let lastSentContent = ''; // Dedup: skip sending same/similar message twice
|
|
189
|
+
// Normalize text for similarity comparison (strip markdown, collapse whitespace)
|
|
190
|
+
const normalize = (s) => s.replace(/[#*_`~\-|>]/g, '').replace(/\s+/g, ' ').trim().toLowerCase();
|
|
191
|
+
const isSimilar = (a, b) => {
|
|
192
|
+
if (!a || !b)
|
|
193
|
+
return false;
|
|
194
|
+
const na = normalize(a), nb = normalize(b);
|
|
195
|
+
if (na === nb)
|
|
196
|
+
return true;
|
|
197
|
+
// Check if one contains the other (common with slight variations)
|
|
198
|
+
if (na.length > 20 && nb.length > 20) {
|
|
199
|
+
if (na.includes(nb) || nb.includes(na))
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
};
|
|
189
204
|
console.log(`[ClaudeCode] Agent Team round ${round + 1}: ${userMessage.substring(0, 80)}${currentInputFiles?.length ? ` (+${currentInputFiles.length} images)` : ''}`);
|
|
190
205
|
const defaultWorkspace = path.join(os.homedir(), 'tuna-workspace');
|
|
191
206
|
const cwd = task.repoPath || defaultWorkspace;
|
|
@@ -229,20 +244,23 @@ export class ClaudeCodeAdapter {
|
|
|
229
244
|
if (event?.type === 'message_start') {
|
|
230
245
|
messageCount++;
|
|
231
246
|
console.log(`[ClaudeCode] message_start #${messageCount}, accumulated=${turnAccumulatedText.length} chars`);
|
|
232
|
-
if (messageCount > 1
|
|
233
|
-
|
|
247
|
+
if (messageCount > 1) {
|
|
248
|
+
// Always clear streaming bubble on new turn (prevents cross-turn accumulation)
|
|
234
249
|
ws.sendPMStreamEnd(task.id, streamMsgId);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
250
|
+
if (turnAccumulatedText.trim()) {
|
|
251
|
+
console.log(`[ClaudeCode] ✂️ Splitting bubble — finalizing ${turnAccumulatedText.length} chars from previous turn`);
|
|
252
|
+
const simplified = simplifyMarkdown(turnAccumulatedText);
|
|
253
|
+
if (!isSimilar(simplified, lastSentContent)) {
|
|
254
|
+
ws.sendPMMessage(task.id, {
|
|
255
|
+
sender: 'pm',
|
|
256
|
+
content: simplified,
|
|
257
|
+
startedAt: firstChunkIso || undefined,
|
|
258
|
+
});
|
|
259
|
+
lastSentContent = simplified;
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
console.log(`[ClaudeCode] ⏭️ Skipping duplicate message (${simplified.length} chars)`);
|
|
263
|
+
}
|
|
246
264
|
}
|
|
247
265
|
turnAccumulatedText = '';
|
|
248
266
|
firstChunkIso = '';
|
|
@@ -338,7 +356,7 @@ export class ClaudeCodeAdapter {
|
|
|
338
356
|
// Send finalized message for the last turn's remaining text (skip if duplicate)
|
|
339
357
|
if (turnAccumulatedText.trim()) {
|
|
340
358
|
const simplified = simplifyMarkdown(turnAccumulatedText);
|
|
341
|
-
if (simplified
|
|
359
|
+
if (!isSimilar(simplified, lastSentContent)) {
|
|
342
360
|
ws.sendPMMessage(task.id, {
|
|
343
361
|
sender: 'pm',
|
|
344
362
|
content: simplified,
|
|
@@ -347,7 +365,7 @@ export class ClaudeCodeAdapter {
|
|
|
347
365
|
lastSentContent = simplified;
|
|
348
366
|
}
|
|
349
367
|
else {
|
|
350
|
-
console.log(`[ClaudeCode] ⏭️ Skipping
|
|
368
|
+
console.log(`[ClaudeCode] ⏭️ Skipping similar final message (${simplified.length} chars)`);
|
|
351
369
|
}
|
|
352
370
|
}
|
|
353
371
|
// Last round → close
|