Repository navigation
fix(chat): reconcile and dismiss browser-local unsent submissions - #1970
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Browser-local failed submissions can remain appended to an otherwise valid server conversation, with no way to dismiss individual records from the transcript. In the reported case, a regular Chrome profile showed two identical-looking Not sent user bubbles, while an embedded browser opening the same session showed only server history. The two recovered bubbles had distinct temporary message IDs: they were separate pending submissions, rather than evidence of duplicate server rows.
Pending submissions are stored in localStorage, with sessionStorage and legacy-format fallbacks. Browser profiles have separate storage, and clearing the HTTP cache does not clear these recovery records.
Several gaps made this confusing and persistent:
Reproduction
The fix provides explicit recovery actions and consistent reconciliation; browser-local drafts still belong to their originating browser profile.
Changes
Data preservation
Equal text is not sufficient proof of delivery. Distinct submission IDs continue to be treated independently, even if their contents are identical. Delivery reconciliation uses client_submission_id, and retry continues to use the existing request snapshot and submission identity.
Discard is limited to local failed submissions and is blocked while streaming. It does not call the server message-deletion endpoint. Existing per-record tombstones also prevent discarded legacy records or fallback copies from reappearing. Session cleanup preserves other sessions' records and clears any associated draft-source binding.
Validation
The changes add 16 regression cases covering individual disposal of identical pending submissions, legacy tombstones, draft recovery, selected-path continuity, storage failure, streaming guards, causal acceptance, runtime status restoration, and session-scoped deletion cleanup.
Not run: production build and the complete pre-commit suite (pre-commit is not installed in this environment).
Scope
This PR addresses browser-local unsent-message recovery and its lifecycle. It does not claim to resolve the separately reported issue where deleting conversation A appears to affect conversation B; that requires its own reproduction and investigation.
Modules affected
Checklist