(self, request)
| 235 | log("info", "Global TTS process stopped") |
| 236 | |
| 237 | async def handle_chat(self, request): |
| 238 | # Set heartbeat interval to 30 seconds and timeout to 60 seconds to prevent connections from being disconnected by intermediate proxies/firewalls |
| 239 | ws = web.WebSocketResponse(heartbeat=30.0, receive_timeout=None) |
| 240 | await ws.prepare(request) |
| 241 | |
| 242 | client_id = f"Client-{id(ws)}" |
| 243 | turn_counter = 0 |
| 244 | is_recording = True |
| 245 | |
| 246 | # system_prompt for current session |
| 247 | session_system_prompt = self.system_prompt |
| 248 | |
| 249 | # history |
| 250 | messages = [] |
| 251 | audio_list = [] |
| 252 | |
| 253 | async def recv_loop(): |
| 254 | nonlocal close, is_recording, turn_counter, opus_reader |
| 255 | try: |
| 256 | async for message in ws: |
| 257 | if message.type == aiohttp.WSMsgType.ERROR: |
| 258 | log("error", f"{ws.exception()}") |
| 259 | break |
| 260 | elif message.type == aiohttp.WSMsgType.CLOSED: |
| 261 | break |
| 262 | elif message.type != aiohttp.WSMsgType.BINARY: |
| 263 | log("error", f"unexpected message type {message.type}") |
| 264 | continue |
| 265 | message = message.data |
| 266 | if not isinstance(message, bytes): |
| 267 | log("error", f"unsupported message type {type(message)}") |
| 268 | continue |
| 269 | if len(message) == 0: |
| 270 | log("warning", "empty message") |
| 271 | continue |
| 272 | |
| 273 | try: |
| 274 | decoded = decode_message(message) |
| 275 | msg_type = decoded['type'] |
| 276 | |
| 277 | if msg_type == 'audio': |
| 278 | if is_recording: |
| 279 | payload = decoded['data'] |
| 280 | log("info", f"Received audio data: {len(payload)} bytes") |
| 281 | pcm = opus_reader.append_bytes(payload) |
| 282 | if pcm is not None and len(pcm) > 0: |
| 283 | await pcm_queue.put(pcm) |
| 284 | |
| 285 | elif msg_type == 'control': |
| 286 | action = decoded['action'] |
| 287 | if action == 'pause': |
| 288 | log("info", f"Received PAUSE signal") |
| 289 | is_recording = False |
| 290 | await save_audio_queue.put(('pause', None)) |
| 291 | elif action == 'start': |
| 292 | log("info", f"Received START signal") |
| 293 | is_recording = True |
| 294 | turn_counter += 1 |
nothing calls this directly
no test coverage detected