Pipeline.run() used asyncio.gather, so if one loop raised, the failing coroutine propagated while the sibling loops kept running detached; aclose() in the finally then closed a source/stt out from under a still-live loop. Switch to asyncio.TaskGroup so a failing loop cancels+awaits the siblings before teardown. Add a regression test asserting an error in the conversation loop cancels the perception loop and still closes every source.
4.3 KiB
4.3 KiB