private/Build-BatchPrompt.ps1
|
function Build-BatchPrompt { <# .SYNOPSIS Builds a combined prompt for batch file processing. .DESCRIPTION Combines multiple files into a single prompt for batch processing. Includes static context files, dynamic context from ContextFilter, and file contents. Used when BatchSize > 1 to reduce API calls. .PARAMETER BasePrompt The base prompt text. .PARAMETER FilesToProcess Array of file paths to include in the batch. .PARAMETER StaticContextFiles Array of static context file paths to include. .PARAMETER ContextFilter Optional scriptblock for deriving dynamic context files. .PARAMETER ContextFilterBase Base directories to search for derived context files. .PARAMETER ToolName The AI tool being used (e.g., Claude, Aider). Aider handles context differently. .PARAMETER ReasoningEffort Optional reasoning effort level for Claude (low, medium, high). .PARAMETER PSCmdlet The PSCmdlet object for ShouldProcess support. .OUTPUTS [hashtable] with keys: - FullPrompt: The complete prompt with all context and files - TargetFile: The first file in the batch (used for directory context) - TargetDirectory: The directory of the first file .EXAMPLE $params = @{ BasePrompt = "Translate these files" FilesToProcess = @("file1.md", "file2.md") ToolName = "Claude" } $result = Build-BatchPrompt @params #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [string]$BasePrompt, [Parameter(Mandatory)] [string[]]$FilesToProcess, [Parameter()] [string[]]$StaticContextFiles, [Parameter()] [scriptblock]$ContextFilter, [Parameter()] [string[]]$ContextFilterBase, [Parameter(Mandatory)] [string]$ToolName, [Parameter()] [ValidateSet('low', 'medium', 'high', '')] [string]$ReasoningEffort, [Parameter()] [System.Management.Automation.PSCmdlet]$PSCmdlet ) Write-PSFMessage -Level Verbose -Message "BATCH MODE: Combining $($FilesToProcess.Count) files into a SINGLE API request" $fullPrompt = $BasePrompt # Add static context files (not for Aider - it handles context differently) if ($ToolName -ne 'Aider' -and $StaticContextFiles -and $StaticContextFiles.Count -gt 0) { Write-PSFMessage -Level Verbose -Message "Adding $($StaticContextFiles.Count) static context file(s) to batch prompt" foreach ($ctxFile in $StaticContextFiles) { if (Test-Path $ctxFile) { $content = Get-Content -Path $ctxFile -Raw $fullPrompt += "`n`n--- Context from $($ctxFile) ---`n$content" Write-PSFMessage -Level Verbose -Message "Added static context: $ctxFile" } } # If context is a single JSON file, append instruction for raw JSON output $existingContextFiles = @($StaticContextFiles | Where-Object { Test-Path $_ }) if ($existingContextFiles.Count -eq 1) { $singleContextFile = $existingContextFiles[0] if ([System.IO.Path]::GetExtension($singleContextFile).ToLower() -eq '.json') { $script:singleJson = $true $jsonInstruction = "IMPORTANT: Output raw JSON only - no markdown code fences, no backticks, no explanation. Response must start with { and end with } for direct parsing by ConvertFrom-Json. Follow the schema EXACTLY - use only the property names defined in the schema, no additional properties." $fullPrompt += "`n`n$jsonInstruction" Write-PSFMessage -Level Verbose -Message "Single JSON context detected - appended: $jsonInstruction" } else { $script:singleJson = $false } } else { $script:singleJson = $false } } else { $script:singleJson = $false } # Add dynamic context files from ContextFilter (not for Aider) if ($ToolName -ne 'Aider' -and $ContextFilter) { $dynamicParams = @{ BasePrompt = $fullPrompt InputFiles = $FilesToProcess ContextFilter = $ContextFilter ContextFilterBase = $ContextFilterBase PSCmdlet = $PSCmdlet } $dynamicResult = Add-DynamicContextToPrompt @dynamicParams $fullPrompt = $dynamicResult.Prompt } # Add all files in batch with their contents $fullPrompt += "`n`n=== FILES TO PROCESS ===`n" foreach ($fileInBatch in $FilesToProcess) { $fileContent = Get-Content -Path $fileInBatch -Raw -ErrorAction SilentlyContinue # Use full absolute path in the prompt for clarity $absolutePath = (Resolve-Path -Path $fileInBatch).Path $fullPrompt += "`n--- FILE: $absolutePath ---`n$fileContent`n" Write-PSFMessage -Level Verbose -Message " - Added file to batch: $absolutePath" } Write-PSFMessage -Level Verbose -Message "Batch prompt ready: $($FilesToProcess.Count) files combined into single request" # Add Claude reasoning trigger if needed if ($ToolName -eq 'Claude' -and $ReasoningEffort) { $reasoningPhrase = switch ($ReasoningEffort) { 'low' { 'think hard' } 'medium' { 'think harder' } 'high' { 'ultrathink' } } $fullPrompt += "`n`n$reasoningPhrase" Write-PSFMessage -Level Verbose -Message "Claude reasoning trigger appended: $reasoningPhrase" } # For batch mode, use the first file as the "target" for tool arguments $targetFile = $FilesToProcess[0] $targetDirectory = Split-Path $targetFile -Parent return @{ FullPrompt = $fullPrompt TargetFile = $targetFile TargetDirectory = $targetDirectory } } |