From 324a019b5f91380943a5bf7fcd5b463bcf3b4aab Mon Sep 17 00:00:00 2001 From: Sabiha Khan Date: Tue, 7 Jul 2026 14:41:44 +0530 Subject: [PATCH] fix: non vad user turn timestamp --- api/services/pipecat/in_memory_buffers.py | 5 +++- api/tests/test_realtime_feedback_observer.py | 25 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/api/services/pipecat/in_memory_buffers.py b/api/services/pipecat/in_memory_buffers.py index 9b10ebde..349c1add 100644 --- a/api/services/pipecat/in_memory_buffers.py +++ b/api/services/pipecat/in_memory_buffers.py @@ -137,7 +137,10 @@ class InMemoryLogsBuffer: self, timestamp: Optional[str] = None, *, from_vad: bool = False ): """Record when the user started speaking for the current turn.""" - if self._user_speech_start_from_vad and not from_vad: + vad_interval_is_open = ( + self._user_speech_start_from_vad and self._user_speech_end_timestamp is None + ) + if vad_interval_is_open and not from_vad: return self._user_speech_start_timestamp = timestamp or self._now_iso() diff --git a/api/tests/test_realtime_feedback_observer.py b/api/tests/test_realtime_feedback_observer.py index e70c81b8..781339b5 100644 --- a/api/tests/test_realtime_feedback_observer.py +++ b/api/tests/test_realtime_feedback_observer.py @@ -265,3 +265,28 @@ async def test_completed_bot_speech_interval_is_not_reused_for_next_pre_playback second_event = logs_buffer.get_events()[-1] assert second_event["payload"] == {"text": "Second"} + + +@pytest.mark.asyncio +async def test_non_vad_user_turn_after_completed_vad_turn_gets_fresh_timestamps(): + logs_buffer = InMemoryLogsBuffer(workflow_run_id=123) + + logs_buffer.mark_user_started_speaking( + "2026-01-01T00:00:01.000+00:00", from_vad=True + ) + logs_buffer.mark_user_stopped_speaking( + "2026-01-01T00:00:02.000+00:00", from_vad=True + ) + await logs_buffer.append( + {"type": "rtf-user-transcription", "payload": {"text": "First", "final": True}} + ) + + logs_buffer.mark_user_started_speaking("2026-01-01T00:00:10.000+00:00") + logs_buffer.mark_user_stopped_speaking("2026-01-01T00:00:12.000+00:00") + await logs_buffer.append( + {"type": "rtf-user-transcription", "payload": {"text": "Second", "final": True}} + ) + + second_event = logs_buffer.get_events()[-1] + assert second_event["payload"]["timestamp"] == "2026-01-01T00:00:10.000+00:00" + assert second_event["payload"]["end_timestamp"] == "2026-01-01T00:00:12.000+00:00"