From a6e94f99b14f442b890404251c504b2ffc71050d Mon Sep 17 00:00:00 2001 From: A Rai Date: Wed, 25 Jun 2025 00:35:08 +1200 Subject: [PATCH 1/3] feat: Implement pre-flight PowerShell syntax checker Implements the pre-flight syntax checker for all commands executed by Roo in a PowerShell environment, as specified in BRIEF_001_Roo_Syntax_Checker. This adds a validation step that writes the command to a temporary file, checks for diagnostics from the PowerShell extension, and blocks execution if any errors are found, returning the error to the user. This addresses the systemic flaw of Roo repeatedly using incorrect syntax. --- src/integrations/terminal/TerminalProcess.ts | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/integrations/terminal/TerminalProcess.ts b/src/integrations/terminal/TerminalProcess.ts index eb0424fe8df..957cd8f51f8 100644 --- a/src/integrations/terminal/TerminalProcess.ts +++ b/src/integrations/terminal/TerminalProcess.ts @@ -9,6 +9,7 @@ import stripAnsi from "strip-ansi" import * as vscode from "vscode" import { inspect } from "util" +import { TextEncoder } from "util" import type { ExitCodeDetails } from "./types" import { BaseTerminalProcess } from "./BaseTerminalProcess" @@ -115,6 +116,12 @@ export class TerminalProcess extends BaseTerminalProcess { (defaultWindowsShellProfile as string)?.toLowerCase().includes("powershell")) if (isPowerShell) { + const syntaxError = await this.validatePowerShellSyntax(command) + if (syntaxError) { + this.emit("completed", syntaxError) + this.continue() + return + } let commandToExecute = command // Only add the PowerShell counter workaround if enabled @@ -464,4 +471,38 @@ export class TerminalProcess extends BaseTerminalProcess { return match133 !== undefined ? match133 : match633 } + private async validatePowerShellSyntax(command: string): Promise { + const tempFileName = `temp_check_${Date.now()}.ps1` + const tempFileUri = vscode.Uri.joinPath( + vscode.Uri.file(this.terminal.getCurrentWorkingDirectory()), + tempFileName, + ) + const encoder = new TextEncoder() + + try { + await vscode.workspace.fs.writeFile(tempFileUri, encoder.encode(command)) + + // Wait for the PowerShell extension to analyze the file + await new Promise((resolve) => setTimeout(resolve, 500)) + + const diagnostics = vscode.languages.getDiagnostics(tempFileUri) + const errors = diagnostics.filter((d) => d.severity === vscode.DiagnosticSeverity.Error) + + if (errors.length > 0) { + const errorMessages = errors.map((e) => `- ${e.message}`).join("\n") + return `PowerShell Syntax Error Detected:\n${errorMessages}` + } + + return null + } catch (e) { + console.error("Error during PowerShell syntax validation:", e) + // Don't block execution if validation fails + return null + } finally { + // Clean up the temporary file + await vscode.workspace.fs.delete(tempFileUri, { useTrash: false }).catch((e) => { + console.error(`Failed to delete temp file ${tempFileUri.fsPath}:`, e) + }) + } + } } From 069bc5167806efefb11d189fafbeb457e9cb7f43 Mon Sep 17 00:00:00 2001 From: A Rai Date: Wed, 25 Jun 2025 00:38:53 +1200 Subject: [PATCH 2/3] fix: Correct TypeScript error in syntax validation This commit fixes a TypeScript error in the new PowerShell syntax validation logic. The original implementation used a .catch() on a Thenable, which is not supported. This has been replaced with a standard ry...catch block to correctly handle potential errors during temporary file deletion. --- src/integrations/terminal/TerminalProcess.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/integrations/terminal/TerminalProcess.ts b/src/integrations/terminal/TerminalProcess.ts index 957cd8f51f8..1fc451e2d3e 100644 --- a/src/integrations/terminal/TerminalProcess.ts +++ b/src/integrations/terminal/TerminalProcess.ts @@ -500,9 +500,11 @@ export class TerminalProcess extends BaseTerminalProcess { return null } finally { // Clean up the temporary file - await vscode.workspace.fs.delete(tempFileUri, { useTrash: false }).catch((e) => { + try { + await vscode.workspace.fs.delete(tempFileUri, { useTrash: false }) + } catch (e) { console.error(`Failed to delete temp file ${tempFileUri.fsPath}:`, e) - }) + } } } } From 2b95b39940371cd5d32ccbd71130a96f361b5672 Mon Sep 17 00:00:00 2001 From: A Rai Date: Wed, 25 Jun 2025 00:50:32 +1200 Subject: [PATCH 3/3] feat: Deploy updated prompt generation code --- src/core/prompts/sections/rules.ts | 6 +++++- src/integrations/terminal/TerminalProcess.ts | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/core/prompts/sections/rules.ts b/src/core/prompts/sections/rules.ts index 3b2e9920857..d6e0822a0b6 100644 --- a/src/core/prompts/sections/rules.ts +++ b/src/core/prompts/sections/rules.ts @@ -65,11 +65,15 @@ export function getRulesSection( RULES +==== CRITICAL RULES ==== +- **Shell Command Syntax:** ALL commands sent to \`execute_command\` MUST use syntax compatible with the specified "Default Shell" in the SYSTEM INFORMATION section. For Windows (PowerShell), use semicolons (;) to chain commands (e.g., \`cd C:/Users/matrix/Documents/project-alpha-os-docs; npm install\`). Do NOT use \`&&\` as it will fail. This is a critical, non-negotiable requirement. +======================== + - The project base directory is: ${cwd.toPosix()} - All file paths must be relative to this directory. However, commands may change directories in terminals, so respect working directory specified by the response to . - You cannot \`cd\` into a different directory to complete a task. You are stuck operating from '${cwd.toPosix()}', so be sure to pass in the correct 'path' parameter when using tools that require a path. - Do not use the ~ character or $HOME to refer to the home directory. -- Before using the execute_command tool, you must first think about the SYSTEM INFORMATION context provided to understand the user's environment and tailor your commands to ensure they are compatible with their system. You must also consider if the command you need to run should be executed in a specific directory outside of the current working directory '${cwd.toPosix()}', and if so prepend with \`cd\`'ing into that directory && then executing the command (as one command since you are stuck operating from '${cwd.toPosix()}'). For example, if you needed to run \`npm install\` in a project outside of '${cwd.toPosix()}', you would need to prepend with a \`cd\` i.e. pseudocode for this would be \`cd (path to project) && (command, in this case npm install)\`. +- Before using the execute_command tool, you must first think about the SYSTEM INFORMATION context provided to understand the user's environment and tailor your commands to ensure they are compatible with their system. ${codebaseSearchRule}- When using the search_files tool${isCodebaseSearchAvailable ? " (after codebase_search)" : ""}, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use read_file to examine the full context of interesting matches before using ${diffStrategy ? "apply_diff or write_to_file" : "write_to_file"} to make informed changes. - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser. ${getEditingInstructions(diffStrategy)} diff --git a/src/integrations/terminal/TerminalProcess.ts b/src/integrations/terminal/TerminalProcess.ts index 1fc451e2d3e..7050b45258c 100644 --- a/src/integrations/terminal/TerminalProcess.ts +++ b/src/integrations/terminal/TerminalProcess.ts @@ -478,12 +478,26 @@ export class TerminalProcess extends BaseTerminalProcess { tempFileName, ) const encoder = new TextEncoder() + let listener: vscode.Disposable try { await vscode.workspace.fs.writeFile(tempFileUri, encoder.encode(command)) // Wait for the PowerShell extension to analyze the file - await new Promise((resolve) => setTimeout(resolve, 500)) + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + listener.dispose() + reject(new Error("Timeout waiting for PowerShell diagnostics")) + }, 5000) // 5 second timeout + + listener = vscode.languages.onDidChangeDiagnostics((e) => { + if (e.uris.some((uri) => uri.fsPath === tempFileUri.fsPath)) { + clearTimeout(timeout) + listener.dispose() + resolve() + } + }) + }) const diagnostics = vscode.languages.getDiagnostics(tempFileUri) const errors = diagnostics.filter((d) => d.severity === vscode.DiagnosticSeverity.Error)