Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

## [Unreleased]

### Fixed

- Messaging/session display merges now preserve sidecar transcript order when the sidecar already contains at least as many rows as the mirrored state store, avoiding role/content fallback sorting when timestamp precision collapses.

## [v0.51.153] — 2026-05-28 — Release DY (stage-batch35 — 11-PR low-risk cleanup: title-language + clarify SSE + upload filename + discoverability + SSE reconnect + gateway image + docker docs)

### Changed
Expand Down
6 changes: 6 additions & 0 deletions api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,12 @@ def _merged_session_messages_for_display(session, cli_messages=None) -> list:
sidecar_messages = list(getattr(session, "messages", []) or [])
if cli_messages:
if sidecar_messages and sidecar_messages != cli_messages:
if len(sidecar_messages) >= len(cli_messages):
return merge_session_messages_append_only(
sidecar_messages,
cli_messages,
truncation_watermark=getattr(session, "truncation_watermark", None),
)
merged_messages = []
seen_message_keys = set()
for msg in sorted(list(cli_messages) + list(sidecar_messages), key=lambda m: (
Expand Down
33 changes: 33 additions & 0 deletions tests/test_issue2472_fork_from_here_messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,39 @@ def test_messaging_merge_helper_dedupes_equivalent_timestamp_formats():
assert [m["content"] for m in merged] == ["hi", "same answer"]


def test_messaging_merge_preserves_longer_sidecar_order_when_timestamps_collapse():
"""A repaired messaging sidecar can preserve order but lose subsecond timestamps.

Re-sorting those messages by ``(timestamp, role, content)`` groups assistant
and tool rows before user rows, making the WebUI look like replies vanished.
"""
session = SimpleNamespace(
messages=[
{"role": "assistant", "content": "prior answer", "timestamp": 100.0},
{"role": "user", "content": "first prompt", "timestamp": 101.0},
{"role": "assistant", "content": "first answer", "timestamp": 101.0},
{"role": "user", "content": "second prompt", "timestamp": 101.0},
{"role": "assistant", "content": "second answer", "timestamp": 101.0},
]
)
cli_messages = [
{"role": "user", "content": "first prompt", "timestamp": 101.1},
{"role": "assistant", "content": "first answer", "timestamp": 101.2},
{"role": "user", "content": "second prompt", "timestamp": 101.3},
{"role": "assistant", "content": "second answer", "timestamp": 101.4},
]

merged = routes._merged_session_messages_for_display(session, cli_messages)

assert [m["content"] for m in merged] == [
"prior answer",
"first prompt",
"first answer",
"second prompt",
"second answer",
]


def test_branch_handler_uses_merged_messaging_messages_for_keep_count():
branch_idx = ROUTES_PY.index('parsed.path == "/api/session/branch":')
block = ROUTES_PY[branch_idx : branch_idx + 2600]
Expand Down
Loading