( messages: RenderableMessage[], tools: Tools, )
| 786 | * - Breaks groups when assistant text appears |
| 787 | */ |
| 788 | export function collapseReadSearchGroups( |
| 789 | messages: RenderableMessage[], |
| 790 | tools: Tools, |
| 791 | ): RenderableMessage[] { |
| 792 | const result: RenderableMessage[] = [] |
| 793 | let currentGroup = createEmptyGroup() |
| 794 | let deferredSkippable: RenderableMessage[] = [] |
| 795 | |
| 796 | function flushGroup(): void { |
| 797 | if (currentGroup.messages.length === 0) { |
| 798 | return |
| 799 | } |
| 800 | result.push(createCollapsedGroup(currentGroup)) |
| 801 | for (const deferred of deferredSkippable) { |
| 802 | result.push(deferred) |
| 803 | } |
| 804 | deferredSkippable = [] |
| 805 | currentGroup = createEmptyGroup() |
| 806 | } |
| 807 | |
| 808 | for (const msg of messages) { |
| 809 | if (isCollapsibleToolUse(msg, tools)) { |
| 810 | // This is a collapsible tool use - type predicate narrows to CollapsibleMessage |
| 811 | const toolInfo = getCollapsibleToolInfo(msg, tools)! |
| 812 | |
| 813 | if (toolInfo.isMemoryWrite) { |
| 814 | // Memory file write/edit — check if it's team memory |
| 815 | const count = countToolUses(msg) |
| 816 | if ( |
| 817 | feature('TEAMMEM') && |
| 818 | teamMemOps?.isTeamMemoryWriteOrEdit(toolInfo.name, toolInfo.input) |
| 819 | ) { |
| 820 | currentGroup.teamMemoryWriteCount = |
| 821 | (currentGroup.teamMemoryWriteCount ?? 0) + count |
| 822 | } else { |
| 823 | currentGroup.memoryWriteCount += count |
| 824 | } |
| 825 | } else if (toolInfo.isAbsorbedSilently) { |
| 826 | // Snip/ToolSearch absorbed silently — no count, no summary text. |
| 827 | // Hidden from the default view but still shown in verbose mode |
| 828 | // (Ctrl+O) via the groupMessages iteration in CollapsedReadSearchContent. |
| 829 | } else if (toolInfo.mcpServerName) { |
| 830 | // MCP search/read — counted separately so the summary says |
| 831 | // "Queried slack N times" instead of "Read N files". |
| 832 | const count = countToolUses(msg) |
| 833 | currentGroup.mcpCallCount = (currentGroup.mcpCallCount ?? 0) + count |
| 834 | currentGroup.mcpServerNames?.add(toolInfo.mcpServerName) |
| 835 | const input = toolInfo.input as { query?: string } | undefined |
| 836 | if (input?.query) { |
| 837 | currentGroup.latestDisplayHint = `"${input.query}"` |
| 838 | } |
| 839 | } else if (isFullscreenEnvEnabled() && toolInfo.isBash) { |
| 840 | // Non-search/read Bash command — counted separately so the summary |
| 841 | // says "Ran N bash commands" instead of breaking the group. |
| 842 | const count = countToolUses(msg) |
| 843 | currentGroup.bashCount = (currentGroup.bashCount ?? 0) + count |
| 844 | const input = toolInfo.input as { command?: string } | undefined |
| 845 | if (input?.command) { |
no test coverage detected