diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index af5f9925c3..4a7b3da924 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1530,12 +1530,54 @@ export const webviewMessageHandler = async ( message.value && message.editedMessageContent ) { - await handleMessageModificationsOperation( - message.value, - "edit", - message.editedMessageContent, - message.images, - ) + // Check if this is an AI message edit + const currentCline = provider.getCurrentTask() + if (currentCline) { + const messageIndex = currentCline.clineMessages.findIndex( + (msg: ClineMessage) => msg.ts === message.value, + ) + if (messageIndex !== -1) { + const targetMessage = currentCline.clineMessages[messageIndex] + + // If this is an AI text message, handle it differently + if (targetMessage.say === "text" && !targetMessage.partial) { + // For AI messages, we need to update the message directly + // and update the API conversation history + targetMessage.text = message.editedMessageContent + if (message.images) { + targetMessage.images = message.images + } + + // Save the updated messages + await saveTaskMessages({ + messages: currentCline.clineMessages, + taskId: currentCline.taskId, + globalStoragePath: provider.contextProxy.globalStorageUri.fsPath, + }) + + // Also update the API conversation history if this message exists there + const apiIndex = currentCline.apiConversationHistory.findIndex( + (msg: ApiMessage) => msg.ts === message.value, + ) + if (apiIndex !== -1) { + // Update the content for assistant messages in API history + // Note: ApiMessage type doesn't support images property directly + currentCline.apiConversationHistory[apiIndex].content = message.editedMessageContent + } + + // Update the UI to reflect the changes + await provider.postStateToWebview() + } else { + // For user feedback messages, use the existing edit flow + await handleMessageModificationsOperation( + message.value, + "edit", + message.editedMessageContent, + message.images, + ) + } + } + } } break } diff --git a/tmp/Roo-Code b/tmp/Roo-Code new file mode 160000 index 0000000000..8111da66bd --- /dev/null +++ b/tmp/Roo-Code @@ -0,0 +1 @@ +Subproject commit 8111da66bd59ca8d500e5eae23b24a0419ed7345 diff --git a/tmp/Roo-Code-rc b/tmp/Roo-Code-rc new file mode 160000 index 0000000000..7b7bb49572 --- /dev/null +++ b/tmp/Roo-Code-rc @@ -0,0 +1 @@ +Subproject commit 7b7bb49572975c4aeff2381a0ebea99b3aa4542c diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 26bc71074a..87feca47c5 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -1118,19 +1118,54 @@ export const ChatRowContent = ({ return null // we should never see this message type case "text": return ( -
+
{t("chat:text.rooSaid")} + {/* Add edit button for AI responses */} + {!isStreaming && !message.partial && editable && ( +
{ + e.stopPropagation() + handleEditClick() + }}> + +
+ )}
- - {message.images && message.images.length > 0 && ( -
- {message.images.map((image, index) => ( - - ))} + {isEditing ? ( +
+
+ ) : ( + <> + + {message.images && message.images.length > 0 && ( +
+ {message.images.map((image, index) => ( + + ))} +
+ )} + )}
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index d358c68f1c..f34ef14075 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1542,22 +1542,27 @@ const ChatViewComponent: React.ForwardRefRenderFunction { - let tool: any = {} - try { - tool = JSON.parse(messageOrGroup.text || "{}") - } catch (_) { - if (messageOrGroup.text?.includes("updateTodoList")) { - tool = { tool: "updateTodoList" } + // Allow editing of user feedback messages + messageOrGroup.say === "user_feedback" || + // Allow editing of AI text responses + (messageOrGroup.say === "text" && !messageOrGroup.partial) || + // Allow editing of updateTodoList tool messages when buttons are enabled + (messageOrGroup.type === "ask" && + messageOrGroup.ask === "tool" && + (() => { + let tool: any = {} + try { + tool = JSON.parse(messageOrGroup.text || "{}") + } catch (_) { + if (messageOrGroup.text?.includes("updateTodoList")) { + tool = { tool: "updateTodoList" } + } } - } - if (tool.tool === "updateTodoList" && alwaysAllowUpdateTodoList) { - return false - } - return tool.tool === "updateTodoList" && enableButtons && !!primaryButtonText - })() + if (tool.tool === "updateTodoList" && alwaysAllowUpdateTodoList) { + return false + } + return tool.tool === "updateTodoList" && enableButtons && !!primaryButtonText + })()) } /> )