Public/Select-CopilotSession.ps1
|
function Invoke-CopilotSessionPicker { param( [Parameter(Mandatory)] [object[]]$Sessions ) $choices = @($Sessions | ForEach-Object { [PSCustomObject]@{ Id = $_.Id Name = $_.Name Summary = $_.Summary Repository = $_.Repository Branch = $_.Branch Cwd = $_.Cwd UpdatedAt = $_.UpdatedAt EventCount = $_.EventCount Session = $_ } }) if (Get-Command Out-ConsoleGridView -ErrorAction SilentlyContinue) { $selected = $choices | Out-ConsoleGridView -OutputMode Single return $selected.Session } if (Get-Command Out-GridView -ErrorAction SilentlyContinue) { $selected = $choices | Out-GridView -Title 'Select Copilot session to resume' -PassThru return $selected.Session } Write-Host 'Select a Copilot session to resume:' -ForegroundColor Yellow Write-Host '' for ($i = 0; $i -lt $choices.Count; $i++) { $choice = $choices[$i] $updatedAt = if ($choice.UpdatedAt) { $choice.UpdatedAt.LocalDateTime } else { '(unknown)' } Write-Host (" [{0}] {1}" -f ($i + 1), $choice.Summary) -ForegroundColor ($(if ($i -eq 0) { 'Cyan' } else { 'Gray' })) Write-Host (" Repo: {0} Branch: {1}" -f ($choice.Repository ?? '(unknown)'), ($choice.Branch ?? '(unknown)')) -ForegroundColor DarkGray Write-Host (" Cwd: {0}" -f ($choice.Cwd ?? '(unknown)')) -ForegroundColor DarkGray Write-Host (" Updated: {0} Events: {1}" -f $updatedAt, $choice.EventCount) -ForegroundColor DarkGray } Write-Host ' [Q] Cancel' -ForegroundColor Green Write-Host '' do { Write-Host "Select session [1-$($choices.Count)/Q]: " -NoNewline -ForegroundColor Yellow $selection = Read-Host if ($selection -in @('Q', 'q')) { return $null } $number = $selection -as [int] } while ($null -eq $number -or $number -lt 1 -or $number -gt $choices.Count) return $choices[$number - 1].Session } function Select-CopilotSession { <# .SYNOPSIS Selects and resumes a Copilot CLI session from all sessions on the machine. .DESCRIPTION Lists sessions from Get-CopilotSession -All, optionally filters them by ID, repository, or branch, and resumes the selected session by delegating to Resume-CopilotSession. When filters and -First resolve to exactly one session, the picker is skipped. Otherwise, the command prefers Out-ConsoleGridView, then Out-GridView, then a numbered console prompt. By default the resume runs from the session's recorded Cwd so sessions from other directories restore their original workspace context. Use -StayInDirectory to resume from the current directory instead. .PARAMETER Id Select a session by ID. Wildcards are supported. .PARAMETER Repository Filter sessions by repository. Wildcards are supported. .PARAMETER Branch Filter sessions by branch. Wildcards are supported. .PARAMETER First Take the first N matching sessions after sorting by UpdatedAt descending. Use -First 1 to resume the most recent matching session without a picker. .PARAMETER StayInDirectory Resume the chosen session from the current directory instead of changing to the session's recorded Cwd. .PARAMETER Prompt Optional prompt to execute in autopilot mode within the resumed session. .PARAMETER RemainingArgs Any additional arguments passed through to Resume-CopilotSession. .EXAMPLE Select-CopilotSession # Shows a picker over all Copilot sessions and resumes the selected one. .EXAMPLE Select-CopilotSession -Repository 'shmuelie/powershell-modules' -Branch 'main' -First 1 # Resumes the most recent matching session without opening the picker. .EXAMPLE Select-CopilotSession -Id 'abc-*' -WhatIf # Shows which matching session would be resumed without launching Copilot. #> [CmdletBinding(SupportsShouldProcess)] param( [SupportsWildcards()] [ValidateNotNullOrEmpty()] [string]$Id, [SupportsWildcards()] [ValidateNotNullOrEmpty()] [string]$Repository, [SupportsWildcards()] [ValidateNotNullOrEmpty()] [string]$Branch, [ValidateRange(1, [int]::MaxValue)] [int]$First, [switch]$StayInDirectory, [string]$Prompt, [Parameter(ValueFromRemainingArguments)] [string[]]$RemainingArgs ) $sessions = @(Get-CopilotSession -All | Sort-Object UpdatedAt -Descending) if ($Id) { $sessions = @($sessions | Where-Object { $_.Id -like $Id }) } if ($Repository) { $sessions = @($sessions | Where-Object { $_.Repository -like $Repository }) } if ($Branch) { $sessions = @($sessions | Where-Object { $_.Branch -like $Branch }) } if ($First) { $sessions = @($sessions | Select-Object -First $First) } if ($sessions.Count -eq 0) { Write-Error 'No Copilot sessions matched the specified criteria.' return } $session = if ($sessions.Count -eq 1) { $sessions[0] } else { if ($WhatIfPreference) { Write-Error 'Multiple Copilot sessions matched. Refine the filters or use -First 1 to preview without opening the picker.' return } Invoke-CopilotSessionPicker -Sessions $sessions } if ($null -eq $session) { return } $target = "$($session.Summary) ($($session.Id))" $action = if ($StayInDirectory) { 'Resume Copilot session from current directory' } else { "Resume Copilot session from $($session.Cwd)" } if (-not $PSCmdlet.ShouldProcess($target, $action)) { return } $resumeParams = @{ Id = $session.Id } if ($Prompt) { $resumeParams['Prompt'] = $Prompt } if ($StayInDirectory) { if ($RemainingArgs) { Resume-CopilotSession @resumeParams -RemainingArgs $RemainingArgs } else { Resume-CopilotSession @resumeParams } return } if (-not $session.Cwd -or -not (Test-Path -LiteralPath $session.Cwd -PathType Container)) { Write-Error "Session '$($session.Id)' has no existing Cwd to resume from: $($session.Cwd)" return } Push-Location -LiteralPath $session.Cwd try { if ($RemainingArgs) { Resume-CopilotSession @resumeParams -RemainingArgs $RemainingArgs } else { Resume-CopilotSession @resumeParams } } finally { Pop-Location } } |