Captures stdout from agent and streams it to websocket without dropping numeric content
| 16 | logging.getLogger('websockets.protocol').setLevel(logging.CRITICAL) |
| 17 | |
| 18 | class StreamCapture: |
| 19 | """Captures stdout from agent and streams it to websocket without dropping numeric content""" |
| 20 | |
| 21 | def __init__(self, websocket): |
| 22 | self.websocket = websocket |
| 23 | self.buffer = "" |
| 24 | self.original_stdout = sys.stdout |
| 25 | self.in_tool_execution = False |
| 26 | self.response_started = False |
| 27 | |
| 28 | def write(self, text): |
| 29 | self.buffer += text |
| 30 | asyncio.create_task(self.process_buffer()) |
| 31 | |
| 32 | def flush(self): |
| 33 | self.original_stdout.flush() |
| 34 | |
| 35 | async def process_buffer(self): |
| 36 | if not self.buffer: |
| 37 | return |
| 38 | |
| 39 | text = self.buffer |
| 40 | self.buffer = "" |
| 41 | |
| 42 | # Tool execution detection |
| 43 | if "🛠️ Executing tool:" in text or "Executing tool:" in text: |
| 44 | self.in_tool_execution = True |
| 45 | try: |
| 46 | await self.websocket.send(json.dumps({ |
| 47 | "type": "tool_execution", |
| 48 | "message": "Processing with tools...", |
| 49 | "timestamp": time.time() |
| 50 | })) |
| 51 | except: |
| 52 | pass |
| 53 | return |
| 54 | |
| 55 | if self.in_tool_execution: |
| 56 | # End tool execution once normal text comes in |
| 57 | if not ("Args:" in text or "command" in text or "action" in text): |
| 58 | self.in_tool_execution = False |
| 59 | |
| 60 | # ✅ Do NOT strip here – just send raw text |
| 61 | if text: |
| 62 | try: |
| 63 | if not self.response_started: |
| 64 | await self.websocket.send(json.dumps({ |
| 65 | "type": "response_start", |
| 66 | "timestamp": time.time() |
| 67 | })) |
| 68 | self.response_started = True |
| 69 | |
| 70 | await self.websocket.send(json.dumps({ |
| 71 | "type": "response_chunk", |
| 72 | "chunk": text, # ← raw text, spaces preserved |
| 73 | "timestamp": time.time() |
| 74 | })) |
| 75 | except: |
no outgoing calls
no test coverage detected