fix(session): follow-up message overwrites historical user message text#256
fix(session): follow-up message overwrites historical user message text#256oss-agent-shin wants to merge 1 commit into
Conversation
When a session has existing history, thread.messages already contains prior user messages seeded from the /message endpoint. sentUsers starts empty, so sentUsers[0] (the first new follow-up) was positionally mapped to the first historical user message — replacing its text in the UI — instead of being appended as a fresh entry at the end. Root cause: the sentUsers→thread position mapping counted ALL user messages starting from index 0, with no awareness of how many pre-existed. Fix: capture sentUserBaseRef.current = count of user messages already in the thread at the moment the very first send fires. The messages memo skips that many historical user messages before applying sentUsers overrides, so sentUsers[0] always maps to the first new user message slot. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR fixes a positional off-by-one in the
Confidence Score: 4/5Safe to merge; the fix is targeted and well-reasoned, with only a minor missing The core mechanism is correct — src/app/sessions/[sid]/view.tsx — specifically the
|
| Filename | Overview |
|---|---|
| src/app/sessions/[sid]/view.tsx | Introduces sentUserBaseRef to offset the sentUsers → thread.messages mapping past historical user messages; logic is sound and correctly reset on session change, with one minor missing dependency in the handleSend useCallback array. |
Comments Outside Diff (1)
-
src/app/sessions/[sid]/view.tsx, line 531 (link)sentUsersis read insidehandleSend(thesentUsers.length === 0guard is the entire mechanism of this fix) but is absent from theuseCallbackdependency array. In practice the callback is recreated after every send becausedraftis always reset to"", so the stale-closure window is very short and the check behaves correctly today. However, the missing dep means any future change that allowsdraftto stay unchanged between two sends (e.g. a "Send on click" flow with no text, only attachments already present from a prior cleared state) could causesentUsers.lengthto be read as0again on the second send, silently re-settingsentUserBaseRef.currentand reintroducing the original bug. AddingsentUsersto the deps array makes the guarantee explicit and will also silence anyexhaustive-depslint rule.
Reviews (1): Last reviewed commit: "fix(session): follow-up message overwrit..." | Re-trigger Greptile
Bug
Sending a follow-up message in a session that already has prior conversation history caused the follow-up text to silently replace the first historical user message in the thread instead of appearing as a new entry.
Root cause —
src/app/sessions/[sid]/view.tsx,messagesuseMemo:The
sentUsers→thread.messagesmapping was purely positional:sentUsers[u]was applied to theu-th user message in the thread, starting from index 0. When a session has existing history,thread.messagesalready contains past user messages on load, andsentUsersstarts empty. The moment the user sends a follow-up:sentUsers = [{text: "follow up"}]thread.messagesstill has[user1_historical, asst1_historical]sentUsers[0]→user1_historical, replacing its textwhileappend loop didn't fire becauseu === sentUsers.lengthafter the for-loop)Fix
Capture
sentUserBaseRef.current— the number of user messages already in the thread when the very first send happens in a page session. The memo then skips that many historical user messages before it starts applyingsentUsersoverrides.sentUsers[0]now maps to the first new user message slot, not to a historical one.The ref is:
setSentUsers), so it's already in place when the memo re-runs after the state update0whensessionIdchanges (same effect as the existingsetSentUsers([])reset)Test plan
🤖 Generated with Claude Code