diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index e8dbffb62d..3468caca92 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -62,6 +62,7 @@ export const globalSettingsSchema = z.object({ alwaysAllowFollowupQuestions: z.boolean().optional(), followupAutoApproveTimeoutMs: z.number().optional(), alwaysAllowUpdateTodoList: z.boolean().optional(), + allowAttemptCompletion: z.boolean().optional(), allowedCommands: z.array(z.string()).optional(), deniedCommands: z.array(z.string()).optional(), commandExecutionTimeout: z.number().optional(), diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap index ced0ede463..4feac40b41 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap @@ -288,25 +288,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap index 90bbc1ae34..a53ee10609 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap @@ -185,25 +185,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap index 9fdf29df77..ef1d5e496e 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap @@ -287,25 +287,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap index 3594c8054f..c323122f92 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap @@ -337,25 +337,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap index 00e7d3f5db..e94afc8ea1 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap @@ -293,25 +293,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap index ced0ede463..4feac40b41 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap @@ -288,25 +288,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap index 72e208ee6a..ca168717ed 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap @@ -341,25 +341,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap index ced0ede463..4feac40b41 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap @@ -288,25 +288,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap index 72aa071ce6..2eb7a967d1 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap @@ -376,25 +376,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap index ced0ede463..4feac40b41 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap @@ -288,25 +288,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap index 83271f47ad..0d23c85940 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap @@ -341,25 +341,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap index 3594c8054f..c323122f92 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap @@ -337,25 +337,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap index ced0ede463..4feac40b41 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap @@ -288,25 +288,6 @@ Example: -## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. -IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. -Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -Usage: - - -Your final result description here - - - -Example: Requesting to attempt completion with a result - - -I've updated the CSS - - - ## switch_mode Description: Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch. Parameters: diff --git a/src/core/prompts/system.ts b/src/core/prompts/system.ts index 3cc327c815..4b48e4586f 100644 --- a/src/core/prompts/system.ts +++ b/src/core/prompts/system.ts @@ -62,6 +62,7 @@ async function generatePrompt( settings?: SystemPromptSettings, todoList?: TodoItem[], modelId?: string, + isOrchestrated?: boolean, ): Promise { if (!context) { throw new Error("Extension context is required for generating system prompt") @@ -108,6 +109,7 @@ ${getToolDescriptionsForMode( settings, enableMcpServerCreation, modelId, + isOrchestrated, )} ${getToolUseGuidelinesSection(codeIndexManager)} @@ -153,6 +155,7 @@ export const SYSTEM_PROMPT = async ( settings?: SystemPromptSettings, todoList?: TodoItem[], modelId?: string, + isOrchestrated?: boolean, ): Promise => { if (!context) { throw new Error("Extension context is required for generating system prompt") @@ -225,5 +228,6 @@ ${customInstructions}` settings, todoList, modelId, + isOrchestrated, ) } diff --git a/src/core/prompts/tools/__tests__/attempt-completion-conditional.spec.ts b/src/core/prompts/tools/__tests__/attempt-completion-conditional.spec.ts new file mode 100644 index 0000000000..28f411024e --- /dev/null +++ b/src/core/prompts/tools/__tests__/attempt-completion-conditional.spec.ts @@ -0,0 +1,275 @@ +import { getToolDescriptionsForMode } from "../index" + +describe("attempt_completion conditional inclusion", () => { + const mockCwd = "/test/path" + const mockSupportsComputerUse = false + + describe("for orchestrated tasks", () => { + it("should always include attempt_completion tool when isOrchestrated is true", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, // codeIndexManager + undefined, // diffStrategy + undefined, // browserViewportSize + undefined, // mcpHub + undefined, // customModes + undefined, // experiments + undefined, // partialReadsEnabled + { allowAttemptCompletion: false }, // settings with allowAttemptCompletion disabled + undefined, // enableMcpServerCreation + undefined, // modelId + true, // isOrchestrated = true + ) + + expect(result).toContain("## attempt_completion") + expect(result).toContain("After each tool use, the user will respond with the result") + }) + + it("should include attempt_completion even when allowAttemptCompletion is false", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: false }, + undefined, + undefined, + true, // isOrchestrated = true + ) + + expect(result).toContain("## attempt_completion") + }) + + it("should include attempt_completion even when allowAttemptCompletion is undefined", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + {}, // settings without allowAttemptCompletion + undefined, + undefined, + true, // isOrchestrated = true + ) + + expect(result).toContain("## attempt_completion") + }) + }) + + describe("for standard (non-orchestrated) tasks", () => { + it("should exclude attempt_completion when isOrchestrated is false and allowAttemptCompletion is false", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: false }, + undefined, + undefined, + false, // isOrchestrated = false + ) + + expect(result).not.toContain("## attempt_completion") + expect(result).not.toContain("After each tool use, the user will respond with the result") + }) + + it("should exclude attempt_completion when isOrchestrated is undefined and allowAttemptCompletion is false", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: false }, + undefined, + undefined, + undefined, // isOrchestrated = undefined (defaults to false) + ) + + expect(result).not.toContain("## attempt_completion") + }) + + it("should exclude attempt_completion by default when allowAttemptCompletion is undefined", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + {}, // settings without allowAttemptCompletion + undefined, + undefined, + false, // isOrchestrated = false + ) + + expect(result).not.toContain("## attempt_completion") + }) + + it("should include attempt_completion when allowAttemptCompletion is explicitly true", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: true }, // explicitly enabled + undefined, + undefined, + false, // isOrchestrated = false + ) + + expect(result).toContain("## attempt_completion") + expect(result).toContain("After each tool use, the user will respond with the result") + }) + + it("should include attempt_completion when isOrchestrated is undefined but allowAttemptCompletion is true", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: true }, + undefined, + undefined, + undefined, // isOrchestrated = undefined + ) + + expect(result).toContain("## attempt_completion") + }) + }) + + describe("edge cases", () => { + it("should handle null settings gracefully", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + null as any, // null settings + undefined, + undefined, + false, + ) + + // Should exclude attempt_completion by default + expect(result).not.toContain("## attempt_completion") + }) + + it("should handle undefined settings gracefully", () => { + const result = getToolDescriptionsForMode( + "code", + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, // undefined settings + undefined, + undefined, + false, + ) + + // Should exclude attempt_completion by default + expect(result).not.toContain("## attempt_completion") + }) + }) + + describe("interaction with different modes", () => { + const testModes = ["code", "architect", "ask", "debug"] + + testModes.forEach((mode) => { + it(`should respect orchestration flag in ${mode} mode`, () => { + // Orchestrated task should include attempt_completion + const orchestratedResult = getToolDescriptionsForMode( + mode, + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: false }, + undefined, + undefined, + true, + ) + + expect(orchestratedResult).toContain("## attempt_completion") + + // Non-orchestrated task with setting disabled should exclude it + const standardResult = getToolDescriptionsForMode( + mode, + mockCwd, + mockSupportsComputerUse, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + { allowAttemptCompletion: false }, + undefined, + undefined, + false, + ) + + expect(standardResult).not.toContain("## attempt_completion") + }) + }) + }) +}) diff --git a/src/core/prompts/tools/index.ts b/src/core/prompts/tools/index.ts index 8b4e90733c..bb3364961e 100644 --- a/src/core/prompts/tools/index.ts +++ b/src/core/prompts/tools/index.ts @@ -74,6 +74,7 @@ export function getToolDescriptionsForMode( settings?: Record, enableMcpServerCreation?: boolean, modelId?: string, + isOrchestrated?: boolean, ): string { const config = getModeConfig(mode, customModes) const args: ToolArgs = { @@ -118,6 +119,13 @@ export function getToolDescriptionsForMode( // Add always available tools ALWAYS_AVAILABLE_TOOLS.forEach((tool) => tools.add(tool)) + // Conditionally include attempt_completion based on task context + // For orchestrated subtasks, always include it + // For standard tasks, check user setting (default is to exclude) + if (!isOrchestrated && settings?.allowAttemptCompletion !== true) { + tools.delete("attempt_completion") + } + // Conditionally exclude codebase_search if feature is disabled or not configured if ( !codeIndexManager || diff --git a/src/core/prompts/types.ts b/src/core/prompts/types.ts index d90b1b821a..5786ae25be 100644 --- a/src/core/prompts/types.ts +++ b/src/core/prompts/types.ts @@ -6,4 +6,5 @@ export interface SystemPromptSettings { todoListEnabled: boolean useAgentRules: boolean newTaskRequireTodos: boolean + allowAttemptCompletion?: boolean } diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 1a5092a375..90f998c204 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -128,6 +128,7 @@ export type TaskOptions = { taskNumber?: number onCreated?: (task: Task) => void initialTodos?: TodoItem[] + isOrchestrated?: boolean } export class Task extends EventEmitter implements TaskLike { @@ -141,6 +142,7 @@ export class Task extends EventEmitter implements TaskLike { readonly parentTask: Task | undefined = undefined readonly taskNumber: number readonly workspacePath: string + readonly isOrchestrated: boolean /** * The mode associated with this task. Persisted across sessions @@ -291,6 +293,7 @@ export class Task extends EventEmitter implements TaskLike { taskNumber = -1, onCreated, initialTodos, + isOrchestrated = false, }: TaskOptions) { super() @@ -312,6 +315,7 @@ export class Task extends EventEmitter implements TaskLike { this.instanceId = crypto.randomUUID().slice(0, 8) this.taskNumber = -1 + this.isOrchestrated = isOrchestrated this.rooIgnoreController = new RooIgnoreController(this.cwd) this.rooProtectedController = new RooProtectedController(this.cwd) @@ -2225,6 +2229,7 @@ export class Task extends EventEmitter implements TaskLike { maxConcurrentFileReads, maxReadFileLine, apiConfiguration, + allowAttemptCompletion, } = state ?? {} return await (async () => { @@ -2258,9 +2263,11 @@ export class Task extends EventEmitter implements TaskLike { newTaskRequireTodos: vscode.workspace .getConfiguration("roo-cline") .get("newTaskRequireTodos", false), + allowAttemptCompletion, }, undefined, // todoList this.api.getModel().id, + this.isOrchestrated, ) })() } diff --git a/src/core/tools/newTaskTool.ts b/src/core/tools/newTaskTool.ts index 6b650cb94e..8beaae4574 100644 --- a/src/core/tools/newTaskTool.ts +++ b/src/core/tools/newTaskTool.ts @@ -122,8 +122,10 @@ export async function newTaskTool( cline.pausedModeSlug = (await provider.getState()).mode ?? defaultModeSlug // Create new task instance first (this preserves parent's current mode in its history) + // Mark this as an orchestrated subtask so it will include attempt_completion tool const newCline = await provider.createTask(unescapedMessage, undefined, cline, { initialTodos: todoItems, + isOrchestrated: true, }) if (!newCline) { pushToolResult(t("tools:newTask.errors.policy_restriction")) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index a7c59560e4..f277a430b1 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -756,6 +756,7 @@ export class ClineProvider | "consecutiveMistakeLimit" | "experiments" | "initialTodos" + | "isOrchestrated" > > = {}, ) { @@ -790,6 +791,7 @@ export class ClineProvider onCreated: this.taskCreationCallback, enableBridge: BridgeOrchestrator.isEnabled(cloudUserInfo, remoteControlEnabled), initialTodos: options.initialTodos, + isOrchestrated: options.isOrchestrated, ...options, }) @@ -1685,6 +1687,7 @@ export class ClineProvider alwaysAllowWriteOutsideWorkspace, alwaysAllowWriteProtected, alwaysAllowExecute, + allowAttemptCompletion, allowedCommands, deniedCommands, alwaysAllowBrowser, @@ -1784,6 +1787,7 @@ export class ClineProvider alwaysAllowWriteOutsideWorkspace: alwaysAllowWriteOutsideWorkspace ?? false, alwaysAllowWriteProtected: alwaysAllowWriteProtected ?? false, alwaysAllowExecute: alwaysAllowExecute ?? false, + allowAttemptCompletion: allowAttemptCompletion ?? false, alwaysAllowBrowser: alwaysAllowBrowser ?? false, alwaysAllowMcp: alwaysAllowMcp ?? false, alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false, @@ -1982,6 +1986,7 @@ export class ClineProvider alwaysAllowWriteOutsideWorkspace: stateValues.alwaysAllowWriteOutsideWorkspace ?? false, alwaysAllowWriteProtected: stateValues.alwaysAllowWriteProtected ?? false, alwaysAllowExecute: stateValues.alwaysAllowExecute ?? false, + allowAttemptCompletion: stateValues.allowAttemptCompletion ?? false, alwaysAllowBrowser: stateValues.alwaysAllowBrowser ?? false, alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false, alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false, diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 65fe181859..c50db538a0 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -221,6 +221,7 @@ export type ExtensionState = Pick< | "alwaysAllowSubtasks" | "alwaysAllowExecute" | "alwaysAllowUpdateTodoList" + | "allowAttemptCompletion" | "allowedCommands" | "deniedCommands" | "allowedMaxRequests" diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index e2df805340..9dfbc1fc30 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -45,6 +45,7 @@ export interface WebviewMessage { | "alwaysAllowExecute" | "alwaysAllowFollowupQuestions" | "alwaysAllowUpdateTodoList" + | "allowAttemptCompletion" | "followupAutoApproveTimeoutMs" | "webviewDidLaunch" | "newTask" diff --git a/webview-ui/src/components/chat/AutoApproveMenu.tsx b/webview-ui/src/components/chat/AutoApproveMenu.tsx index 8961fc7f5d..5f1170d5f8 100644 --- a/webview-ui/src/components/chat/AutoApproveMenu.tsx +++ b/webview-ui/src/components/chat/AutoApproveMenu.tsx @@ -21,6 +21,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { autoApprovalEnabled, setAutoApprovalEnabled, alwaysApproveResubmit, + allowAttemptCompletion, setAlwaysAllowReadOnly, setAlwaysAllowWrite, setAlwaysAllowExecute, @@ -31,19 +32,21 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { setAlwaysApproveResubmit, setAlwaysAllowFollowupQuestions, setAlwaysAllowUpdateTodoList, + setAllowAttemptCompletion, } = useExtensionState() const { t } = useAppTranslation() const baseToggles = useAutoApprovalToggles() - // AutoApproveMenu needs alwaysApproveResubmit in addition to the base toggles + // AutoApproveMenu needs alwaysApproveResubmit and allowAttemptCompletion in addition to the base toggles const toggles = useMemo( () => ({ ...baseToggles, alwaysApproveResubmit: alwaysApproveResubmit, + allowAttemptCompletion: allowAttemptCompletion, }), - [baseToggles, alwaysApproveResubmit], + [baseToggles, alwaysApproveResubmit, allowAttemptCompletion], ) const { hasEnabledOptions, effectiveAutoApprovalEnabled } = useAutoApprovalState(toggles, autoApprovalEnabled) @@ -84,6 +87,9 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { case "alwaysAllowUpdateTodoList": setAlwaysAllowUpdateTodoList(value) break + case "allowAttemptCompletion": + setAllowAttemptCompletion(value) + break } // Check if we need to update the master auto-approval state @@ -119,6 +125,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { setAlwaysApproveResubmit, setAlwaysAllowFollowupQuestions, setAlwaysAllowUpdateTodoList, + setAllowAttemptCompletion, setAutoApprovalEnabled, ], ) diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx index 5ce44c747d..4e049f44df 100644 --- a/webview-ui/src/components/settings/AutoApproveSettings.tsx +++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx @@ -30,6 +30,7 @@ type AutoApproveSettingsProps = HTMLAttributes & { alwaysAllowExecute?: boolean alwaysAllowFollowupQuestions?: boolean alwaysAllowUpdateTodoList?: boolean + allowAttemptCompletion?: boolean followupAutoApproveTimeoutMs?: number allowedCommands?: string[] allowedMaxRequests?: number | undefined @@ -55,6 +56,7 @@ type AutoApproveSettingsProps = HTMLAttributes & { | "allowedMaxCost" | "deniedCommands" | "alwaysAllowUpdateTodoList" + | "allowAttemptCompletion" > } @@ -74,6 +76,7 @@ export const AutoApproveSettings = ({ alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs = 60000, alwaysAllowUpdateTodoList, + allowAttemptCompletion, allowedCommands, allowedMaxRequests, allowedMaxCost, @@ -166,6 +169,7 @@ export const AutoApproveSettings = ({ alwaysAllowExecute={alwaysAllowExecute} alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions} alwaysAllowUpdateTodoList={alwaysAllowUpdateTodoList} + allowAttemptCompletion={allowAttemptCompletion} onToggle={(key, value) => setCachedStateField(key, value)} /> diff --git a/webview-ui/src/components/settings/AutoApproveToggle.tsx b/webview-ui/src/components/settings/AutoApproveToggle.tsx index e6540f3d89..89cd42337c 100644 --- a/webview-ui/src/components/settings/AutoApproveToggle.tsx +++ b/webview-ui/src/components/settings/AutoApproveToggle.tsx @@ -16,6 +16,7 @@ type AutoApproveToggles = Pick< | "alwaysAllowExecute" | "alwaysAllowFollowupQuestions" | "alwaysAllowUpdateTodoList" + | "allowAttemptCompletion" > export type AutoApproveSetting = keyof AutoApproveToggles @@ -99,6 +100,13 @@ export const autoApproveSettingsConfig: Record { alwaysAllowExecute: true, alwaysAllowFollowupQuestions: false, alwaysAllowUpdateTodoList: true, + allowAttemptCompletion: false, onToggle: mockOnToggle, } diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index bd335d7b2d..0007439d55 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -145,6 +145,8 @@ export interface ExtensionStateContextType extends ExtensionState { routerModels?: RouterModels alwaysAllowUpdateTodoList?: boolean setAlwaysAllowUpdateTodoList: (value: boolean) => void + allowAttemptCompletion?: boolean + setAllowAttemptCompletion: (value: boolean) => void includeDiagnosticMessages?: boolean setIncludeDiagnosticMessages: (value: boolean) => void maxDiagnosticMessages?: number @@ -250,6 +252,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode }, codebaseIndexModels: { ollama: {}, openai: {} }, alwaysAllowUpdateTodoList: true, + allowAttemptCompletion: false, includeDiagnosticMessages: true, maxDiagnosticMessages: 50, }) @@ -304,6 +307,13 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode if ((newState as any).followupAutoApproveTimeoutMs !== undefined) { setFollowupAutoApproveTimeoutMs((newState as any).followupAutoApproveTimeoutMs) } + // Update allowAttemptCompletion if present in state message + if ((newState as any).allowAttemptCompletion !== undefined) { + setState((prevState) => ({ + ...prevState, + allowAttemptCompletion: (newState as any).allowAttemptCompletion, + })) + } // Update includeTaskHistoryInEnhance if present in state message if ((newState as any).includeTaskHistoryInEnhance !== undefined) { setIncludeTaskHistoryInEnhance((newState as any).includeTaskHistoryInEnhance) @@ -514,6 +524,10 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setAlwaysAllowUpdateTodoList: (value) => { setState((prevState) => ({ ...prevState, alwaysAllowUpdateTodoList: value })) }, + allowAttemptCompletion: state.allowAttemptCompletion, + setAllowAttemptCompletion: (value) => { + setState((prevState) => ({ ...prevState, allowAttemptCompletion: value })) + }, includeDiagnosticMessages: state.includeDiagnosticMessages, setIncludeDiagnosticMessages: (value) => { setState((prevState) => ({ ...prevState, includeDiagnosticMessages: value })) diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 33fba24b8e..48b9ac6b79 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -195,6 +195,10 @@ "label": "Todo", "description": "Automatically update the to-do list without requiring approval" }, + "allowAttemptCompletion": { + "label": "Completion", + "description": "Allow Roo to use the attempt_completion tool to end tasks. When disabled, tasks continue until you manually stop them" + }, "apiRequestLimit": { "title": "Max Count", "unlimited": "Unlimited"