feat(kilo-vscode): allow removing queued messages#8844
feat(kilo-vscode): allow removing queued messages#8844kilo-code-bot[bot] wants to merge 12 commits intomainfrom
Conversation
- wire deleteMessage through the webview messaging system - add DeleteMessageRequest type and handler in KiloProvider - propagate deleteMessage through session context and UI - render trash icon next to queued messages with deleteQueued label - pass onDeleteQueued to UserMessageDisplay and VscodeSessionTurn - update i18n with ui.message.deleteQueued - adjust CSS to align controls in bash-output area
| console.warn("[Kilo New] Cannot delete message: not connected") | ||
| return | ||
| } | ||
| handleMessageRemoved(sessionID, messageID) |
There was a problem hiding this comment.
CRITICAL: Queued deletes cannot succeed while the session is busy
onDeleteQueued is only exposed for queued prompts, which only exist while another turn is still running. The server-side delete route calls SessionPrompt.assertNotBusy(), so this request is rejected every time the button is shown. Because the message is removed optimistically before the request returns, the UI looks successful until the session reloads. This needs either a queue-aware backend delete path or a rollback instead of unconditional local removal.
| <GrowBox animate={!!props.animate} open={!!props.queued}> | ||
| <div data-slot="user-message-queued-indicator"> | ||
| <TextShimmer text={i18n.t("ui.message.queued")} /> | ||
| <Show when={props.onDeleteQueued}> |
There was a problem hiding this comment.
WARNING: Attachment-only queued messages never show the delete action
This button is rendered inside the surrounding Show when={text()} block. PromptInput allows sending prompts with only image/PDF attachments, so those queued messages will never render the queued indicator or delete control and cannot be removed with this feature.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (1 files)
Reviewed by gpt-5.4-20260305 · 432,871 tokens |
| // kilocode_change start | ||
| const messages = await Session.messages({ sessionID: params.sessionID }) | ||
| const target = messages.find((msg) => msg.info.id === params.messageID) | ||
| const newer = messages.find((msg) => msg.info.role === "user" && msg.info.id > params.messageID) |
There was a problem hiding this comment.
CRITICAL: This still rejects the common single-queued-message case
Using has newer user message as the proxy for is queued misses the newest queued prompt, because the last queued user message has no later user after it. In the common case of one active turn plus one queued prompt, newer is undefined, so the route still falls back to assertNotBusy() and the delete fails. It also means the currently active user message would bypass the busy guard whenever another queued prompt exists. The check needs to identify messages after the active turn, not messages with any later user in history.
| const messages = await Session.messages({ sessionID: params.sessionID }) | ||
| const user = messages.filter((msg) => msg.info.role === "user") | ||
| const target = user.find((msg) => msg.info.id === params.messageID) | ||
| const active = user.at(0) |
There was a problem hiding this comment.
CRITICAL: active points at the oldest user message, not the running one
Session.messages() is consumed throughout the app as chronological history, so user.at(0) selects the first prompt in the session. While the session is busy, every later user message now skips assertNotBusy(), including the currently active prompt, so this can allow deleting the turn that is still being processed. The queued/delete check needs to compare against the latest active user turn, not the first user in history.
|
kilo-code-bot: please re-review latest commit 0b22c62. The active turn is now calculated from the first assistant boundary, not user.at(-1). |
Summary
Closes #8832