* Process progress messages to group consecutive search/read operations into summaries. * For ants only - returns original messages for non-ants. * @param isAgentRunning - If true, the last group is always marked as active (in progress)
(messages: ProgressMessage<Progress>[], tools: Tools, isAgentRunning: boolean)
| 98 | * @param isAgentRunning - If true, the last group is always marked as active (in progress) |
| 99 | */ |
| 100 | function processProgressMessages(messages: ProgressMessage<Progress>[], tools: Tools, isAgentRunning: boolean): ProcessedMessage[] { |
| 101 | // Only process for ants |
| 102 | if ("external" !== 'ant') { |
| 103 | return messages.filter((m): m is ProgressMessage<AgentToolProgress> => hasProgressMessage(m.data) && m.data.message.type !== 'user').map(m => ({ |
| 104 | type: 'original', |
| 105 | message: m |
| 106 | })); |
| 107 | } |
| 108 | const result: ProcessedMessage[] = []; |
| 109 | let currentGroup: { |
| 110 | searchCount: number; |
| 111 | readCount: number; |
| 112 | replCount: number; |
| 113 | startUuid: string; |
| 114 | } | null = null; |
| 115 | function flushGroup(isActive: boolean): void { |
| 116 | if (currentGroup && (currentGroup.searchCount > 0 || currentGroup.readCount > 0 || currentGroup.replCount > 0)) { |
| 117 | result.push({ |
| 118 | type: 'summary', |
| 119 | searchCount: currentGroup.searchCount, |
| 120 | readCount: currentGroup.readCount, |
| 121 | replCount: currentGroup.replCount, |
| 122 | uuid: `summary-${currentGroup.startUuid}`, |
| 123 | isActive |
| 124 | }); |
| 125 | } |
| 126 | currentGroup = null; |
| 127 | } |
| 128 | const agentMessages = messages.filter((m): m is ProgressMessage<AgentToolProgress> => hasProgressMessage(m.data)); |
| 129 | |
| 130 | // Build tool_use lookup incrementally as we iterate |
| 131 | const toolUseByID = new Map<string, ToolUseBlockParam>(); |
| 132 | for (const msg of agentMessages) { |
| 133 | // Track tool_use blocks as we see them |
| 134 | if (msg.data.message.type === 'assistant') { |
| 135 | for (const c of msg.data.message.message.content) { |
| 136 | if (c.type === 'tool_use') { |
| 137 | toolUseByID.set(c.id, c as ToolUseBlockParam); |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | const info = getSearchOrReadInfo(msg, tools, toolUseByID); |
| 142 | if (info && (info.isSearch || info.isRead || info.isREPL)) { |
| 143 | // This is a search/read/REPL operation - add to current group |
| 144 | if (!currentGroup) { |
| 145 | currentGroup = { |
| 146 | searchCount: 0, |
| 147 | readCount: 0, |
| 148 | replCount: 0, |
| 149 | startUuid: msg.uuid |
| 150 | }; |
| 151 | } |
| 152 | // Only count tool_result messages (not tool_use) to avoid double counting |
| 153 | if (msg.data.message.type === 'user') { |
| 154 | if (info.isSearch) { |
| 155 | currentGroup.searchCount++; |
| 156 | } else if (info.isREPL) { |
| 157 | currentGroup.replCount++; |
no test coverage detected