Revert "fix: ensure stop_reason is always set and reduce noisy logs (… (#9086)
Revert "fix: ensure stop_reason is always set and reduce noisy logs (#9046)" This reverts commit 4241a360579440d2697124ba69061d0e46ecc5e9. **Problem:** After the original change, caren-code-agent reported streams hanging indefinitely. The trace shows ttft (time to first token) succeeds, but the stream never closes. **Root Cause (suspected):** The change modified `is_complete=is_done` to `is_complete=saw_done`, meaning error events no longer mark the stream as complete immediately. This may cause timing issues where clients wait for more data before the finalizer runs. **Fix:** Revert to the defensive "belt-and-suspenders" approach that always appends [DONE]. The noisy logs are preferable to hanging streams. The original comment noted: "Even if a previous chunk set `complete`, an extra [DONE] is harmless and ensures SDKs that rely on explicit [DONE] will exit." 👾 Generated with [Letta Code](https://letta.com) Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -263,10 +263,11 @@ async def create_background_stream_processor(
|
|||||||
# Don't let parsing failures interfere with streaming
|
# Don't let parsing failures interfere with streaming
|
||||||
error_metadata = {"error": {"message": "Failed to parse error payload from stream."}}
|
error_metadata = {"error": {"message": "Failed to parse error payload from stream."}}
|
||||||
|
|
||||||
await writer.write_chunk(run_id=run_id, data=chunk, is_complete=saw_done)
|
is_done = saw_done or saw_error
|
||||||
|
|
||||||
# Only break after seeing [DONE] or error
|
await writer.write_chunk(run_id=run_id, data=chunk, is_complete=is_done)
|
||||||
if saw_done or saw_error:
|
|
||||||
|
if is_done:
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -393,19 +394,20 @@ async def create_background_stream_processor(
|
|||||||
conversation_id=conversation_id,
|
conversation_id=conversation_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Only append [DONE] if we didn't already see it (fallback safety mechanism)
|
# Belt-and-suspenders: always append a terminal [DONE] chunk to ensure clients terminate
|
||||||
if not saw_done:
|
# Even if a previous chunk set `complete`, an extra [DONE] is harmless and ensures SDKs that
|
||||||
logger.warning(
|
# rely on explicit [DONE] will exit.
|
||||||
"[Stream Finalizer] Appending forced [DONE] for run=%s (saw_error=%s, saw_done=%s, final_stop_reason=%s)",
|
logger.warning(
|
||||||
run_id,
|
"[Stream Finalizer] Appending forced [DONE] for run=%s (saw_error=%s, saw_done=%s, final_stop_reason=%s)",
|
||||||
saw_error,
|
run_id,
|
||||||
saw_done,
|
saw_error,
|
||||||
final_stop_reason,
|
saw_done,
|
||||||
)
|
final_stop_reason,
|
||||||
try:
|
)
|
||||||
await writer.mark_complete(run_id)
|
try:
|
||||||
except Exception as e:
|
await writer.mark_complete(run_id)
|
||||||
logger.warning(f"Failed to append terminal [DONE] for run {run_id}: {e}")
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to append terminal [DONE] for run {run_id}: {e}")
|
||||||
|
|
||||||
|
|
||||||
async def redis_sse_stream_generator(
|
async def redis_sse_stream_generator(
|
||||||
|
|||||||
Reference in New Issue
Block a user