( event: StreamEvent, context: StreamingContext, execContext: ExecutionContext, options: OrchestratorOptions, scope: ToolScope )
| 115 | * - Main call phase only stores in context.toolCalls |
| 116 | */ |
| 117 | export async function handleToolEvent( |
| 118 | event: StreamEvent, |
| 119 | context: StreamingContext, |
| 120 | execContext: ExecutionContext, |
| 121 | options: OrchestratorOptions, |
| 122 | scope: ToolScope |
| 123 | ): Promise<void> { |
| 124 | const isSubagent = scope === 'subagent' |
| 125 | const parentToolCallId = isSubagent ? getScopedParentToolCallId(event, context) : undefined |
| 126 | |
| 127 | if (isSubagent && !parentToolCallId) return |
| 128 | |
| 129 | if (event.type !== 'tool') { |
| 130 | return |
| 131 | } |
| 132 | |
| 133 | if (isToolArgsDeltaStreamEvent(event)) { |
| 134 | return |
| 135 | } |
| 136 | |
| 137 | // A tool event breaks the thinking stream. Flush any open thinking |
| 138 | // block into contentBlocks BEFORE we add the tool_call block, or |
| 139 | // contentBlocks will end up with tool_call before thinking — which |
| 140 | // re-renders on reload in the wrong order (Mothership group above |
| 141 | // the Thinking block, even though thinking happened first). A subagent |
| 142 | // tool event flushes only its OWN lane so a concurrent sibling's thinking |
| 143 | // is left intact; a main tool event flushes all subagent lanes. |
| 144 | if (isSubagent && parentToolCallId) { |
| 145 | flushSubagentThinkingBlock(context, parentToolCallId) |
| 146 | } else { |
| 147 | flushSubagentThinkingBlock(context) |
| 148 | } |
| 149 | flushThinkingBlock(context) |
| 150 | |
| 151 | if (isToolResultStreamEvent(event)) { |
| 152 | handleResultPhase(event.payload, context, parentToolCallId) |
| 153 | return |
| 154 | } |
| 155 | |
| 156 | if (!isToolCallStreamEvent(event)) { |
| 157 | return |
| 158 | } |
| 159 | |
| 160 | if (!parentToolCallId) { |
| 161 | context.sawMainToolCall = true |
| 162 | context.finalAssistantContent = '' |
| 163 | } |
| 164 | |
| 165 | await handleCallPhase( |
| 166 | event.payload, |
| 167 | context, |
| 168 | execContext, |
| 169 | options, |
| 170 | parentToolCallId, |
| 171 | scope, |
| 172 | getScopedSpanIdentity(event) |
| 173 | ) |
| 174 | } |
no test coverage detected