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 eb0424fe8df..7050b45258c 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,54 @@ 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() + 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, 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) + + 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 + try { + await vscode.workspace.fs.delete(tempFileUri, { useTrash: false }) + } catch (e) { + console.error(`Failed to delete temp file ${tempFileUri.fsPath}:`, e) + } + } + } }