fix(office-ui): stop progress-row flicker and surface native role replies end to end
Two user-visible defects in company mode, root-caused via project 6666/8888 DB forensics: Progress-row flicker (thinking preview appearing/disappearing): progress entries were broadcast to clients before reaching the persistence buffer, so a tool_call-triggered session_detail snapshot rebuilt from the DB erased freshly streamed entries from the live log. Buffer now fills before the broadcast and session_detail flushes it before reading. Native role transcripts incomplete (thinking only at start, no narration, no final summary — external agents unaffected): - thinking deltas shared one stream id per conversation turn while seq reset per iteration, collapsing all iterations into one entry and silently dropping live thinking from iteration 2 on; now keyed per iteration like assistant deltas - assistant_delta events were mapped to None; company mode now surfaces them as streaming 'assistant' progress entries (rendered as Reply cards, merged like thinking, excluded from inline chat rows) - thinking was persisted one row per token, flooding the 1000-entry cap and evicting interleaved tool history; append_progress now folds streaming deltas per (type, turn, stream) with seq dedup - the terminal company turn was hidden at summary detail and, worse, its id-keyed backfill merge kept the first-inserted intermediate content, so the final reply never reached any channel; terminal turns are now flagged company_final_turn, visible at summary detail, and carry their own ui_message_id so they insert as fresh rows - appendProgressEntry applied its seq guard against unrelated entries when the stream key was absent from the log, killing the first delta of any fresh stream; the guard now only applies within the same stream Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -435,8 +435,13 @@ class NativeRuntimeV2:
|
||||
"canonical_turn_id": conversation_turn_id,
|
||||
"conversation_turn_id": conversation_turn_id,
|
||||
"execution_turn_id": execution_turn_id,
|
||||
"item_id": f"{turn_id}:thinking",
|
||||
"stream_id": f"{turn_id}:thinking",
|
||||
# Keyed per iteration (like assistant_delta):
|
||||
# thinking_delta_seq resets every iteration, so a
|
||||
# turn-scoped stream id makes downstream seq guards
|
||||
# drop iteration>=2 deltas and collapses all
|
||||
# iterations into one entry (no tool interleaving).
|
||||
"item_id": f"{execution_turn_id}:thinking",
|
||||
"stream_id": f"{execution_turn_id}:thinking",
|
||||
"seq": thinking_delta_seq,
|
||||
"text": thinking_text,
|
||||
},
|
||||
@@ -2797,6 +2802,11 @@ class NativeRuntimeV2:
|
||||
if is_company_mode:
|
||||
metadata["execution_mode"] = "company_mode"
|
||||
metadata["company_runtime_raw_turn"] = True
|
||||
if not tool_calls:
|
||||
# Terminal iteration of the company turn — this is the role's
|
||||
# final reply. Marked so the UI can show it at summary detail
|
||||
# even though the kind is otherwise full-detail-only.
|
||||
metadata["company_final_turn"] = True
|
||||
if task.assigned_to:
|
||||
metadata["role_id"] = str(task.assigned_to)
|
||||
else:
|
||||
@@ -2808,7 +2818,15 @@ class NativeRuntimeV2:
|
||||
if message_turn_id and message_turn_id != canonical_turn_id:
|
||||
metadata["execution_turn_id"] = message_turn_id
|
||||
if is_company_mode:
|
||||
metadata["ui_message_id"] = f"runtime-v2-company-assistant:{canonical_turn_id}"
|
||||
# Tool-calling iterations of a company conversation turn share
|
||||
# one UI row; the terminal reply gets its own id. The id-keyed
|
||||
# backfill merge keeps the first-inserted content for same-kind
|
||||
# candidates, so reusing the shared id freezes the row at
|
||||
# iteration 1 and swallows the final reply entirely.
|
||||
if metadata.get("company_final_turn"):
|
||||
metadata["ui_message_id"] = f"runtime-v2-company-assistant-final:{canonical_turn_id}"
|
||||
else:
|
||||
metadata["ui_message_id"] = f"runtime-v2-company-assistant:{canonical_turn_id}"
|
||||
elif is_intermediate_tool_turn:
|
||||
metadata["ui_message_id"] = f"runtime-v2-intermediate-assistant:{message_turn_id or canonical_turn_id}"
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user