diff --git a/api/streaming.py b/api/streaming.py index e7748440..9f079409 100644 --- a/api/streaming.py +++ b/api/streaming.py @@ -2052,7 +2052,10 @@ def _run_agent_streaming( # Pass personality via ephemeral_system_prompt (agent's own mechanism) if _personality_prompt: agent.ephemeral_system_prompt = _personality_prompt - _turn_started_at = getattr(s, 'pending_started_at', None) or time.time() + _pending_started_at = getattr(s, 'pending_started_at', None) + # Normal chat-start sets pending_started_at before spawning this thread; + # fallback to now only for recovered/legacy flows where that marker is absent. + _turn_started_at = _pending_started_at if _pending_started_at is not None else time.time() _previous_messages = list(s.messages or []) _previous_context_messages = list(_session_context_messages(s)) _pre_compression_count = getattr( diff --git a/tests/test_turn_duration_display.py b/tests/test_turn_duration_display.py index a3f79d24..8fc38c25 100644 --- a/tests/test_turn_duration_display.py +++ b/tests/test_turn_duration_display.py @@ -21,6 +21,14 @@ def test_streaming_done_payload_includes_backend_turn_duration(): "Turn duration should be measured from the persisted pending_started_at " "start time, not only from browser-local state." ) + assert "if _pending_started_at is not None else time.time()" in STREAMING_PY, ( + "The fallback should preserve explicit timestamp values and only use now " + "when pending_started_at is absent." + ) + assert "recovered/legacy flows" in STREAMING_PY, ( + "The missing-start fallback should be documented so it is not mistaken " + "for the primary timing path." + ) assert "_turnDuration" in STREAMING_PY, ( "The measured duration should be persisted on the assistant message so " "it survives reload after the SSE stream settles."