Mercurial
diff dictation/session.py @ 280:49e9e591c9bb
Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 18 Aug 2026 19:14:53 -0700 |
| parents | 78699f810817 |
| children |
line wrap: on
line diff
--- a/dictation/session.py Mon Aug 17 22:22:36 2026 -0700 +++ b/dictation/session.py Tue Aug 18 19:14:53 2026 -0700 @@ -54,8 +54,11 @@ @channel.on("message") def on_message(message: Any) -> None: - if message == "stop": - self.stopping = True + if message in {"commit", "pause", "stop"}: + if message == "stop": + self.stopping = True + if self.partial_task and not self.partial_task.done(): + self.partial_task.cancel() event = self.segmenter.flush() if event and event.samples is not None: self._start_final(event.samples) @@ -155,6 +158,26 @@ ) ) + async def _cancel_pending_ice_transactions(self) -> None: + # aioice 0.10.2 can leave STUN retry timers armed after its datagram + # transport closes. Cancel their futures first so Transaction.run() + # clears each timer before RTCPeerConnection.close() drops sockets. + ice_transports = getattr( + self.peer, + "_RTCPeerConnection__iceTransports", + (), + ) + for ice_transport in ice_transports: + connection = getattr(ice_transport, "_connection", None) + for protocol in getattr(connection, "_protocols", ()): + for transaction in tuple( + getattr(protocol, "transactions", {}).values() + ): + future = getattr(transaction, "_Transaction__future", None) + if future is not None and not future.done(): + future.cancel() + await asyncio.sleep(0) + async def close(self) -> None: if self.closed: return @@ -174,4 +197,5 @@ await asyncio.gather(*tasks, return_exceptions=True) if self.channel and self.channel.readyState != "closed": self.channel.close() + await self._cancel_pending_ice_transactions() await self.peer.close()