52 lines
1.9 KiB
Python
52 lines
1.9 KiB
Python
"""A long tool call must not get the pipeline cancelled.
|
|
|
|
Regression test: pipecat's idle timer only resets on speech frames, so a slow
|
|
turn looked identical to an abandoned session and cancelled the worker and the
|
|
runner mid-answer.
|
|
"""
|
|
import asyncio, sys
|
|
from pathlib import Path
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
from pipecat.frames.frames import EndFrame, Frame, TTSSpeakFrame
|
|
from pipecat.pipeline.pipeline import Pipeline
|
|
from pipecat.pipeline.worker import PipelineParams, PipelineWorker
|
|
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
|
|
from pipecat.workers.runner import WorkerRunner
|
|
|
|
class Probe(FrameProcessor):
|
|
async def process_frame(self, f, d):
|
|
await super().process_frame(f, d)
|
|
await self.push_frame(f, d)
|
|
|
|
async def run(idle_timeout_secs, label, *, expect_cancelled, quiet_for=4.0):
|
|
worker = PipelineWorker(
|
|
Pipeline([Probe()]),
|
|
params=PipelineParams(),
|
|
idle_timeout_secs=idle_timeout_secs,
|
|
)
|
|
cancelled = {"yes": False}
|
|
@worker.event_handler("on_idle_timeout")
|
|
async def _(w):
|
|
cancelled["yes"] = True
|
|
|
|
runner = WorkerRunner(handle_sigint=False)
|
|
await runner.add_workers(worker)
|
|
task = asyncio.create_task(runner.run())
|
|
await asyncio.sleep(quiet_for) # stand in for a slow tool call
|
|
alive = not task.done()
|
|
await worker.queue_frames([EndFrame()])
|
|
try:
|
|
await asyncio.wait_for(task, timeout=10)
|
|
except Exception:
|
|
pass
|
|
got_cancelled = cancelled["yes"] or not alive
|
|
verdict = "PASS" if got_cancelled == expect_cancelled else "FAIL"
|
|
print(f" {verdict} {label}: cancelled={got_cancelled} (expected {expect_cancelled})")
|
|
|
|
async def main():
|
|
# The first shows the bug is real; the second shows the fix holds.
|
|
await run(2.0, "a short idle timeout still cancels", expect_cancelled=True)
|
|
await run(None, "disabled: a slow turn survives", expect_cancelled=False)
|
|
|
|
asyncio.run(main())
|