Functions/GenXdev.Coding.PowerShell.Modules/Update-Refactor.ps1
############################################################################### <# .SYNOPSIS Updates and manages refactoring sets including file selection and processing. .DESCRIPTION Provides comprehensive management of refactoring sets by: - Adding or removing files from processing queues - Cleaning up deleted files from the set - Managing state information and progress tracking - Handling LLM-based file selection and processing - Supporting both automatic and manual file management - Maintaining detailed logs of all operations .PARAMETER Name Names of refactor sets to update, accepts wildcards. Default is "*". .PARAMETER Refactor Direct input of refactor set objects instead of loading by name. .PARAMETER FilesToAdd Files to add to the processing queue. .PARAMETER FilesToRemove Files to remove from the processing queue. .PARAMETER CleanUpDeletedFiles Remove entries for files that no longer exist on disk. .PARAMETER AskBeforeLLMSelection Prompt before launching LLM invocations for file selections. .PARAMETER PerformLLMSelections Enable LLM-based file selection processing. .PARAMETER PerformAllLLMSelections Process all files in the refactor set with LLM. .PARAMETER RetryFailedLLMSelections Retry previously failed LLM selections. .PARAMETER Clear Remove all files from the refactor set. .PARAMETER ClearLog Clear the refactor set's operation log. .PARAMETER Reset Start processing from beginning of refactor set. .PARAMETER ResetLMSelections Restart all LLM selections from beginning. .PARAMETER MarkAllCompleted Mark all files as successfully refactored. .PARAMETER SelectByModifiedDateFrom Select files modified on or after this date. .PARAMETER SelectByModifiedDateTo Select files modified on or before this date. .PARAMETER SelectByCreationDateFrom Select files created on or after this date. .PARAMETER SelectByCreationDateTo Select files created on or before this date. .PARAMETER RedoLast Reprocess the last refactoring operation. .PARAMETER PromptKey Key identifying which prompt script to use. .PARAMETER Prompt Direct prompt text to use for processing. .PARAMETER SelectionScript PowerShell script for file selection logic. .PARAMETER AutoAddModifiedFiles Automatically add modified files to processing queue. .PARAMETER SelectionPrompt Content for LLM-based selection prompts. .PARAMETER Temperature Temperature setting for response randomness (0.0-1.0). .PARAMETER Force Force stop LM-Studio before initialization. .PARAMETER Priority Processing priority level for this refactor set. .PARAMETER ExposedCmdLets PowerShell commands available during LLM selection. .PARAMETER Code Open file in Visual Studio Code. .PARAMETER VisualStudio Open file in Visual Studio. .PARAMETER KeysToSend Keystrokes to send after opening file. .PARAMETER Speak Enable text-to-speech for operation details. .PARAMETER LLMQueryType Type of LLM query to perform. .PARAMETER Model LLM model identifier for LM-Studio. .PARAMETER HuggingFaceIdentifier Model retrieval identifier for LM-Studio. .PARAMETER MaxToken Maximum tokens allowed in responses (-1 for default). .PARAMETER Cpu Number of CPU cores to dedicate to AI operations. .PARAMETER TTLSeconds Time-to-live in seconds for API model requests. .PARAMETER SelectByFreeRam Select configuration by available system RAM. .PARAMETER SelectByFreeGpuRam Select configuration by available GPU RAM. .PARAMETER Gpu GPU processing control (-2=Auto, -1=LM-Studio default). .PARAMETER ApiEndpoint API endpoint URL for LLM service. .PARAMETER ApiKey Authentication key for API access. .PARAMETER TimeoutSeconds The timeout in seconds for AI operations. .PARAMETER SessionOnly Use alternative settings stored in session for AI preferences. .PARAMETER ClearSession Clear alternative settings stored in session for AI preferences. .PARAMETER PreferencesDatabasePath Database path for preference data files. .PARAMETER SkipSession Store settings only in persistent preferences without affecting session. .EXAMPLE Update-Refactor -Name "CodeCleanup" -FilesToAdd ".\src\*.cs" ` -CleanUpDeletedFiles -PerformLLMSelections .EXAMPLE Get-Refactor "MyRefactor" | Update-Refactor -Reset -Clear .EXAMPLE updaterefactor * -Clear -Reset #> ############################################################################### function Update-Refactor { [CmdletBinding(DefaultParameterSetName = 'Name', SupportsShouldProcess)] [Alias("updaterefactor")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSAvoidUsingInvokeExpression', '', Justification = 'Required for dynamic script execution in refactoring context')] param ( ############################################################################### [Parameter( ParameterSetName = 'Name', Mandatory = $false, Position = 0, HelpMessage = "The name of the refactor, accepts wildcards", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [SupportsWildcards()] [string[]] $Name = @("*"), ############################################################################### [Parameter( ParameterSetName = 'Refactor', Mandatory = $false, Position = 1, HelpMessage = "The refactor set to update" )] [ValidateNotNull()] [GenXdev.Helpers.RefactorDefinition[]] $Refactor, ############################################################################### [Parameter( Mandatory = $false, Position = 2, HelpMessage = "Filenames to add" )] [ValidateNotNull()] [System.IO.FileInfo[]] $FilesToAdd = @(), ############################################################################### [Parameter( Mandatory = $false, Position = 3, HelpMessage = "Filenames to remove" )] [ValidateNotNull()] [System.IO.FileInfo[]] $FilesToRemove = @(), ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Select files by modified date from" )] [ValidateNotNullOrEmpty()] [datetime] $SelectByModifiedDateFrom, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Select files by modified date to" )] [ValidateNotNullOrEmpty()] [datetime] $SelectByModifiedDateTo, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Select files by creation date from" )] [ValidateNotNullOrEmpty()] [datetime] $SelectByCreationDateFrom, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Select files by creation date to" )] [ValidateNotNullOrEmpty()] [datetime] $SelectByCreationDateTo, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The prompt key indicates which prompt script to use" )] [ValidateNotNullOrEmpty()] [string] $PromptKey, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The prompt key indicates which prompt script to use" )] [ValidateNotNullOrEmpty()] [string] $Prompt = "", ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("Powershell script for function to select items to " + "refactor") )] [ValidateNotNullOrEmpty()] [string] $SelectionScript, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("If provided, will invoke LLM to do the selection " + "based on the content of the script") )] [ValidateNotNullOrEmpty()] [string] $SelectionPrompt, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The type of LLM query" )] [ValidateSet( "SimpleIntelligence", "Knowledge", "Pictures", "TextTranslation", "Coding", "ToolUse" )] [string] $LLMQueryType = "Coding", ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The model identifier or pattern to use for AI operations" )] [string] $Model, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The LM Studio specific model identifier" )] [Alias("ModelLMSGetIdentifier")] [string] $HuggingFaceIdentifier, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Temperature for response randomness (0.0-1.0)" )] [ValidateRange(0.0, 1.0)] [double] $Temperature = 0.2, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The maximum number of tokens to use in AI operations" )] [int] $MaxToken, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Time-to-live in seconds for API-loaded models" )] [int] $TTLSeconds, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The number of CPU cores to dedicate to AI operations" )] [int] $Cpu, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("How much to offload to the GPU. If 'off', GPU " + "offloading is disabled. If 'max', all layers are " + "offloaded to GPU. If a number between 0 and 1, " + "that fraction of layers will be offloaded to the " + "GPU. -1 = LM Studio will decide how much to " + "offload to the GPU. -2 = Auto") )] [ValidateRange(-2, 1)] [int] $Gpu = -1, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The API endpoint URL for AI operations" )] [string] $ApiEndpoint, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The API key for authenticated AI operations" )] [string] $ApiKey, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The timeout in seconds for AI operations" )] [int] $TimeoutSeconds, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Priority for this refactor set" )] [ValidateNotNullOrEmpty()] [int] $Priority, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("Array of PowerShell command definitions to use as " + "tools during LLM selection") )] [GenXdev.Helpers.ExposedCmdletDefinition[]] $ExposedCmdLets = @(), ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The keys to invoke as key strokes after opening the file" )] [Alias("keys")] [string[]] $KeysToSend = @(), ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Database path for preference data files" )] [string] $PreferencesDatabasePath, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Clean up deleted files" )] [switch] $CleanUpDeletedFiles, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Switch to suppress user interaction" )] [switch] $AskBeforeLLMSelection, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Switch to enable LLM-based file selection processing" )] [switch] $PerformLLMSelections, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Switch to process all files in the refactor set" )] [switch] $PerformAllLLMSelections, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Switch to retry failed LLM selections" )] [switch] $RetryFailedLLMSelections, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Clear all files from the refactor set" )] [switch] $Clear, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Clear the log of the refactor set" )] [switch] $ClearLog, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Start from the beginning of the refactor set" )] [switch] $Reset, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Restart all LLMSelections" )] [switch] $ResetLMSelections, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Mark all files as refactored" )] [switch] $MarkAllCompleted, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Redo the last refactor" )] [switch] $RedoLast, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Will automatically add modified files to the queue" )] [switch] $AutoAddModifiedFiles, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Force stop LM Studio before initialization" )] [switch] $Force, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "The ide to open the file in" )] [Alias("c")] [switch] $Code, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Open in Visual Studio" )] [Alias("vs")] [switch] $VisualStudio, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Speak out the details of next refactor" )] [switch] $Speak, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Select configuration by available system RAM" )] [switch] $SelectByFreeRam, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Select configuration by available GPU RAM" )] [switch] $SelectByFreeGpuRam, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("Use alternative settings stored in session for AI " + "preferences") )] [switch] $SessionOnly, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("Clear alternative settings stored in session for AI " + "preferences") )] [switch] $ClearSession, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ("Store settings only in persistent preferences " + "without affecting session") )] [Alias("FromPreferences")] [switch] $SkipSession ############################################################################### ) begin { # establish the modules path for GenXdev operations $modulesPath = GenXdev.FileSystem\Expand-Path "$PSScriptRoot\..\..\..\..\" # log start of operation for debugging and tracking Microsoft.PowerShell.Utility\Write-Verbose "Starting Update-Refactor operation" # load refactor set by name if not provided directly via pipeline if ($PSCmdlet.ParameterSetName -eq 'Name') { # retrieve and sort refactor definitions by priority $Refactor = @( GenXdev.Coding\Get-Refactor -Name $Name | Microsoft.PowerShell.Utility\Sort-Object -Property Priority -Descending ) } # exit early if no refactor set found to prevent further processing if ($null -eq $Refactor -or $Refactor.Count -eq 0) { Microsoft.PowerShell.Utility\Write-Warning "No refactorset found" return } # initialize tracking variables for file operations and progress $now = GenXdev.Console\UtcNow $script:filesAdded = 0 $script:filesRemoved = 0 $script:onlyFirst = -not $PerformAllLLMSelections $script:last = $null } process { # process each refactor definition in the collection foreach ($refactorDefinition in $Refactor) { # initialize or clear state containers when requested if ($Clear -or ($null -eq $refactorDefinition.State.Unselected)) { $refactorDefinition.State.Unselected = @() } # initialize or clear selected files collection if ($Clear -or ($null -eq $refactorDefinition.State.Selected)) { $refactorDefinition.State.Selected = @() } # initialize or clear refactored files collection if ($Clear -or ($null -eq $refactorDefinition.State.Refactored)) { $refactorDefinition.State.Refactored = @() } # initialize log collection if missing if ($null -eq $refactorDefinition.Log) { $refactorDefinition.Log = @() } # clear operation log if requested if ($ClearLog) { $null = $refactorDefinition.Log.Clear() # record log clearing action in new log entry $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Log cleared" } ) } # reset all state indices and progress when clearing if ($Clear) { $refactorDefinition.State.RefactoredIndex = -1 $refactorDefinition.State.SelectedIndex = -1 $refactorDefinition.State.UnselectedIndex = -1 $refactorDefinition.State.PercentageComplete = 0 # log the clear operation for audit trail $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Refactor set cleared" } ) } # update prompt key if specified and different from current value if ($PSBoundParameters.ContainsKey('PromptKey')) { if ($refactorDefinition.RefactorSettings.PromptKey -ne $PromptKey) { # log the change for audit trail $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = ("Prompt key changed from " + "'$($refactorDefinition.RefactorSettings.PromptKey)' " + "to '$PromptKey'") } ) # apply the new prompt key value $refactorDefinition.RefactorSettings.PromptKey = $PromptKey } } # update prompt text if provided and different if ($PSBoundParameters.ContainsKey('Prompt')) { if ($refactorDefinition.RefactorSettings.Prompt -ne $Prompt) { # log the prompt text change $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = ("Prompt changed from " + "'$($refactorDefinition.RefactorSettings.Prompt)' " + "to '$Prompt'") } ) # apply the new prompt text $refactorDefinition.RefactorSettings.Prompt = $Prompt } } # update selection script if provided and different if ($PSBoundParameters.ContainsKey('SelectionScript')) { if ($refactorDefinition.SelectionSettings.Script -ne $SelectionScript) { # log the selection script change $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = ("Selection script changed from " + "'$($refactorDefinition.SelectionSettings.Script)' " + "to '$SelectionScript'") } ) # apply the new selection script $refactorDefinition.SelectionSettings.Script = $SelectionScript } } # update auto-add modified files setting if changed if ($PSBoundParameters.ContainsKey('AutoAddModifiedFiles')) { if ($refactorDefinition.SelectionSettings.AutoAddModifiedFiles -ne $AutoAddModifiedFiles) { # log the auto-add setting change $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = ("AutoAddModifiedFiles changed from " + "'$($refactorDefinition.SelectionSettings.AutoAddModifiedFiles)' " + "to '$AutoAddModifiedFiles'") } ) # apply the new auto-add setting $refactorDefinition.SelectionSettings.AutoAddModifiedFiles = $AutoAddModifiedFiles } } if ($PSBoundParameters.ContainsKey('SelectionPrompt')) { if ($refactorDefinition.SelectionSettings.LLM.Prompt -ne $SelectionPrompt) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Selection prompt changed from '$($refactorDefinition.SelectionSettings.LLM.Prompt))' to '$SelectionPrompt'" } ) $refactorDefinition.SelectionSettings.LLM.Prompt = $SelectionPrompt } } if ($PSBoundParameters.ContainsKey('Model')) { if ($refactorDefinition.SelectionSettings.LLM.Model -ne $Model) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Model changed from '$($refactorDefinition.SelectionSettings.LLM.Model))' to '$Model'" } ) $refactorDefinition.SelectionSettings.LLM.Model = $Model } } if ($PSBoundParameters.ContainsKey('HuggingFaceIdentifier')) { if ($refactorDefinition.SelectionSettings.LLM.HuggingFaceIdentifier -ne $HuggingFaceIdentifier) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "HuggingFaceIdentifier changed from '$($refactorDefinition.SelectionSettings.LLM.HuggingFaceIdentifier))' to '$HuggingFaceIdentifier'" } ) $refactorDefinition.SelectionSettings.LLM.HuggingFaceIdentifier = $HuggingFaceIdentifier } } if ($PSBoundParameters.ContainsKey('Temperature')) { if ($refactorDefinition.SelectionSettings.LLM.Temperature -ne $Temperature) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Temperature changed from '$($refactorDefinition.SelectionSettings.LLM.Temperature))' to '$Temperature'" } ) $refactorDefinition.SelectionSettings.LLM.Temperature = $Temperature } } if ($PSBoundParameters.ContainsKey('MaxToken')) { if ($refactorDefinition.SelectionSettings.LLM.MaxToken -ne $MaxToken) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "MaxToken changed from '$($refactorDefinition.SelectionSettings.LLM.MaxToken))' to '$MaxToken'" } ) $refactorDefinition.SelectionSettings.LLM.MaxToken = $MaxToken } } if ($PSBoundParameters.ContainsKey('TTLSeconds')) { if ($refactorDefinition.SelectionSettings.LLM.TTLSeconds -ne $TTLSeconds) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "TTLSeconds changed from '$($refactorDefinition.SelectionSettings.LLM.TTLSeconds))' to '$TTLSeconds'" } ) $refactorDefinition.SelectionSettings.LLM.TTLSeconds = $TTLSeconds } } if ($PSBoundParameters.ContainsKey('Cpu')) { if ($refactorDefinition.SelectionSettings.LLM.Cpu -ne $Cpu) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Cpu changed from '$($refactorDefinition.SelectionSettings.LLM.Cpu))' to '$Cpu'" } ) $refactorDefinition.SelectionSettings.LLM.Cpu = $Cpu } } if ($PSBoundParameters.ContainsKey('SelectByFreeRam')) { if ($refactorDefinition.SelectionSettings.LLM.SelectByFreeRam -ne $SelectByFreeRam) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "SelectByFreeRam changed from '$($refactorDefinition.SelectionSettings.LLM.SelectByFreeRam))' to '$SelectByFreeRam'" } ) $refactorDefinition.SelectionSettings.LLM.SelectByFreeRam = $SelectByFreeRam } } if ($PSBoundParameters.ContainsKey('SelectByFreeGpuRam')) { if ($refactorDefinition.SelectionSettings.LLM.SelectByFreeGpuRam -ne $SelectByFreeGpuRam) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "SelectByFreeGpuRam changed from '$($refactorDefinition.SelectionSettings.LLM.SelectByFreeGpuRam))' to '$SelectByFreeGpuRam'" } ) $refactorDefinition.SelectionSettings.LLM.SelectByFreeGpuRam = $SelectByFreeGpuRam } } if ($PSBoundParameters.ContainsKey('LLMQueryType')) { if ($refactorDefinition.SelectionSettings.LLM.LLMQueryType -ne $LLMQueryType) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "LLMQueryType changed from '$($refactorDefinition.SelectionSettings.LLM.LLMQueryType))' to '$LLMQueryType'" } ) $refactorDefinition.SelectionSettings.LLM.LLMQueryType = $LLMQueryType } } if ($PSBoundParameters.ContainsKey('TimeoutSeconds')) { if ($refactorDefinition.SelectionSettings.LLM.TimeoutSeconds -ne $TimeoutSeconds) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "TimeoutSeconds changed from '$($refactorDefinition.SelectionSettings.LLM.TimeoutSeconds))' to '$TimeoutSeconds'" } ) $refactorDefinition.SelectionSettings.LLM.TimeoutSeconds = $TimeoutSeconds } } if ($PSBoundParameters.ContainsKey('Gpu')) { if ($refactorDefinition.SelectionSettings.LLM.Gpu -ne $Gpu) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Gpu changed from '$($refactorDefinition.SelectionSettings.LLM.Gpu))' to '$Gpu'" } ) $refactorDefinition.SelectionSettings.LLM.Gpu = $Gpu } } if ($PSBoundParameters.ContainsKey('Force')) { if ($refactorDefinition.SelectionSettings.LLM.Force -ne $Force) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Force changed from '$($refactorDefinition.SelectionSettings.LLM.Force))' to '$Force'" } ) $refactorDefinition.SelectionSettings.LLM.Force = $Force } } if ($PSBoundParameters.ContainsKey('ApiEndpoint')) { if ($refactorDefinition.SelectionSettings.LLM.ApiEndpoint -ne $ApiEndpoint) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "ApiEndpoint changed from '$($refactorDefinition.SelectionSettings.LLM.ApiEndpoint))' to '$ApiEndpoint'" } ) $refactorDefinition.SelectionSettings.LLM.ApiEndpoint = $ApiEndpoint } } if ($PSBoundParameters.ContainsKey('ApiKey')) { if ($refactorDefinition.SelectionSettings.LLM.ApiKey -ne $ApiKey) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "ApiKey changed from '$($refactorDefinition.SelectionSettings.LLM.ApiKey))' to '$ApiKey'" } ) $refactorDefinition.SelectionSettings.LLM.ApiKey = $ApiKey } } if ($PSBoundParameters.ContainsKey('ExposedCmdLets')) { if ($refactorDefinition.SelectionSettings.LLM.ExposedCmdLets -ne $ExposedCmdLets) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "ExposedCmdLets changed from '$($refactorDefinition.SelectionSettings.LLM.ExposedCmdLets))' to '$ExposedCmdLets'" } ) $refactorDefinition.SelectionSettings.LLM.ExposedCmdLets = $ExposedCmdLets } } if ($PSBoundParameters.ContainsKey("Priority")) { if ($refactorDefinition.Priority -ne $Priority) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Priority changed from '$($refactorDefinition.Priority))' to '$Priority'" } ) $refactorDefinition.Priority = $Priority } } if ($PSBoundParameters.ContainsKey('KeysToSend')) { if ($refactorDefinition.RefactorSettings.KeysToSend -ne $KeysToSend) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "KeysToSend changed from '$($refactorDefinition.RefactorSettings.KeysToSend))' to '$KeysToSend'" } ) $refactorDefinition.RefactorSettings.KeysToSend = $KeysToSend } } $newCode = $PSBoundParameters.ContainsKey("Code") ? ($Code ? 1 : 0) : -1; if ($refactorDefinition.RefactorSettings.Code -ne $newCode) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Code changed from '$($refactorDefinition.RefactorSettings.Code))' to '$newCode'" } ) $refactorDefinition.RefactorSettings.Code = $newCode } $newVisualStudio = $PSBoundParameters.ContainsKey("VisualStudio") ? ($VisualStudio ? 1 : 0) : -1; if ($refactorDefinition.RefactorSettings.VisualStudio -ne $newVisualStudio) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "VisualStudio changed from '$($refactorDefinition.RefactorSettings.VisualStudio))' to '$newVisualStudio'" } ) $refactorDefinition.RefactorSettings.VisualStudio = $newVisualStudio } if ($null -ne $SelectByModifiedDateFrom) { # copy all refactored files to FilesToAdd $FilesToAdd += @( $refactorDefinition.State.Refactored | Microsoft.PowerShell.Core\ForEach-Object { if ([string]::IsNullOrWhiteSpace($_)) { return } $fi = [System.IO.FileInfo]::new($_); if ($fi.Exists -and $fi.LastWriteTime -ge $SelectByModifiedDateFrom) { $fi } } ); $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "New file selection made: Redo all files modifief from date '$SelectByModifiedDateFrom'" } ) } if ($null -ne $SelectByModifiedDateTo) { # copy all refactored files to FilesToAdd $FilesToAdd += @( $refactorDefinition.State.Refactored | Microsoft.PowerShell.Core\ForEach-Object { if ([string]::IsNullOrWhiteSpace($_)) { return } $fi = [System.IO.FileInfo]::new($_); if ($fi.Exists -and $fi.LastWriteTime -lt $SelectByModifiedDateFrom) { $fi } } ); $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "New file selection made: Redo all files modifief to date '$SelectByModifiedDateTo'" } ) } if ($null -ne $SelectByCreationDateFrom) { # copy all refactored files to FilesToAdd $FilesToAdd += @( $refactorDefinition.State.Refactored | Microsoft.PowerShell.Core\ForEach-Object { if ([string]::IsNullOrWhiteSpace($_)) { return } $fi = [System.IO.FileInfo]::new($_); if ($fi.Exists -and $fi.CreationTime -ge $SelectByModifiedDateFrom) { $fi } } ); $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "New file selection made: Redo all files created from date '$SelectByCreationDateFrom'" } ) } if ($null -ne $SelectByCreationDateTo) { # copy all refactored files to FilesToAdd $FilesToAdd += @( $refactorDefinition.State.Refactored | Microsoft.PowerShell.Core\ForEach-Object { if ([string]::IsNullOrWhiteSpace($_)) { return } $fi = [System.IO.FileInfo]::new($_); if ($fi.Exists -and $fi.CreationTime -lt $SelectByModifiedDateFrom) { $fi } } ); $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "New file selection made: Redo all files created to date '$SelectByCreationDateTo'" } ) } if ($RedoLast -and $refactorDefinition.State.Refactored.Count -gt 0) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Redoing last refactor" } ) $refactorDefinition.State.RefactoredIndex = [Math]::Max(-1, $refactorDefinition.State.RefactoredIndex - 1) } elseif ($Reset) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Resetting refactor set" } ) $refactorDefinition.State.RefactoredIndex = -1 $refactorDefinition.State.Selected = @(@( $refactorDefinition.State.Selected + $refactorDefinition.State.Refactored ) | Microsoft.PowerShell.Utility\Select-Object -Unique) $null = $refactorDefinition.State.Refactored.Clear(); } if ($MarkAllCompleted) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Marking all files as refactored" } ) $refactorDefinition.State.Refactored = @(@( $refactorDefinition.State.Refactored + $refactorDefinition.State.Selected ) | Microsoft.PowerShell.Utility\Select-Object -Unique) $null = $refactorDefinition.State.Selected.Clear(); $refactorDefinition.State.SelectedIndex = $refactorDefinition.State.Selected.Count - 1; $refactorDefinition.State.RefactoredIndex = $refactorDefinition.State.Refactored.Count - 1; $refactorDefinition.State.PercentageComplete = 100; } if ($ResetLMSelections) { $null = $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Resetting LLM selections" } ) $refactorDefinition.State.SelectedIndex = -1; $refactorDefinition.State.Unselected = @(@( $refactorDefinition.State.Unselected + $refactorDefinition.State.Selected ) | Microsoft.PowerShell.Utility\Select-Object -Unique) $null = $refactorDefinition.State.Selected.Clear(); } Microsoft.PowerShell.Utility\Write-Verbose "Processing refactor definition: $($refactorDefinition.Name)" # execute selection script to get automatically selected files [System.IO.FileInfo[]] $automaticFiles = ($null = @( if (-not [string]::IsNullOrWhiteSpace( $refactorDefinition.SelectionSettings.Script)) { Microsoft.PowerShell.Utility\Write-Verbose "Executing selection script" if (-not $Clear) { Microsoft.PowerShell.Utility\Invoke-Expression -Command $refactorDefinition.SelectionSettings.Script } } ) + @($FilesToAdd | Microsoft.PowerShell.Core\ForEach-Object { if ($null -ne $_) { $item = Microsoft.PowerShell.Management\Get-Item -Path (GenXdev.FileSystem\Expand-Path $_) -ErrorAction SilentlyContinue if ($null -ne $item) { $item } } })) | Microsoft.PowerShell.Utility\Sort-Object -Property FullName -Unique | Microsoft.PowerShell.Utility\Sort-Object -Property LastWriteTimeUtc; if ($null -ne $automaticFiles) { # process new files to be added @($automaticFiles) | Microsoft.PowerShell.Core\ForEach-Object { if ($null -eq $_ ) { return } # check if file exists in any collection $indexRefactored = $refactorDefinition.State.Refactored.IndexOf($_) $indexSelected = $refactorDefinition.State.Selected.IndexOf($_) $indexUnselected = $refactorDefinition.State.Unselected.IndexOf($_) # add file if not already present if ($indexRefactored -lt 0 -and $indexSelected -lt 0 -and $indexUnselected -lt 0) { # add to selected if no LLM prompt, otherwise to unselected if ([string]::IsNullOrWhiteSpace( $refactorDefinition.SelectionSettings.LLM.Prompt)) { $null = $refactorDefinition.State.Selected.Add($_) } else { $null = $refactorDefinition.State.Unselected.Add($_) } $script:filesAdded++ return; } if ((($null -ne $FilesToAdd) -and ($FilesToAdd.IndexOf($_) -ge 0)) -or ( $refactorDefinition.SelectionSettings.AutoAddModifiedFiles -and ($refactorDefinition.State.LastUpdated -lt ($_.LastWriteTimeUtc.AddMinutes(-15)) ) )) { if ($indexRefactored -ge 0) { $null = $refactorDefinition.State.Refactored.RemoveAt($indexRefactored) if ($indexRefactored -le $refactorDefinition.State.RefactoredIndex) { $refactorDefinition.State.RefactoredIndex = [Math]::Max(-1, $refactorDefinition.State.RefactoredIndex - 1) } $indexRefactored = -1; if ($indexSelected -lt 0) { $null = $refactorDefinition.State.Selected.Add($_) } } } } } # process files marked for removal $FilesToRemove | Microsoft.PowerShell.Core\ForEach-Object { # locate file in collections $indexRefactored = $refactorDefinition.State.Refactored.IndexOf($_) $indexSelected = $refactorDefinition.State.Selected.IndexOf($_) $indexUnselected = $refactorDefinition.State.Unselected.IndexOf($_) # remove from refactored collection and update index if ($indexRefactored -ge 0) { $target = "File: $($_)" $action = "Remove from refactored set" if ($PSCmdlet.ShouldProcess($target, $action)) { $null = $refactorDefinition.State.Refactored.RemoveAt($indexRefactored) if ($indexRefactored -le $refactorDefinition.State.RefactoredIndex) { $refactorDefinition.State.RefactoredIndex = [Math]::Max(-1, $refactorDefinition.State.RefactoredIndex - 1) } $indexRefactored = -1 $script:filesRemoved++ } } # remove from selected collection and update index if ($indexSelected -ge 0) { $null = $refactorDefinition.State.Selected.RemoveAt($indexSelected) if ($indexSelected -le $refactorDefinition.State.SelectedIndex) { $refactorDefinition.State.SelectedIndex = [Math]::Max(-1, $refactorDefinition.State.SelectedIndex - 1) } $indexSelected = -1 } # remove from unselected collection and update index if ($indexUnselected -ge 0) { $null = $refactorDefinition.State.Unselected.RemoveAt($indexUnselected) if ($indexUnselected -le $refactorDefinition.State.UnselectedIndex) { $refactorDefinition.State.UnselectedIndex = [Math]::Max(-1, $refactorDefinition.State.UnselectedIndex - 1) } $indexUnselected = -1 } } # migrate folder names for ($refactoredIndex = $refactorDefinition.State.Refactored.Count - 1; $refactoredIndex -ge 0; $refactoredIndex--) { if ($null -eq $refactorDefinition.State.Refactored[$refactoredIndex]) { $null = $refactorDefinition.State.Refactored.RemoveAt($refactoredIndex) } else { $path = (GenXdev.FileSystem\Expand-Path ($refactorDefinition.State.Refactored[$refactoredIndex])) if ($path.StartsWith("$modulesPath\GenXdev")) { $parts = $path.Substring($modulesPath.Length).Split("\", [System.StringSplitOptions]::RemoveEmptyEntries); if ($parts.Length -gt 1) { [Version] $version = $null if ([Version]::tryParse($parts[1], [ref]$version)) { $path = "$modulesPath\$($parts[0])\1.200.2025\$($path.Substring($modulesPath.Length + $parts[0].Length+ $parts[1].Length + 2))" if ($refactorDefinition.State.Refactored.IndexOf($path) -lt 0) { $refactorDefinition.State.Refactored[$refactoredIndex] = $path } else { $null = $refactorDefinition.State.Refactored.RemoveAt($refactoredIndex) if ($refactoredIndex -le $refactorDefinition.State.RefactoredIndex) { $refactorDefinition.State.RefactoredIndex = [Math]::Max(-1, $refactorDefinition.State.RefactoredIndex - 1) } } } } } } } # migrate folder names for ($selectedIndex = $refactorDefinition.State.Selected.Count - 1; $selectedIndex -ge 0; $selectedIndex--) { if ($null -eq $refactorDefinition.State.Selected[$selectedIndex]) { $null = $refactorDefinition.State.Selected.RemoveAt($selectedIndex) } else { $path = (GenXdev.FileSystem\Expand-Path $refactorDefinition.State.Selected[$selectedIndex]) if ($path.StartsWith("$modulesPath\GenXdev")) { $parts = $path.Substring($modulesPath.Length).Split("\", [System.StringSplitOptions]::RemoveEmptyEntries); if ($parts.Length -gt 1) { [Version] $version = $null if ([Version]::tryParse($parts[1], [ref]$version)) { $path = "$modulesPath\$($parts[0])\1.200.2025\$($path.Substring($modulesPath.Length + $parts[0].Length+ $parts[1].Length + 2))" if ($refactorDefinition.State.Selected.IndexOf($path) -lt 0) { $refactorDefinition.State.Selected[$selectedIndex] = $path } else { $null = $refactorDefinition.State.Selected.RemoveAt($selectedIndex) if ($selectedIndex -le $refactorDefinition.State.SelectedIndex) { $refactorDefinition.State.SelectedIndex = [Math]::Max(-1, $refactorDefinition.State.SelectedIndex - 1) } } } } } } } # migrate folder names for ($unselectedIndex = $refactorDefinition.State.Unselected.Count - 1; $unselectedIndex -ge 0; $unselectedIndex--) { if ($null -eq $refactorDefinition.State.Unselected[$unselectedIndex]) { $null = $refactorDefinition.State.Unselected.RemoveAt($unselectedIndex) } else { $path = (GenXdev.FileSystem\Expand-Path $refactorDefinition.State.Unselected[$unselectedIndex]) if ($path.StartsWith("$modulesPath\GenXdev")) { $parts = $path.Substring($modulesPath.Length).Split("\", [System.StringSplitOptions]::RemoveEmptyEntries); if ($parts.Length -gt 1) { [Version] $version = $null if ([Version]::tryParse($parts[1], [ref]$version)) { $path = "$modulesPath\$($parts[0])\1.200.2025\$($path.Substring($modulesPath.Length + $parts[0].Length+ $parts[1].Length + 2))" if ($refactorDefinition.State.Unselected.IndexOf($path) -lt 0) { $refactorDefinition.State.Unselected[$unselectedIndex] = $path } else { $null = $refactorDefinition.State.Unselected.RemoveAt($unselectedIndex) if ($unselectedIndex -le $refactorDefinition.State.UnselectedIndex) { $refactorDefinition.State.UnselectedIndex = [Math]::Max(-1, $refactorDefinition.State.UnselectedIndex - 1) } } } } } } } # clean up deleted files if requested if ($CleanUpDeletedFiles) { # clean refactored collection for ($refactoredIndex = $refactorDefinition.State.Refactored.Count - 1; $refactoredIndex -ge 0; $refactoredIndex--) { if ($null -eq $refactorDefinition.State.Refactored[$refactoredIndex]) { $null = $refactorDefinition.State.Refactored.RemoveAt($refactoredIndex) } else { $path = (GenXdev.FileSystem\Expand-Path ($refactorDefinition.State.Refactored[$refactoredIndex])) if (-not [IO.Path]::Exists($path)) { $null = $refactorDefinition.State.Refactored.RemoveAt($refactoredIndex) } } if ($refactorDefinition.State.RefactoredIndex -lt $refactoredIndex) { $refactorDefinition.State.RefactoredIndex = [Math]::Max(-1, $refactorDefinition.State.RefactoredIndex - 1) } } # clean selected collection for ($selectedIndex = $refactorDefinition.State.Selected.Count - 1; $selectedIndex -ge 0; $selectedIndex--) { $path = (GenXdev.FileSystem\Expand-Path $refactorDefinition.State.Selected[$selectedIndex]) if (-not [IO.Path]::Exists($path)) { $null = $refactorDefinition.State.Selected.RemoveAt($selectedIndex) } if ($refactorDefinition.State.SelectedIndex -lt $selectedIndex) { $refactorDefinition.State.SelectedIndex = [Math]::Max(-1, $refactorDefinition.State.SelectedIndex - 1) } } # clean unselected collection for ($unselectedIndex = $refactorDefinition.State.Unselected.Count - 1; $unselectedIndex -ge 0; $unselectedIndex--) { $path = (GenXdev.FileSystem\Expand-Path $refactorDefinition.State.Unselected[$unselectedIndex]) if (-not [IO.Path]::Exists($path)) { $null = $refactorDefinition.State.Unselected.RemoveAt($unselectedIndex) } if ($refactorDefinition.State.UnselectedIndex -lt $unselectedIndex) { $refactorDefinition.State.UnselectedIndex = [Math]::Max(-1, $refactorDefinition.State.UnselectedIndex - 1) } } } # handle llm selections if enabled if ((-not [string]::IsNullOrWhiteSpace($refactorDefinition.SelectionSettings.LLM.Prompt)) -and (!!$PerformLLMSelections -or !!$PerformAllLLMSelections)) { if (((-not $AskBeforeLLMSelection) -or ($refactorDefinition.State.Selected.Count -eq 0)) -and $refactorDefinition.State.Unselected.Count -ge 0) { $userAnswer = 1; if ($AskBeforeLLMSelection -and (-not $Script:_AlwaysRunLLMDuringRefactors)) { if ($Speak) { GenXdev.Console\Start-TextToSpeech "What to do next?" } $userAnswer = $host.ui.PromptForChoice( "There are only files left that need an LLM invocation", "What to do next?", @("&Allways run invocations", "&Run all invocation now", "&Run invocation", "&Don't invoke now"), 0 ) } if ($userAnswer -eq 0) { $Script:_AlwaysRunLLMDuringRefactors = $true } if ($userAnswer -eq 1) { $script:onlyFirst = $false } elseif ($userAnswer -eq 3) { continue } if ($RetryFailedLLMSelections) { $refactorDefinition.State.UnselectedIndex = -1; } } $refactorDefinition.State.UnselectedIndex++; $script:nextFile = $refactorDefinition.State.Unselected[$refactorDefinition.State.UnselectedIndex]; function goNext { $script:nextFile = $null; while ($refactorDefinition.State.UnselectedIndex -lt $refactorDefinition.State.Unselected.Count -and ($null -eq $script:nextFile -or ((-not [IO.File]::Exists($script:nextFile))))) { $refactorDefinition.State.UnselectedIndex = [Math]::Min( $refactorDefinition.State.UnselectedIndex + 1, $refactorDefinition.State.Unselected.Count - 1 ) if ($refactorDefinition.State.UnselectedIndex -lt $refactorDefinition.State.Unselected.Count) { $script:nextFile = $refactorDefinition.State.Unselected[$refactorDefinition.State.UnselectedIndex]; } else { $script:nextFile = $null; } } } goNext while (($null -ne $script:nextFile) -and ($script:last -ne $script:nextFile)) { try { # Create a string builder for verbose output $verboseOutput = [System.Text.StringBuilder]::new() # Create a scriptblock to capture verbose output $verboseScriptBlock = { param($Message) $null = $verboseOutput.AppendLine($Message) } # Register temporary verbose handler $null = Microsoft.PowerShell.Utility\Register-EngineEvent -SourceIdentifier "Verbose" -Action $verboseScriptBlock # Run the test and get the result $result = GenXdev.Coding\Test-RefactorLLMSelection ` -RefactorDefinition $refactorDefinition ` -Path ($script:nextFile) } catch { $result = $false $now = GenXdev.Console\UtcNow $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Error during LLM selection of file '$($script:nextFile)' : $($_.Exception.Message)" } ) } finally { # Clean up verbose handling $null = Microsoft.PowerShell.Utility\Unregister-Event -SourceIdentifier "Verbose" -ErrorAction SilentlyContinue } if ($result -eq $true) { $now = GenXdev.Console\UtcNow $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "File '$($script:nextFile)' was selected by LLM for refactoring`n$($verboseOutput.ToString())" } ) $indexRefactored = $refactorDefinition.State.Refactored.IndexOf(($script:nextFile)) $indexSelected = $refactorDefinition.State.Selected.IndexOf(($script:nextFile)) $indexUnselected = $refactorDefinition.State.Unselected.IndexOf(($script:nextFile)) if ($indexSelected -lt 0) { $null = $refactorDefinition.State.Selected.Add(($script:nextFile)) } if ($indexUnselected -ge 0) { $null = $refactorDefinition.State.Unselected.RemoveAt($indexUnselected) if ($indexUnselected -le $refactorDefinition.State.UnselectedIndex) { $refactorDefinition.State.UnselectedIndex = [Math]::Max(-1, $refactorDefinition.State.UnselectedIndex - 1) } } if ($indexRefactored -ge 0) { $refactorDefinition.State.Refactored.RemoveAt($indexRefactored) if ($indexRefactored -le $refactorDefinition.State.RefactoredIndex) { $refactorDefinition.State.RefactoredIndex = [Math]::Max(-1, $refactorDefinition.State.RefactoredIndex - 1) } } # persist changes to preferences if ($PSCmdlet.ShouldProcess( "Refactor set: $($refactorDefinition.Name)", "Save changes")) { $json = $refactorDefinition | Microsoft.PowerShell.Utility\ConvertTo-Json -Depth 10 -Compress $latestJson = (GenXdev.Data\Get-GenXdevPreference ` -Name "refactor_set_$($refactorDefinition.Name)" ` -PreferencesDatabasePath $PreferencesDatabasePath ` -ErrorAction SilentlyContinue ) if ($null -eq $latestJson) { Microsoft.PowerShell.Utility\Write-Warning "Refactor set has been deleted" break; } $latest = $latestJson | Microsoft.PowerShell.Utility\ConvertFrom-Json -ErrorAction SilentlyContinue if ($null -ne $latest -and ($latest.State.LastUpdated -gt $refactorDefinition.State.LastUpdated)) { $latest.State = $refactorDefinition.State; $latest.Log = $refactorDefinition.Log; $refactorDefinition = $latest; } $now = GenXdev.Console\UtcNow $refactorDefinition.State.LastUpdated = $now $json = $refactorDefinition | Microsoft.PowerShell.Utility\ConvertTo-Json -Depth 10 -Compress GenXdev.Data\Set-GenXdevPreference ` -Name "refactor_set_$($refactorDefinition.Name)" ` -Value $json ` -PreferencesDatabasePath $PreferencesDatabasePath ` -ErrorAction SilentlyContinue } if ($script:onlyFirst) { break } } else { $now = GenXdev.Console\UtcNow $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "File '$($script:nextFile)' was NOT selected by LLM for refactoring`n$($verboseOutput.ToString())" } ) } $script:last = $script:nextFile goNext } } # update state and persist changes if modifications were made if (($null -ne $refactorDefinition) -and ($refactorDefinition -is [GenXdev.Helpers.RefactorDefinition])) { Microsoft.PowerShell.Utility\Write-Verbose ("Updating refactor set state with $script:filesAdded added " + "and $script:filesRemoved removed") # $totalFilesLeft = ( # ($refactorDefinition.State.Unselected.Count - 1) - # $refactorDefinition.State.UnselectedIndex # ) + ( # ($refactorDefinition.State.Selected.Count - 1) - # $refactorDefinition.State.SelectedIndex # ) + ( # ($refactorDefinition.State.Refactored.Count - 1) - # $refactorDefinition.State.RefactoredIndex # ); $totalFilesDone = ( $refactorDefinition.State.UnselectedIndex + 1 ) + ( $refactorDefinition.State.SelectedIndex + 1 ) + ( $refactorDefinition.State.RefactoredIndex + 1 ); $totalFiles = ( $refactorDefinition.State.Unselected.Count ) + ( $refactorDefinition.State.Selected.Count ) + ( $refactorDefinition.State.Refactored.Count ) # calculate and update completion percentage $refactorDefinition.State.PercentageComplete = [System.Math]::Min(100, [Math]::Round( (100 * $totalFilesDone) / [Math]::Max(1, $totalFiles), 0 )) $now = GenXdev.Console\UtcNow if ($script:filesAdded -gt 0 -or $script:filesRemoved -gt 0) { # log status update $refactorDefinition.Log.Add( [GenXdev.Helpers.RefactorLogItem]@{ Timestamp = $now Message = "Refactor set updated, $script:filesAdded files added, " + "$script:filesRemoved files removed, " + "($($refactorDefinition.State.PercentageComplete)% " + "complete)" } ) } # persist changes to preferences if ($PSCmdlet.ShouldProcess( "Refactor set: $($refactorDefinition.Name)", "Save changes")) { $latestJson = (GenXdev.Data\Get-GenXdevPreference ` -Name "refactor_set_$($refactorDefinition.Name)" ` -PreferencesDatabasePath $PreferencesDatabasePath ` -ErrorAction SilentlyContinue ) if ($null -eq $latestJson) { Microsoft.PowerShell.Utility\Write-Warning "Refactor set has been deleted" break; } $latest = $latestJson | Microsoft.PowerShell.Utility\ConvertFrom-Json -ErrorAction SilentlyContinue if ($null -ne $latest -and ($latest.State.LastUpdated -lt $refactorDefinition.State.LastUpdated)) { $latest.State = $refactorDefinition.State; $latest.Log = $refactorDefinition.Log; $refactorDefinition = $latest; } $now = GenXdev.Console\UtcNow $refactorDefinition.State.LastUpdated = $now $json = $refactorDefinition | Microsoft.PowerShell.Utility\ConvertTo-Json -Depth 10 -Compress GenXdev.Data\Set-GenXdevPreference ` -Name "refactor_set_$($refactorDefinition.Name)" ` -Value $json ` -PreferencesDatabasePath $PreferencesDatabasePath ` -ErrorAction SilentlyContinue } Microsoft.PowerShell.Utility\Write-Verbose "Refactor set updated successfully" } } } end { } } ############################################################################### |