(toolUses: Array<{
param: ToolUseBlockParam;
isResolved: boolean;
isError: boolean;
isInProgress: boolean;
progressMessages: ProgressMessage<Progress>[];
result?: {
param: ToolResultBlockParam;
output: Output;
};
}>, options: {
shouldAnimate: boolean;
tools: Tools;
})
| 647 | }; |
| 648 | } |
| 649 | export function renderGroupedAgentToolUse(toolUses: Array<{ |
| 650 | param: ToolUseBlockParam; |
| 651 | isResolved: boolean; |
| 652 | isError: boolean; |
| 653 | isInProgress: boolean; |
| 654 | progressMessages: ProgressMessage<Progress>[]; |
| 655 | result?: { |
| 656 | param: ToolResultBlockParam; |
| 657 | output: Output; |
| 658 | }; |
| 659 | }>, options: { |
| 660 | shouldAnimate: boolean; |
| 661 | tools: Tools; |
| 662 | }): React.ReactNode | null { |
| 663 | const { |
| 664 | shouldAnimate, |
| 665 | tools |
| 666 | } = options; |
| 667 | |
| 668 | // Calculate stats for each agent |
| 669 | const agentStats = toolUses.map(({ |
| 670 | param, |
| 671 | isResolved, |
| 672 | isError, |
| 673 | progressMessages, |
| 674 | result |
| 675 | }) => { |
| 676 | const stats = calculateAgentStats(progressMessages); |
| 677 | const lastToolInfo = extractLastToolInfo(progressMessages, tools); |
| 678 | const parsedInput = inputSchema().safeParse(param.input); |
| 679 | |
| 680 | // teammate_spawned is not part of the exported Output type (cast through unknown |
| 681 | // for dead code elimination), so check via string comparison on the raw value |
| 682 | const isTeammateSpawn = result?.output?.status as string === 'teammate_spawned'; |
| 683 | |
| 684 | // For teammate spawns, show @name with type in parens and description as status |
| 685 | let agentType: string; |
| 686 | let description: string | undefined; |
| 687 | let color: keyof Theme | undefined; |
| 688 | let descriptionColor: keyof Theme | undefined; |
| 689 | let taskDescription: string | undefined; |
| 690 | if (isTeammateSpawn && parsedInput.success && parsedInput.data.name) { |
| 691 | agentType = `@${parsedInput.data.name}`; |
| 692 | const subagentType = parsedInput.data.subagent_type; |
| 693 | description = isCustomSubagentType(subagentType) ? subagentType : undefined; |
| 694 | taskDescription = parsedInput.data.description; |
| 695 | // Use the custom agent definition's color on the type, not the name |
| 696 | descriptionColor = isCustomSubagentType(subagentType) ? getAgentColor(subagentType) as keyof Theme | undefined : undefined; |
| 697 | } else { |
| 698 | agentType = parsedInput.success ? userFacingName(parsedInput.data) : 'Agent'; |
| 699 | description = parsedInput.success ? parsedInput.data.description : undefined; |
| 700 | color = parsedInput.success ? userFacingNameBackgroundColor(parsedInput.data) : undefined; |
| 701 | taskDescription = undefined; |
| 702 | } |
| 703 | |
| 704 | // Check if this was launched as a background agent OR backgrounded mid-execution |
| 705 | const launchedAsAsync = parsedInput.success && 'run_in_background' in parsedInput.data && parsedInput.data.run_in_background === true; |
| 706 | const outputStatus = (result?.output as { |
nothing calls this directly
no test coverage detected