Stream response from LLM client. Args: client: LLM client with streaming support messages: Conversation messages tools: Available tools for function calling after_tool_calls: True when this is a follow-up after tool execution (
(
self,
client,
messages: list[dict[str, Any]],
tools: list[dict[str, Any]] | None = None,
after_tool_calls: bool = False,
**kwargs,
)
| 246 | self._dashboard_bridge = dashboard_bridge |
| 247 | |
| 248 | async def stream_response( |
| 249 | self, |
| 250 | client, |
| 251 | messages: list[dict[str, Any]], |
| 252 | tools: list[dict[str, Any]] | None = None, |
| 253 | after_tool_calls: bool = False, |
| 254 | **kwargs, |
| 255 | ) -> dict[str, Any]: |
| 256 | """Stream response from LLM client. |
| 257 | |
| 258 | Args: |
| 259 | client: LLM client with streaming support |
| 260 | messages: Conversation messages |
| 261 | tools: Available tools for function calling |
| 262 | after_tool_calls: True when this is a follow-up after tool execution |
| 263 | (thinking models need extra time to process tool results) |
| 264 | **kwargs: Additional arguments for client |
| 265 | |
| 266 | Returns: |
| 267 | Response dictionary (for backwards compatibility) |
| 268 | """ |
| 269 | # Reset state |
| 270 | self._interrupted = False |
| 271 | self._usage = None |
| 272 | self.tool_accumulator = ToolCallAccumulator() |
| 273 | |
| 274 | # Start display |
| 275 | await self.display.start_streaming() |
| 276 | start_time = time.time() |
| 277 | |
| 278 | try: |
| 279 | # Check client capabilities |
| 280 | if not hasattr(client, "create_completion"): |
| 281 | logger.warning("Client doesn't support create_completion") |
| 282 | return await self._handle_non_streaming( |
| 283 | client, messages, tools, **kwargs |
| 284 | ) |
| 285 | |
| 286 | # Stream with chunk timeout protection |
| 287 | await self._stream_with_timeout( |
| 288 | client, messages, tools, after_tool_calls=after_tool_calls, **kwargs |
| 289 | ) |
| 290 | |
| 291 | # Finalize tool calls |
| 292 | tool_calls = self.tool_accumulator.finalize() |
| 293 | |
| 294 | # Capture state values BEFORE stop_streaming clears them |
| 295 | chunks_received = ( |
| 296 | self.display.streaming_state.chunks_received |
| 297 | if self.display.streaming_state |
| 298 | else 0 |
| 299 | ) |
| 300 | reasoning_content = ( |
| 301 | self.display.streaming_state.reasoning_content |
| 302 | if self.display.streaming_state |
| 303 | else None |
| 304 | ) |
| 305 |