mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: add ability to edit subtask instructions
- Added edit button to subtask instructions in orchestrator mode - Users can now modify subtask content before approval - Reduces unnecessary LLM calls and token usage - Implements inline editing similar to user message editing Fixes #9593
This commit is contained in:
parent
3c05cae722
commit
aa35136558
3 changed files with 137 additions and 4 deletions
|
|
@ -1542,6 +1542,56 @@ export const webviewMessageHandler = async (
|
|||
}
|
||||
break
|
||||
}
|
||||
case "submitEditedSubtask": {
|
||||
// Handle editing of subtask instructions
|
||||
const currentCline = provider.getCurrentTask()
|
||||
if (currentCline && message.messageTs && message.editedSubtaskContent) {
|
||||
// Find the message with the newTask tool
|
||||
const messageIndex = currentCline.clineMessages.findIndex(
|
||||
(msg: ClineMessage) => msg.ts === message.messageTs,
|
||||
)
|
||||
|
||||
if (messageIndex !== -1) {
|
||||
const targetMessage = currentCline.clineMessages[messageIndex]
|
||||
|
||||
// Parse the tool content to update it
|
||||
if (targetMessage.ask === "tool" && targetMessage.text) {
|
||||
try {
|
||||
const tool = JSON.parse(targetMessage.text)
|
||||
if (tool.tool === "newTask") {
|
||||
// Update the content with the edited subtask instructions
|
||||
tool.content = message.editedSubtaskContent
|
||||
|
||||
// Update the message with the new content
|
||||
currentCline.clineMessages[messageIndex].text = JSON.stringify(tool)
|
||||
|
||||
// Save the updated messages
|
||||
await saveTaskMessages({
|
||||
messages: currentCline.clineMessages,
|
||||
taskId: currentCline.taskId,
|
||||
globalStoragePath: provider.contextProxy.globalStorageUri.fsPath,
|
||||
})
|
||||
|
||||
// Update the UI to reflect the changes
|
||||
await provider.postStateToWebview()
|
||||
|
||||
// Now approve the subtask with the edited content
|
||||
// This simulates the user clicking "Approve" after editing
|
||||
currentCline.handleWebviewAskResponse("yesButtonClicked")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating subtask instructions:", error)
|
||||
vscode.window.showErrorMessage(
|
||||
t("common:errors.message.error_editing_subtask", {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case "hasOpenedModeSelector":
|
||||
await updateGlobalState("hasOpenedModeSelector", message.bool ?? true)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ export interface WebviewMessage {
|
|||
| "deleteMessageConfirm"
|
||||
| "submitEditedMessage"
|
||||
| "editMessageConfirm"
|
||||
| "submitEditedSubtask"
|
||||
| "enableMcpServerCreation"
|
||||
| "remoteControlEnabled"
|
||||
| "taskSyncEnabled"
|
||||
|
|
@ -181,6 +182,7 @@ export interface WebviewMessage {
|
|||
| "requestClaudeCodeRateLimits"
|
||||
text?: string
|
||||
editedMessageContent?: string
|
||||
editedSubtaskContent?: string
|
||||
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"
|
||||
disabled?: boolean
|
||||
context?: string
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ export const ChatRowContent = ({
|
|||
const [editMode, setEditMode] = useState<Mode>(mode || "code")
|
||||
const [editImages, setEditImages] = useState<string[]>([])
|
||||
|
||||
// State for editing subtask instructions
|
||||
const [isEditingSubtask, setIsEditingSubtask] = useState(false)
|
||||
const [editedSubtaskContent, setEditedSubtaskContent] = useState("")
|
||||
|
||||
// Handle message events for image selection during edit mode
|
||||
useEffect(() => {
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
|
|
@ -792,6 +796,30 @@ export const ChatRowContent = ({
|
|||
</>
|
||||
)
|
||||
case "newTask":
|
||||
// Handle edit button click for subtask
|
||||
const handleEditSubtaskClick = () => {
|
||||
setIsEditingSubtask(true)
|
||||
setEditedSubtaskContent(tool.content || "")
|
||||
}
|
||||
|
||||
// Handle cancel edit for subtask
|
||||
const handleCancelEditSubtask = () => {
|
||||
setIsEditingSubtask(false)
|
||||
setEditedSubtaskContent(tool.content || "")
|
||||
}
|
||||
|
||||
// Handle save edit for subtask
|
||||
const handleSaveEditSubtask = () => {
|
||||
setIsEditingSubtask(false)
|
||||
// Send edited subtask content to backend
|
||||
vscode.postMessage({
|
||||
type: "submitEditedSubtask",
|
||||
messageTs: message.ts,
|
||||
editedSubtaskContent: editedSubtaskContent,
|
||||
mode: tool.mode,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={headerStyle}>
|
||||
|
|
@ -805,6 +833,7 @@ export const ChatRowContent = ({
|
|||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="group"
|
||||
style={{
|
||||
marginTop: "4px",
|
||||
backgroundColor: "var(--vscode-badge-background)",
|
||||
|
|
@ -812,6 +841,7 @@ export const ChatRowContent = ({
|
|||
borderRadius: "4px 4px 0 0",
|
||||
overflow: "hidden",
|
||||
marginBottom: "2px",
|
||||
position: "relative",
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
|
|
@ -823,13 +853,64 @@ export const ChatRowContent = ({
|
|||
color: "var(--vscode-badge-foreground)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "6px",
|
||||
justifyContent: "space-between",
|
||||
}}>
|
||||
<span className="codicon codicon-arrow-right"></span>
|
||||
{t("chat:subtasks.newTaskContent")}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "6px" }}>
|
||||
<span className="codicon codicon-arrow-right"></span>
|
||||
{t("chat:subtasks.newTaskContent")}
|
||||
</div>
|
||||
{/* Edit button for subtask instructions */}
|
||||
{message.type === "ask" && !isStreaming && !isEditingSubtask && (
|
||||
<div
|
||||
className="cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleEditSubtaskClick()
|
||||
}}
|
||||
title={t("chat:editSubtaskInstructions")}
|
||||
style={{
|
||||
padding: "2px 4px",
|
||||
borderRadius: "3px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "4px",
|
||||
}}>
|
||||
<Edit className="w-4 h-4" aria-label="Edit subtask instructions" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ padding: "12px 16px", backgroundColor: "var(--vscode-editor-background)" }}>
|
||||
<MarkdownBlock markdown={tool.content} />
|
||||
{isEditingSubtask ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<textarea
|
||||
value={editedSubtaskContent}
|
||||
onChange={(e) => setEditedSubtaskContent(e.target.value)}
|
||||
className="w-full p-2 border border-vscode-input-border bg-vscode-input-background text-vscode-input-foreground rounded"
|
||||
style={{
|
||||
minHeight: "200px",
|
||||
resize: "vertical",
|
||||
fontFamily: "var(--vscode-editor-font-family)",
|
||||
fontSize: "var(--vscode-editor-font-size)",
|
||||
}}
|
||||
placeholder={t("chat:editSubtaskInstructions.placeholder")}
|
||||
autoFocus
|
||||
/>
|
||||
<div className="flex gap-2 justify-end">
|
||||
<button
|
||||
onClick={handleCancelEditSubtask}
|
||||
className="px-3 py-1 rounded bg-vscode-button-secondaryBackground text-vscode-button-secondaryForeground hover:bg-vscode-button-secondaryHoverBackground">
|
||||
{t("chat:cancel")}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSaveEditSubtask}
|
||||
className="px-3 py-1 rounded bg-vscode-button-background text-vscode-button-foreground hover:bg-vscode-button-hoverBackground">
|
||||
{t("chat:save")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<MarkdownBlock markdown={tool.content} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue