fix(tui-gateway): merge agent output on model-switch history_version mismatch (#76870)
When a model switch occurs mid-turn, `_append_model_switch_marker()` appends a marker to session history and increments `history_version`. The turn completion guard then sees `current_version != history_version` and discards all agent output — producing empty assistant messages in the session DB. Detect when the only history mutation during the turn was one or more model-switch markers. In that case, merge the agent's new messages into the current history (which now contains the marker) instead of discarding them. Genuine desyncs (undo/compress/retry) still surface the warning as before. Fixes #76870
This commit is contained in:
parent
75901a295d
commit
f9ed58e6ac
|
|
@ -9689,24 +9689,37 @@ def _run_prompt_submit(
|
|||
session["history"] = result["messages"]
|
||||
session["history_version"] = history_version + 1
|
||||
else:
|
||||
# History mutated externally during the turn
|
||||
# (undo/compress/retry/rollback now guard on
|
||||
# session.running, but this is the defensive
|
||||
# backstop for any path that slips past).
|
||||
# Surface the desync rather than silently
|
||||
# dropping the agent's output — the UI can
|
||||
# show the response and warn that it was
|
||||
# not persisted.
|
||||
print(
|
||||
f"[tui_gateway] prompt.submit: history_version mismatch "
|
||||
f"(expected={history_version} current={current_version}) — "
|
||||
f"agent output NOT written to session history",
|
||||
file=sys.stderr,
|
||||
)
|
||||
status_note = (
|
||||
"History changed during this turn — the response above is visible "
|
||||
"but was not saved to session history."
|
||||
# History mutated externally during the turn.
|
||||
# Check if the only mutation was a model-switch
|
||||
# marker inserted mid-turn (#76870). If so the
|
||||
# agent output is still valid — merge it into the
|
||||
# current history that now contains the marker.
|
||||
current_history = list(session["history"])
|
||||
added = current_history[len(history):]
|
||||
model_switch_only = (
|
||||
len(added) >= 1
|
||||
and all(_is_model_switch_marker(e) for e in added)
|
||||
)
|
||||
if model_switch_only:
|
||||
new_messages = result["messages"][len(history):]
|
||||
session["history"] = current_history + new_messages
|
||||
session["history_version"] = current_version + 1
|
||||
else:
|
||||
# Genuine desync (undo/compress/retry/rollback).
|
||||
# Surface the desync rather than silently
|
||||
# dropping the agent's output — the UI can
|
||||
# show the response and warn that it was
|
||||
# not persisted.
|
||||
print(
|
||||
f"[tui_gateway] prompt.submit: history_version mismatch "
|
||||
f"(expected={history_version} current={current_version}) — "
|
||||
f"agent output NOT written to session history",
|
||||
file=sys.stderr,
|
||||
)
|
||||
status_note = (
|
||||
"History changed during this turn — the response above is visible "
|
||||
"but was not saved to session history."
|
||||
)
|
||||
|
||||
# If auto-compression fired inside run_conversation(), agent.session_id
|
||||
# may have rotated. Sync session_key before downstream title/goal/finalize
|
||||
|
|
|
|||
Loading…
Reference in New Issue