"""The journal must capture both halves of a turn. Regression test for a placement bug: the journal originally sat at the end of the pipeline, where the user aggregator has already consumed the transcript, so it never recorded anything at all. """ import asyncio, json, sys, tempfile from pathlib import Path sys.path.insert(0, str(Path(__file__).parent)) from journal import Journal from pipecat.frames.frames import EndFrame, TranscriptionFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.worker import PipelineWorker from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.aggregators.llm_response_universal import ( LLMContextAggregatorPair, LLMUserAggregatorParams) from pipecat.turns.user_start.external_user_turn_start_strategy import ExternalUserTurnStartStrategy from pipecat.turns.user_stop.external_user_turn_stop_strategy import ExternalUserTurnStopStrategy from pipecat.turns.user_turn_strategies import UserTurnStrategies from pipecat.utils.time import time_now_iso8601 from pipecat.workers.runner import WorkerRunner async def main(): path = Path(tempfile.mkdtemp()) / "journal.jsonl" journal = Journal(path) ctx = LLMContext() ua, _ = LLMContextAggregatorPair(ctx, user_params=LLMUserAggregatorParams( user_turn_strategies=UserTurnStrategies( start=[ExternalUserTurnStartStrategy()], stop=[ExternalUserTurnStopStrategy()]))) worker = PipelineWorker(Pipeline([journal, ua])) runner = WorkerRunner(handle_sigint=False) await runner.add_workers(worker) task = asyncio.create_task(runner.run()) await asyncio.sleep(0.3) await worker.queue_frames([ TranscriptionFrame("what is the sample rate", "u", time_now_iso8601(), None)]) await asyncio.sleep(0.5) journal.record_reply("Sixteen kilohertz.") await asyncio.sleep(0.3) await worker.queue_frames([EndFrame()]) await task rows = [json.loads(l) for l in path.read_text().splitlines() if l.strip()] print(f" {'PASS' if rows else 'FAIL'} journal file written ({len(rows)} entries)") if rows: r = rows[0] print(f" {'PASS' if r['heard'] else 'FAIL'} captured what was heard: {r['heard']!r}") print(f" {'PASS' if r['reply'] else 'FAIL'} captured the reply: {r['reply']!r}") asyncio.run(main())