fix(ui): restrict edit to latest user message (#747)
fix(ui): restrict edit to latest user message (#747) Only the latest user turn shows the pencil/edit affordance. Older user messages remain read-only (copy + timestamp still work). Avoids the misleading implication that historical messages can be lightly edited when the actual action truncates the session and restarts the conversation from that point. Closes #744 Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
# Hermes Web UI -- Changelog
|
||||
|
||||
## [v0.50.97] — 2026-04-20
|
||||
|
||||
### Fixed
|
||||
- **Only the latest user message can be edited** — older user turns no longer show the pencil/edit affordance. This avoids implying that historical turns can be lightly edited when the actual action truncates the session and restarts the conversation from that point. (Closes #744)
|
||||
|
||||
## [v0.50.96] — 2026-04-19
|
||||
|
||||
### Added
|
||||
|
||||
10
static/ui.js
10
static/ui.js
@@ -1409,6 +1409,13 @@ function renderMessages(){
|
||||
if(msgContent(m)||m.attachments?.length||(m.role==='assistant'&&(hasTc||hasTu||_messageHasReasoningPayload(m)))) visWithIdx.push({m,rawIdx});
|
||||
rawIdx++;
|
||||
}
|
||||
let lastUserRawIdx=-1;
|
||||
for(let i=visWithIdx.length-1;i>=0;i--){
|
||||
if(visWithIdx[i].m&&visWithIdx[i].m.role==='user'){
|
||||
lastUserRawIdx=visWithIdx[i].rawIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const insertionAnchor=_compressionAnchorIndex(
|
||||
visWithIdx,
|
||||
compressionState ? compressionState.anchorMessageKey : sessionCompressionAnchorKey,
|
||||
@@ -1471,7 +1478,8 @@ function renderMessages(){
|
||||
filesHtml=`<div class="msg-files">${m.attachments.map(f=>`<div class="msg-file-badge">${li('paperclip',12)} ${esc(f)}</div>`).join('')}</div>`;
|
||||
}
|
||||
const bodyHtml = isUser ? esc(String(content)).replace(/\n/g,'<br>') : renderMd(_stripXmlToolCallsDisplay(String(content)));
|
||||
const editBtn = isUser ? `<button class="msg-action-btn" title="${t('edit_message')}" onclick="editMessage(this)">${li('pencil',13)}</button>` : '';
|
||||
const isEditableUser=isUser&&rawIdx===lastUserRawIdx;
|
||||
const editBtn = isEditableUser ? `<button class="msg-action-btn" title="${t('edit_message')}" onclick="editMessage(this)">${li('pencil',13)}</button>` : '';
|
||||
const retryBtn = isLastAssistant ? `<button class="msg-action-btn" title="${t('regenerate')}" onclick="regenerateResponse(this)">${li('rotate-ccw',13)}</button>` : '';
|
||||
const copyBtn = `<button class="msg-copy-btn msg-action-btn" title="${t('copy')}" onclick="copyMsg(this)">${li('copy',13)}</button>`;
|
||||
const tsVal=m._ts||m.timestamp;
|
||||
|
||||
9
tests/test_issue744.py
Normal file
9
tests/test_issue744.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import pathlib
|
||||
|
||||
|
||||
def test_only_latest_user_message_gets_edit_button():
|
||||
src = pathlib.Path("static/ui.js").read_text(encoding="utf-8")
|
||||
assert "let lastUserRawIdx=-1;" in src
|
||||
assert "const isEditableUser=isUser&&rawIdx===lastUserRawIdx;" in src
|
||||
assert "const editBtn = isEditableUser ?" in src
|
||||
|
||||
Reference in New Issue
Block a user