Files
VoiceAgent/test_observer.py
2026-08-07 18:15:36 -04:00

49 lines
2.2 KiB
Python

"""The turn must close even if the reply observer explodes, and the observer
must be the one we passed rather than pipecat's."""
import asyncio, argparse, sys
sys.path.insert(0, "/Users/adolforeyna/voice-agent")
from pathlib import Path
from bot import build_claude_options
from claude_llm import ClaudeCodeLLM
from pipecat.frames.frames import EndFrame, Frame, LLMContextFrame, LLMFullResponseEndFrame
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.worker import PipelineWorker
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
from pipecat.workers.runner import WorkerRunner
class Sink(FrameProcessor):
def __init__(self):
super().__init__(); self.ended = asyncio.Event()
async def process_frame(self, f, d):
await super().process_frame(f, d)
if isinstance(f, LLMFullResponseEndFrame): self.ended.set()
await self.push_frame(f, d)
async def run(observer, label):
args = argparse.Namespace(allow_writes=False, cwd=str(Path.home()/"Workspace"),
claude_model="claude-sonnet-4-6", load_settings=False)
llm = ClaudeCodeLLM(options=build_claude_options(args, None, None), observer=observer)
sink = Sink()
worker = PipelineWorker(Pipeline([llm, sink]))
runner = WorkerRunner(handle_sigint=False)
await runner.add_workers(worker)
task = asyncio.create_task(runner.run())
await asyncio.sleep(0.4)
ctx = LLMContext(); ctx.add_message({"role":"user","content":"Say hi in three words."})
await worker.queue_frames([LLMContextFrame(context=ctx)])
try:
await asyncio.wait_for(sink.ended.wait(), timeout=90)
print(f" PASS {label}: turn closed")
except asyncio.TimeoutError:
print(f" FAIL {label}: LLMFullResponseEndFrame never arrived")
await worker.queue_frames([EndFrame()]); await task
async def main():
seen = []
await run(seen.append, "normal observer")
print(f" {'PASS' if seen else 'FAIL'} observer actually called ({len(seen)} reply)")
def boom(_): raise RuntimeError("observer blew up")
await run(boom, "observer raises")
asyncio.run(main())