fix: ensure assistant message ID is always greater than parent user message ID#22988
fix: ensure assistant message ID is always greater than parent user message ID#22988lightrabbit wants to merge 2 commits intoanomalyco:devfrom
Conversation
55edf07 to
8368d5d
Compare
When frontend and backend clocks are out of sync, the assistant message ID\ngenerated by the backend could end up smaller than the parent user message\nID, causing the assistant message to appear above the user message in the\nUI timeline. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Replace MessageID.ascending() with MessageID.ascendingAfter(parentID) at\nevery site where an assistant message is created, ensuring the assistant\nmessage ID is always strictly greater than its parent user message ID.\n\nAdds 6 unit tests covering normal case, same-millisecond, clock skew\n(300ms and 5s), uniqueness, and non-interference with ascending(). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
8368d5d to
2e297fd
Compare
|
Note: this PR addresses the same root issue as #21572 ( #21572 fixes this at the UI/rendering layer — it introduces a This PR fixes this at the ID generation layer — it ensures that assistant message IDs are always lexicographically greater than their parent user message IDs by introducing The two approaches are not mutually exclusive. Fixing the ID generation prevents the ordering violation from ever reaching the UI, while the UI-level sort provides a defense-in-depth against any other sources of misordered messages. Together they provide a more robust solution than either alone. |
Issue for this PR
Closes #15657
Type of change
What does this PR do?
Fixes a bug where the first assistant message after a user message could appear above the user message in the UI timeline, making it invisible to the user.
Root cause: When the frontend generates a user message ID using
Identifier.ascending("message")and sends it to the backend, the backend creates the assistant message usingMessageID.ascending(). Both calls useDate.now()internally. If the frontend and backend clocks are slightly out of sync (even by a few hundred milliseconds), the assistant message ID can end up lexicographically smaller than the user message ID. Since the UI sorts messages by ID string order, the assistant message appears before the user message.Fix: Introduces
Identifier.ascendingAfter(prefix, afterID)which operates in the truncated 48-bit encoding space to guarantee the generated ID is strictly greater thanafterID. All four sites that create assistant messages now useMessageID.ascendingAfter(parentID)instead ofMessageID.ascending().Key detail: the ID encoding only stores the lower 48 bits of
timestamp * 0x1000 + counter, so the comparison must happen in that truncated space rather than against rawDate.now()values.How did you verify your code works?
test/id/identifier.test.tscovering:ascending()monotonicityScreenshots / recordings
N/A (backend logic change)
Checklist