@swarmify/agents-mcp 0.2.0

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.
@@ -0,0 +1,766 @@
1
+ import { extractFileOpsFromBash } from './file_ops.js';
2
+ function extractErrorFromRawEvents(events, maxChars = 500) {
3
+ const errorKeywords = ['error', 'Error', 'ERROR', 'failed', 'Failed', 'FAILED', 'exception', 'Exception'];
4
+ for (let i = events.length - 1; i >= Math.max(0, events.length - 20); i--) {
5
+ const event = events[i];
6
+ if (event.type === 'raw') {
7
+ const content = event.content || '';
8
+ if (typeof content === 'string') {
9
+ const contentLower = content.toLowerCase();
10
+ if (errorKeywords.some(keyword => contentLower.includes(keyword.toLowerCase()))) {
11
+ let errorMsg = content.trim();
12
+ if (errorMsg.length > maxChars) {
13
+ errorMsg = errorMsg.substring(0, maxChars - 3) + '...';
14
+ }
15
+ return errorMsg;
16
+ }
17
+ }
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+ export const PRIORITY = {
23
+ critical: [
24
+ 'error',
25
+ 'result',
26
+ 'file_write',
27
+ 'file_delete',
28
+ 'file_create',
29
+ ],
30
+ important: [
31
+ 'tool_use',
32
+ 'bash',
33
+ 'file_read',
34
+ 'thinking',
35
+ 'message',
36
+ ],
37
+ verbose: [
38
+ 'thinking_delta',
39
+ 'message_delta',
40
+ 'init',
41
+ 'turn_start',
42
+ 'user_message',
43
+ 'raw',
44
+ ],
45
+ };
46
+ /**
47
+ * Collapse sequential events of the same type into summary entries.
48
+ * Returns a cleaner list of events suitable for output.
49
+ */
50
+ export function collapseEvents(events, maxEvents = 20) {
51
+ if (events.length === 0)
52
+ return [];
53
+ const collapsed = [];
54
+ let i = 0;
55
+ while (i < events.length) {
56
+ const event = events[i];
57
+ const eventType = event.type || 'unknown';
58
+ // For thinking events, collapse sequential ones
59
+ if (eventType === 'thinking') {
60
+ let count = 1;
61
+ let lastContent = event.content || '';
62
+ let j = i + 1;
63
+ while (j < events.length && events[j].type === 'thinking') {
64
+ count++;
65
+ if (events[j].content) {
66
+ lastContent = events[j].content;
67
+ }
68
+ j++;
69
+ }
70
+ if (count > 1) {
71
+ collapsed.push({
72
+ type: 'thinking_summary',
73
+ count: count,
74
+ last_content: lastContent.length > 200 ? lastContent.slice(-200) : lastContent,
75
+ timestamp: event.timestamp,
76
+ });
77
+ }
78
+ else if (event.content) {
79
+ collapsed.push(event);
80
+ }
81
+ i = j;
82
+ continue;
83
+ }
84
+ // For message events, keep the last content
85
+ if (eventType === 'message') {
86
+ collapsed.push({
87
+ type: 'message',
88
+ content: event.content?.length > 500 ? event.content.slice(-500) : event.content,
89
+ complete: event.complete,
90
+ timestamp: event.timestamp,
91
+ });
92
+ i++;
93
+ continue;
94
+ }
95
+ // Keep tool events as-is but truncate large content
96
+ if (['bash', 'file_write', 'file_read', 'file_create', 'file_delete', 'tool_use'].includes(eventType)) {
97
+ const cleaned = { ...event };
98
+ if (cleaned.command && cleaned.command.length > 200) {
99
+ cleaned.command = cleaned.command.slice(0, 200) + '...';
100
+ }
101
+ collapsed.push(cleaned);
102
+ i++;
103
+ continue;
104
+ }
105
+ // Keep errors and results
106
+ if (['error', 'result'].includes(eventType)) {
107
+ collapsed.push(event);
108
+ i++;
109
+ continue;
110
+ }
111
+ // Skip other event types
112
+ i++;
113
+ }
114
+ // Return only the last N events
115
+ if (collapsed.length > maxEvents) {
116
+ return collapsed.slice(-maxEvents);
117
+ }
118
+ return collapsed;
119
+ }
120
+ /**
121
+ * Get a breakdown of tool calls by type.
122
+ */
123
+ export function getToolBreakdown(events) {
124
+ const breakdown = {};
125
+ for (const event of events) {
126
+ const eventType = event.type || '';
127
+ if (eventType === 'bash') {
128
+ breakdown['bash'] = (breakdown['bash'] || 0) + 1;
129
+ }
130
+ else if (eventType === 'file_write') {
131
+ breakdown['file_write'] = (breakdown['file_write'] || 0) + 1;
132
+ }
133
+ else if (eventType === 'file_read') {
134
+ breakdown['file_read'] = (breakdown['file_read'] || 0) + 1;
135
+ }
136
+ else if (eventType === 'file_create') {
137
+ breakdown['file_create'] = (breakdown['file_create'] || 0) + 1;
138
+ }
139
+ else if (eventType === 'file_delete') {
140
+ breakdown['file_delete'] = (breakdown['file_delete'] || 0) + 1;
141
+ }
142
+ else if (eventType === 'tool_use') {
143
+ const tool = event.tool || 'unknown';
144
+ breakdown[tool] = (breakdown[tool] || 0) + 1;
145
+ }
146
+ }
147
+ return breakdown;
148
+ }
149
+ export function groupAndFlattenEvents(events) {
150
+ if (events.length === 0)
151
+ return [];
152
+ const grouped = [];
153
+ let i = 0;
154
+ while (i < events.length) {
155
+ const event = events[i];
156
+ const eventType = event.type || 'unknown';
157
+ if (eventType === 'message' || eventType === 'thinking') {
158
+ let count = 1;
159
+ let combinedContent = event.content || '';
160
+ let j = i + 1;
161
+ while (j < events.length && events[j].type === eventType) {
162
+ count++;
163
+ if (events[j].content) {
164
+ combinedContent += (combinedContent ? '\n' : '') + events[j].content;
165
+ }
166
+ j++;
167
+ }
168
+ const flattened = {
169
+ type: eventType,
170
+ content: combinedContent.length > 1000 ? combinedContent.slice(-1000) : combinedContent,
171
+ };
172
+ if (count > 1) {
173
+ flattened.count = count;
174
+ }
175
+ grouped.push(flattened);
176
+ i = j;
177
+ continue;
178
+ }
179
+ if (['file_write', 'file_create', 'file_read', 'file_delete'].includes(eventType)) {
180
+ const path = event.path || '';
181
+ if (!path) {
182
+ i++;
183
+ continue;
184
+ }
185
+ const pathGroup = {
186
+ type: eventType,
187
+ path: path,
188
+ count: 1,
189
+ };
190
+ let j = i + 1;
191
+ while (j < events.length && events[j].type === eventType && events[j].path === path) {
192
+ pathGroup.count++;
193
+ j++;
194
+ }
195
+ grouped.push(pathGroup);
196
+ i = j;
197
+ continue;
198
+ }
199
+ if (eventType === 'bash') {
200
+ const command = event.command || '';
201
+ if (!command) {
202
+ i++;
203
+ continue;
204
+ }
205
+ const bashGroup = {
206
+ type: 'bash',
207
+ commands: [command],
208
+ count: 1,
209
+ };
210
+ let j = i + 1;
211
+ while (j < events.length && events[j].type === 'bash') {
212
+ bashGroup.commands.push(events[j].command || '');
213
+ bashGroup.count++;
214
+ j++;
215
+ }
216
+ if (bashGroup.commands.length > 5) {
217
+ bashGroup.commands = bashGroup.commands.slice(-5);
218
+ bashGroup.truncated = bashGroup.count - 5;
219
+ }
220
+ grouped.push(bashGroup);
221
+ i = j;
222
+ continue;
223
+ }
224
+ if (eventType === 'tool_use') {
225
+ const flattened = {
226
+ type: 'tool_use',
227
+ tool: event.tool || 'unknown',
228
+ };
229
+ if (event.name)
230
+ flattened.name = event.name;
231
+ if (event.input) {
232
+ const inputStr = typeof event.input === 'string' ? event.input : JSON.stringify(event.input);
233
+ flattened.input = inputStr.length > 200 ? inputStr.slice(0, 200) + '...' : inputStr;
234
+ }
235
+ grouped.push(flattened);
236
+ i++;
237
+ continue;
238
+ }
239
+ if (['error', 'result'].includes(eventType)) {
240
+ const flattened = {
241
+ type: eventType,
242
+ };
243
+ if (event.message)
244
+ flattened.message = event.message;
245
+ if (event.content)
246
+ flattened.content = event.content;
247
+ if (event.status)
248
+ flattened.status = event.status;
249
+ grouped.push(flattened);
250
+ i++;
251
+ continue;
252
+ }
253
+ i++;
254
+ }
255
+ return grouped;
256
+ }
257
+ export class AgentSummary {
258
+ agentId;
259
+ agentType;
260
+ status;
261
+ duration = null;
262
+ filesModified = new Set();
263
+ filesCreated = new Set();
264
+ filesRead = new Set();
265
+ filesDeleted = new Set();
266
+ toolsUsed = new Set();
267
+ toolCallCount = 0;
268
+ bashCommands = [];
269
+ errors = [];
270
+ warnings = [];
271
+ finalMessage = null;
272
+ eventCount = 0;
273
+ lastActivity = null;
274
+ eventsCache = [];
275
+ constructor(agentId, agentType, status, duration = null, eventCount = 0) {
276
+ this.agentId = agentId;
277
+ this.agentType = agentType;
278
+ this.status = status;
279
+ this.duration = duration;
280
+ this.eventCount = eventCount;
281
+ }
282
+ toDict(detailLevel = 'standard') {
283
+ const base = {
284
+ agent_id: this.agentId,
285
+ agent_type: this.agentType,
286
+ status: this.status,
287
+ };
288
+ if (detailLevel === 'brief') {
289
+ return {
290
+ ...base,
291
+ duration: this.duration,
292
+ tool_call_count: this.toolCallCount,
293
+ last_activity: this.lastActivity,
294
+ files_modified: Array.from(this.filesModified).slice(0, 5),
295
+ files_created: Array.from(this.filesCreated).slice(0, 5),
296
+ has_errors: this.errors.length > 0,
297
+ };
298
+ }
299
+ else if (detailLevel === 'standard') {
300
+ return {
301
+ ...base,
302
+ duration: this.duration,
303
+ files_modified: Array.from(this.filesModified),
304
+ files_created: Array.from(this.filesCreated),
305
+ tools_used: Array.from(this.toolsUsed),
306
+ tool_call_count: this.toolCallCount,
307
+ errors: this.errors.slice(0, 3),
308
+ final_message: this.truncate(this.finalMessage, 2000),
309
+ };
310
+ }
311
+ else {
312
+ return {
313
+ ...base,
314
+ duration: this.duration,
315
+ files_modified: Array.from(this.filesModified),
316
+ files_created: Array.from(this.filesCreated),
317
+ files_read: Array.from(this.filesRead),
318
+ files_deleted: Array.from(this.filesDeleted),
319
+ tools_used: Array.from(this.toolsUsed),
320
+ tool_call_count: this.toolCallCount,
321
+ bash_commands: this.bashCommands.slice(-10),
322
+ errors: this.errors,
323
+ warnings: this.warnings,
324
+ final_message: this.finalMessage,
325
+ event_count: this.eventCount,
326
+ last_activity: this.lastActivity,
327
+ };
328
+ }
329
+ }
330
+ truncate(text, maxLen) {
331
+ if (!text)
332
+ return null;
333
+ if (text.length <= maxLen)
334
+ return text;
335
+ return text.substring(0, maxLen - 3) + '...';
336
+ }
337
+ }
338
+ export function summarizeEvents(agentId, agentType, status, events, duration = null) {
339
+ const summary = new AgentSummary(agentId, agentType, status, duration, events.length);
340
+ summary.eventsCache = events;
341
+ summary.agentId = agentId;
342
+ summary.agentType = agentType;
343
+ summary.status = status;
344
+ for (const event of events) {
345
+ const eventType = event.type || 'unknown';
346
+ summary.lastActivity = eventType;
347
+ if (eventType === 'file_write') {
348
+ const path = event.path || '';
349
+ if (path) {
350
+ summary.filesModified.add(path);
351
+ summary.toolCallCount++;
352
+ }
353
+ }
354
+ else if (eventType === 'file_create') {
355
+ const path = event.path || '';
356
+ if (path) {
357
+ summary.filesCreated.add(path);
358
+ summary.toolCallCount++;
359
+ }
360
+ }
361
+ else if (eventType === 'file_read') {
362
+ const path = event.path || '';
363
+ if (path) {
364
+ summary.filesRead.add(path);
365
+ summary.toolCallCount++;
366
+ }
367
+ }
368
+ else if (eventType === 'file_delete') {
369
+ const path = event.path || '';
370
+ if (path) {
371
+ summary.filesDeleted.add(path);
372
+ summary.toolCallCount++;
373
+ }
374
+ }
375
+ else if (eventType === 'directory_list') {
376
+ summary.toolCallCount++;
377
+ }
378
+ else if (eventType === 'tool_use') {
379
+ const tool = event.tool || 'unknown';
380
+ summary.toolsUsed.add(tool);
381
+ summary.toolCallCount++;
382
+ }
383
+ else if (eventType === 'bash') {
384
+ const command = event.command || '';
385
+ summary.toolsUsed.add('bash');
386
+ if (command) {
387
+ summary.bashCommands.push(command);
388
+ const [filesRead, filesWritten, filesDeleted] = extractFileOpsFromBash(command);
389
+ for (const path of filesRead) {
390
+ summary.filesRead.add(path);
391
+ }
392
+ for (const path of filesWritten) {
393
+ summary.filesModified.add(path);
394
+ }
395
+ for (const path of filesDeleted) {
396
+ summary.filesDeleted.add(path);
397
+ }
398
+ }
399
+ summary.toolCallCount++;
400
+ }
401
+ else if (eventType === 'message') {
402
+ const content = event.content || '';
403
+ if (content) {
404
+ summary.finalMessage = content;
405
+ }
406
+ }
407
+ else if (eventType === 'error') {
408
+ let errorMsg = null;
409
+ for (const key of ['message', 'content', 'error', 'error_message', 'details']) {
410
+ if (event[key]) {
411
+ errorMsg = String(event[key]);
412
+ break;
413
+ }
414
+ }
415
+ if (!errorMsg) {
416
+ errorMsg = extractErrorFromRawEvents(summary.eventsCache);
417
+ }
418
+ if (errorMsg) {
419
+ if (errorMsg.length > 500) {
420
+ errorMsg = errorMsg.substring(0, 497) + '...';
421
+ }
422
+ summary.errors.push(errorMsg);
423
+ }
424
+ }
425
+ else if (eventType === 'warning') {
426
+ const warningMsg = event.message || event.content || '';
427
+ if (warningMsg) {
428
+ summary.warnings.push(warningMsg);
429
+ }
430
+ }
431
+ else if (eventType === 'result') {
432
+ if (event.status === 'error') {
433
+ let errorMsg = null;
434
+ for (const key of ['message', 'error', 'error_message', 'error_details', 'details']) {
435
+ if (event[key]) {
436
+ errorMsg = String(event[key]);
437
+ break;
438
+ }
439
+ }
440
+ if (!errorMsg) {
441
+ errorMsg = extractErrorFromRawEvents(summary.eventsCache);
442
+ }
443
+ if (errorMsg) {
444
+ if (errorMsg.length > 500) {
445
+ errorMsg = errorMsg.substring(0, 497) + '...';
446
+ }
447
+ summary.errors.push(errorMsg);
448
+ }
449
+ }
450
+ if (!summary.duration && event.duration_ms) {
451
+ const durationMs = event.duration_ms;
452
+ const seconds = durationMs / 1000;
453
+ if (seconds < 60) {
454
+ if (seconds % 1 === 0) {
455
+ summary.duration = `${Math.floor(seconds)} seconds`;
456
+ }
457
+ else {
458
+ summary.duration = `${seconds.toFixed(1)} seconds`;
459
+ }
460
+ }
461
+ else {
462
+ const minutes = seconds / 60;
463
+ summary.duration = `${minutes.toFixed(1)} minutes`;
464
+ }
465
+ }
466
+ }
467
+ }
468
+ return summary;
469
+ }
470
+ export function getDelta(agentId, agentType, status, events, since // Optional: ISO timestamp (string) or event index (number)
471
+ ) {
472
+ // Filter events by timestamp (string) or index (number)
473
+ let newEvents;
474
+ let sinceEvent = 0;
475
+ if (since === undefined || since === null) {
476
+ // No filter - return all events
477
+ newEvents = events;
478
+ }
479
+ else if (typeof since === 'number') {
480
+ // Backward compatibility: event index
481
+ sinceEvent = since;
482
+ newEvents = events.slice(sinceEvent);
483
+ }
484
+ else if (typeof since === 'string') {
485
+ // New behavior: timestamp filtering
486
+ const sinceDate = new Date(since);
487
+ newEvents = events.filter((e) => {
488
+ if (!e.timestamp)
489
+ return false;
490
+ const eventDate = new Date(e.timestamp);
491
+ return eventDate > sinceDate;
492
+ });
493
+ }
494
+ else {
495
+ newEvents = events;
496
+ }
497
+ if (newEvents.length === 0) {
498
+ return {
499
+ agent_id: agentId,
500
+ status: status,
501
+ since_event: sinceEvent, // For backward compatibility
502
+ new_events_count: 0,
503
+ has_changes: false,
504
+ new_files_created: [],
505
+ new_files_modified: [],
506
+ new_files_read: [],
507
+ new_files_deleted: [],
508
+ new_bash_commands: [],
509
+ new_messages: [],
510
+ new_tool_count: 0,
511
+ new_errors: [],
512
+ };
513
+ }
514
+ const summary = summarizeEvents(agentId, agentType, status, newEvents);
515
+ return {
516
+ agent_id: agentId,
517
+ agent_type: agentType,
518
+ status: status,
519
+ since_event: sinceEvent, // For backward compatibility
520
+ new_events_count: newEvents.length,
521
+ current_event_count: sinceEvent + newEvents.length, // For backward compatibility
522
+ has_changes: true,
523
+ new_files_created: Array.from(summary.filesCreated),
524
+ new_files_modified: Array.from(summary.filesModified),
525
+ new_files_read: Array.from(summary.filesRead),
526
+ new_files_deleted: Array.from(summary.filesDeleted),
527
+ new_bash_commands: summary.bashCommands.slice(-15),
528
+ new_messages: getLastMessages(newEvents, 5),
529
+ new_tool_count: summary.toolCallCount,
530
+ new_tool_calls: newEvents // For backward compatibility
531
+ .filter((e) => ['tool_use', 'bash', 'file_write'].includes(e.type))
532
+ .slice(-5)
533
+ .map((e) => `${e.tool || 'unknown'}: ${e.command || e.path || ''}`),
534
+ latest_message: summary.finalMessage, // For backward compatibility
535
+ new_errors: summary.errors,
536
+ };
537
+ }
538
+ export function filterEventsByPriority(events, includeLevels = null) {
539
+ if (!includeLevels) {
540
+ includeLevels = ['critical', 'important'];
541
+ }
542
+ const allowedTypes = new Set();
543
+ for (const level of includeLevels) {
544
+ const types = PRIORITY[level] || [];
545
+ for (const type of types) {
546
+ allowedTypes.add(type);
547
+ }
548
+ }
549
+ return events.filter(e => allowedTypes.has(e.type));
550
+ }
551
+ export function getLastTool(events) {
552
+ if (events.length === 0)
553
+ return null;
554
+ const lastEvent = events[events.length - 1];
555
+ const eventType = lastEvent.type || '';
556
+ const validTypes = ['tool_use', 'bash', 'file_write', 'file_create', 'file_read', 'file_delete', 'message', 'error', 'result'];
557
+ if (validTypes.includes(eventType)) {
558
+ return eventType;
559
+ }
560
+ return null;
561
+ }
562
+ export function getToolUses(events) {
563
+ const toolUses = [];
564
+ for (const event of events) {
565
+ if (event.type === 'tool_use') {
566
+ const tool = event.tool || 'unknown';
567
+ const args = event.args || {};
568
+ toolUses.push({ tool, args });
569
+ }
570
+ }
571
+ return toolUses;
572
+ }
573
+ export function getLastMessages(events, count = 3) {
574
+ const messages = [];
575
+ let currentBuffer = '';
576
+ let isCollecting = false;
577
+ for (const event of events) {
578
+ if (event.type === 'message') {
579
+ const content = event.content || '';
580
+ // For streaming events (delta=true), content fragments should be joined.
581
+ // We don't add newlines because these are likely parts of the same sentence/block.
582
+ currentBuffer += content;
583
+ isCollecting = true;
584
+ // If we hit an explicitly complete message, treat it as a boundary
585
+ if (event.complete) {
586
+ if (currentBuffer.trim()) {
587
+ messages.push(currentBuffer);
588
+ }
589
+ currentBuffer = '';
590
+ isCollecting = false;
591
+ }
592
+ }
593
+ else {
594
+ // Any non-message event breaks the message stream
595
+ if (isCollecting) {
596
+ if (currentBuffer.trim()) {
597
+ messages.push(currentBuffer);
598
+ }
599
+ currentBuffer = '';
600
+ isCollecting = false;
601
+ }
602
+ }
603
+ }
604
+ // Handle any remaining buffer at the end
605
+ if (isCollecting && currentBuffer.trim()) {
606
+ messages.push(currentBuffer);
607
+ }
608
+ return messages.slice(-count);
609
+ }
610
+ export function getQuickStatus(agentId, agentType, status, events) {
611
+ const filesCreatedSet = new Set();
612
+ const filesModifiedSet = new Set();
613
+ const filesDeletedSet = new Set();
614
+ const filesReadSet = new Set();
615
+ let toolCount = 0;
616
+ let hasErrors = false;
617
+ const commands = [];
618
+ let lastMessage = null;
619
+ for (const event of events) {
620
+ const eventType = event.type || '';
621
+ if (eventType === 'message') {
622
+ const content = event.content || '';
623
+ if (content) {
624
+ lastMessage = content;
625
+ }
626
+ }
627
+ else if (eventType === 'file_create') {
628
+ const path = event.path || '';
629
+ if (path) {
630
+ filesCreatedSet.add(path);
631
+ }
632
+ toolCount++;
633
+ }
634
+ else if (eventType === 'file_write') {
635
+ const path = event.path || '';
636
+ if (path) {
637
+ filesModifiedSet.add(path);
638
+ }
639
+ toolCount++;
640
+ }
641
+ else if (eventType === 'file_delete') {
642
+ const path = event.path || '';
643
+ if (path) {
644
+ filesDeletedSet.add(path);
645
+ }
646
+ toolCount++;
647
+ }
648
+ else if (eventType === 'file_read') {
649
+ const path = event.path || '';
650
+ if (path) {
651
+ filesReadSet.add(path);
652
+ }
653
+ toolCount++;
654
+ }
655
+ else if (eventType === 'bash') {
656
+ toolCount++;
657
+ const cmd = event.command || '';
658
+ if (cmd) {
659
+ commands.push(cmd.length > 100 ? cmd.substring(0, 97) + '...' : cmd);
660
+ const [filesRead, filesWritten, filesDeleted] = extractFileOpsFromBash(cmd);
661
+ for (const path of filesRead) {
662
+ filesReadSet.add(path);
663
+ }
664
+ for (const path of filesWritten) {
665
+ filesModifiedSet.add(path);
666
+ }
667
+ for (const path of filesDeleted) {
668
+ filesDeletedSet.add(path);
669
+ }
670
+ }
671
+ }
672
+ else if (eventType === 'directory_list') {
673
+ toolCount++;
674
+ }
675
+ else if (['tool_use'].includes(eventType)) {
676
+ toolCount++;
677
+ }
678
+ else if (eventType === 'error' || (eventType === 'result' && event.status === 'error')) {
679
+ hasErrors = true;
680
+ }
681
+ }
682
+ return {
683
+ agent_id: agentId,
684
+ agent_type: agentType,
685
+ status: status,
686
+ files_created: filesCreatedSet.size,
687
+ files_modified: filesModifiedSet.size,
688
+ files_deleted: filesDeletedSet.size,
689
+ files_read: filesReadSet.size,
690
+ tool_count: toolCount,
691
+ last_commands: commands.slice(-3),
692
+ has_errors: hasErrors,
693
+ last_message: lastMessage,
694
+ };
695
+ }
696
+ export function getStatusSummary(agentId, agentType, status, events, duration = null) {
697
+ if (events.length === 0) {
698
+ if (status === 'running') {
699
+ return 'Just started, no activity yet';
700
+ }
701
+ return 'No activity';
702
+ }
703
+ let fileCount = 0;
704
+ let bashCount = 0;
705
+ let toolCount = 0;
706
+ let hasErrors = false;
707
+ for (const event of events) {
708
+ const eventType = event.type || '';
709
+ if (['file_write', 'file_create', 'file_delete'].includes(eventType)) {
710
+ fileCount++;
711
+ }
712
+ else if (eventType === 'bash') {
713
+ bashCount++;
714
+ }
715
+ else if (['tool_use', 'file_read'].includes(eventType)) {
716
+ toolCount++;
717
+ }
718
+ else if (['error', 'result'].includes(eventType)) {
719
+ if (event.status === 'error') {
720
+ hasErrors = true;
721
+ }
722
+ }
723
+ }
724
+ const totalTools = bashCount + toolCount;
725
+ const parts = [];
726
+ if (status === 'running') {
727
+ parts.push('Running');
728
+ }
729
+ else if (status === 'completed') {
730
+ if (hasErrors) {
731
+ parts.push('Completed with errors');
732
+ }
733
+ else {
734
+ parts.push('Completed successfully');
735
+ }
736
+ }
737
+ else if (status === 'failed') {
738
+ parts.push('Failed');
739
+ }
740
+ else if (status === 'stopped') {
741
+ parts.push('Stopped');
742
+ }
743
+ if (fileCount > 0) {
744
+ parts.push(`modified ${fileCount} file${fileCount !== 1 ? 's' : ''}`);
745
+ }
746
+ if (bashCount > 0) {
747
+ parts.push(`used bash ${bashCount} time${bashCount !== 1 ? 's' : ''}`);
748
+ }
749
+ if (toolCount > 0 && bashCount === 0) {
750
+ parts.push(`used ${toolCount} tool${toolCount !== 1 ? 's' : ''}`);
751
+ }
752
+ if (totalTools > 0 && bashCount > 0) {
753
+ parts.push(`used ${totalTools} tool${totalTools !== 1 ? 's' : ''}`);
754
+ }
755
+ if (hasErrors && status === 'running') {
756
+ parts.push('has errors');
757
+ }
758
+ if (parts.length === 0) {
759
+ if (status === 'running') {
760
+ return `Running, ${events.length} event${events.length !== 1 ? 's' : ''} so far`;
761
+ }
762
+ return status.charAt(0).toUpperCase() + status.slice(1);
763
+ }
764
+ return parts.join(', ');
765
+ }
766
+ //# sourceMappingURL=summarizer.js.map