Clean, async-native streaming handler. Uses unified display system - no fallbacks, no dual paths.
| 220 | |
| 221 | |
| 222 | class StreamingResponseHandler: |
| 223 | """Clean, async-native streaming handler. |
| 224 | |
| 225 | Uses unified display system - no fallbacks, no dual paths. |
| 226 | """ |
| 227 | |
| 228 | def __init__( |
| 229 | self, |
| 230 | display: StreamingDisplayManager, |
| 231 | runtime_config: RuntimeConfig | None = None, |
| 232 | dashboard_bridge: "DashboardBridge | None" = None, |
| 233 | ): |
| 234 | """Initialize handler. |
| 235 | |
| 236 | Args: |
| 237 | display: The unified display manager (required, no fallback) |
| 238 | runtime_config: Runtime configuration (optional, will load defaults if not provided) |
| 239 | dashboard_bridge: Optional DashboardBridge for live token streaming to browser. |
| 240 | """ |
| 241 | self.display = display |
| 242 | self.tool_accumulator = ToolCallAccumulator() |
| 243 | self._interrupted = False |
| 244 | self._usage: dict[str, int] | None = None |
| 245 | self.runtime_config = runtime_config or load_runtime_config() |
| 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 |
no outgoing calls