functions/ai/Set-SldgPromptTemplate.ps1
|
function Set-SldgPromptTemplate { <# .SYNOPSIS Creates or updates a custom prompt template override. .DESCRIPTION Writes a custom .prompt file to the configured AI.PromptPath directory. Custom prompts take priority over built-in templates during resolution. If AI.PromptPath is not set, creates a 'prompts' folder next to the module and configures it automatically. The prompt file uses YAML front matter for metadata and supports {{Variable}} placeholders that are substituted at runtime. Accepts pipeline input from Get-SldgPromptTemplate — Purpose, Variant, and Content are bound by property name. .PARAMETER InputObject A prompt template object from Get-SldgPromptTemplate. Purpose, Variant, and Content (when present) are extracted automatically. .PARAMETER Purpose The prompt purpose to override (e.g. 'column-analysis', 'structured-value', 'batch-generation', 'plan-advice', 'locale-data', 'locale-category'). .PARAMETER Variant The variant name. Defaults to 'default'. Use provider names like 'openai' or 'ollama' to create provider-specific overrides. .PARAMETER Content The prompt body text. Can include {{Variable}} placeholders. .PARAMETER Description Optional description stored in the YAML front matter. .PARAMETER FilePath Read the prompt content from an existing file instead of -Content. .PARAMETER Force Overwrite an existing custom prompt without confirmation. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .EXAMPLE PS C:\> Set-SldgPromptTemplate -Purpose 'structured-value' -Variant 'default' -Content $myPrompt -Description 'Custom JSON/XML generator for reports' Creates a custom structured-value prompt template. .EXAMPLE PS C:\> Set-SldgPromptTemplate -Purpose 'column-analysis' -Variant 'ollama' -FilePath '.\my-ollama-prompt.txt' Creates an Ollama-specific override for column analysis from a file. .EXAMPLE PS C:\> Get-SldgPromptTemplate -Purpose structured-value -IncludeContent | Set-SldgPromptTemplate -Force Copies the built-in template as a custom override (Purpose, Variant, Content bound by property name). .EXAMPLE PS C:\> Get-SldgPromptTemplate -Purpose structured-value -IncludeContent | Set-SldgPromptTemplate -Content ($_.Content -replace 'Generate 10', 'Generate 20') -Force Copies and modifies the built-in template. #> [OutputType([SqlLabDataGenerator.PromptTemplate])] [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Content')] param ( [Parameter(ValueFromPipeline, ParameterSetName = 'InputObject')] [PSTypeName('SqlLabDataGenerator.PromptTemplate')] $InputObject, [Parameter(Mandatory, ParameterSetName = 'Content', ValueFromPipelineByPropertyName)] [Parameter(Mandatory, ParameterSetName = 'File', ValueFromPipelineByPropertyName)] [ValidateNotNullOrEmpty()] [string]$Purpose, [Parameter(ValueFromPipelineByPropertyName)] [string]$Variant = 'default', [Parameter(Mandatory, ParameterSetName = 'Content', ValueFromPipelineByPropertyName)] [string]$Content, [Parameter(Mandatory, ParameterSetName = 'File')] [string]$FilePath, [string]$Description, [switch]$Force ) process { # InputObject pipeline binding — extract properties from piped Get-SldgPromptTemplate output if ($PSCmdlet.ParameterSetName -eq 'InputObject' -and $InputObject) { if (-not $PSBoundParameters.ContainsKey('Purpose')) { $Purpose = $InputObject.Purpose } if (-not $PSBoundParameters.ContainsKey('Variant')) { $Variant = $InputObject.Variant } if (-not $PSBoundParameters.ContainsKey('Content') -and $InputObject.PSObject.Properties['Content']) { $Content = $InputObject.Content } } if (-not $Purpose) { Stop-PSFFunction -String 'Prompt.PurposeRequired' -EnableException $true } # Resolve content from file if specified if ($FilePath) { if (-not (Test-Path $FilePath)) { Stop-PSFFunction -String 'Prompt.FileNotFound' -StringValues $FilePath -EnableException $true } $Content = Get-Content -Path $FilePath -Raw -Encoding UTF8 } if (-not $Content) { Stop-PSFFunction -String 'Prompt.ContentEmpty' -EnableException $true } # Ensure custom prompt path exists $customPath = Get-PSFConfigValue -FullName 'SqlLabDataGenerator.AI.PromptPath' if (-not $customPath) { $customPath = Join-Path (Split-Path $script:ModuleRoot -Parent) 'CustomPrompts' Set-PSFConfig -FullName 'SqlLabDataGenerator.AI.PromptPath' -Value $customPath Write-PSFMessage -Level Verbose -Message ($script:strings.'Prompt.PromptPathAutoconfigured' -f $customPath) } if (-not (Test-Path $customPath)) { $null = New-Item -Path $customPath -ItemType Directory -Force Write-PSFMessage -Level Verbose -Message ($script:strings.'Prompt.DirectoryCreated' -f $customPath) } $fileName = "$Purpose.$Variant.prompt" $targetPath = Join-Path $customPath $fileName if ((Test-Path $targetPath) -and -not $Force) { if (-not $PSCmdlet.ShouldProcess($targetPath, 'Overwrite existing custom prompt')) { return } } # Strip existing YAML front matter from content if present (user may have piped from Get-SldgPromptTemplate) $body = $Content if ($Content -match '^---\s*\r?\n[\s\S]*?\r?\n---\s*\r?\n([\s\S]*)$') { $body = $Matches[1] } # Build YAML front matter — escape values to prevent YAML injection $descText = if ($Description) { $Description } else { "Custom override for $Purpose" } # Escape YAML special characters: wrap in single quotes, double any internal single quotes $safePurpose = "'" + ($Purpose -replace "'", "''") + "'" $safeDesc = "'" + ($descText -replace "'", "''") + "'" $header = @" --- purpose: $safePurpose description: $safeDesc version: 1 --- "@ $fullContent = "$header`n$body" Set-Content -Path $targetPath -Value $fullContent -Encoding UTF8 -NoNewline Write-PSFMessage -Level Host -Message ($script:strings.'Prompt.Saved' -f $targetPath) [SqlLabDataGenerator.PromptTemplate]@{ Purpose = $Purpose Variant = $Variant Description = $descText Path = $targetPath IsCustom = $true } } } |