mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix(EXT-665): push tool_result BEFORE delegation to prevent loss
Root cause: In NewTaskTool.execute(), pushToolResult was called AFTER delegateParentAndOpenChild(), but delegateParentAndOpenChild disposes the parent task. This meant the tool_result was lost, and flushPendingToolResultsToHistory generated a placeholder "interrupted" tool_result instead. Fix: Push the tool_result BEFORE calling delegateParentAndOpenChild. Since the child taskId is not yet known, use a generic message. The actual completion result is injected by reopenParentFromDelegation when the child completes. Also keep the defensive duplicate check in reopenParentFromDelegation for backward compatibility with any existing task histories.
This commit is contained in:
parent
42f2b21113
commit
8083b7d935
2 changed files with 18 additions and 11 deletions
|
|
@ -109,16 +109,23 @@ export class NewTaskTool extends BaseTool<"new_task"> {
|
|||
return
|
||||
}
|
||||
|
||||
// IMPORTANT: Push the tool_result BEFORE delegation, because delegateParentAndOpenChild
|
||||
// disposes the parent task. If we push after, the tool_result is lost and
|
||||
// flushPendingToolResultsToHistory will generate a placeholder "interrupted" tool_result,
|
||||
// causing duplicate tool_results when the child completes (EXT-665).
|
||||
//
|
||||
// The child taskId isn't known yet, so we use a generic message. The actual completion
|
||||
// result will be injected by reopenParentFromDelegation when the child completes.
|
||||
pushToolResult(`Delegating to subtask...`)
|
||||
|
||||
// Delegate parent and open child as sole active task
|
||||
const child = await (provider as any).delegateParentAndOpenChild({
|
||||
await (provider as any).delegateParentAndOpenChild({
|
||||
parentTaskId: task.taskId,
|
||||
message: unescapedMessage,
|
||||
initialTodos: todoItems,
|
||||
mode,
|
||||
})
|
||||
|
||||
// Reflect delegation in tool result (no pause/unpause, no wait)
|
||||
pushToolResult(`Delegated to child task ${child.taskId}`)
|
||||
return
|
||||
} catch (error) {
|
||||
await handleError("creating new task", error)
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ describe("newTaskTool", () => {
|
|||
)
|
||||
|
||||
// Verify side effects
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task"))
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
|
||||
it("should not un-escape single escaped \@", async () => {
|
||||
|
|
@ -280,7 +280,7 @@ describe("newTaskTool", () => {
|
|||
expect(mockStartSubtask).toHaveBeenCalledWith("Test message", [], "code")
|
||||
|
||||
// Should complete successfully
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task"))
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
|
||||
it("should work with todos parameter when provided", async () => {
|
||||
|
|
@ -311,7 +311,7 @@ describe("newTaskTool", () => {
|
|||
"code",
|
||||
)
|
||||
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task"))
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
|
||||
it("should error when mode parameter is missing", async () => {
|
||||
|
|
@ -423,7 +423,7 @@ describe("newTaskTool", () => {
|
|||
expect(mockStartSubtask).toHaveBeenCalledWith("Test message", [], "code")
|
||||
|
||||
// Should complete successfully
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task"))
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
|
||||
it("should REQUIRE todos when VSCode setting is enabled", async () => {
|
||||
|
|
@ -501,7 +501,7 @@ describe("newTaskTool", () => {
|
|||
)
|
||||
|
||||
// Should complete successfully
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task"))
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
|
||||
it("should work with empty todos string when VSCode setting is enabled", async () => {
|
||||
|
|
@ -536,7 +536,7 @@ describe("newTaskTool", () => {
|
|||
expect(mockStartSubtask).toHaveBeenCalledWith("Test message", [], "code")
|
||||
|
||||
// Should complete successfully
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task"))
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
|
||||
it("should check VSCode setting with Package.name configuration key", async () => {
|
||||
|
|
@ -671,7 +671,7 @@ describe("newTaskTool delegation flow", () => {
|
|||
)
|
||||
expect(pauseEvents.length).toBe(0)
|
||||
|
||||
// Assert: tool result reflects delegation
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("Delegated to child task child-1"))
|
||||
// Assert: tool result reflects delegation (pushed BEFORE delegation, so no child ID yet)
|
||||
expect(mockPushToolResult).toHaveBeenCalledWith("Delegating to subtask...")
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue