Public/Realtime/Disconnect-RealtimeSession.ps1

function Disconnect-RealtimeSession {
    [CmdletBinding()]
    param ()

    begin {}
    process {}
    end {
        if ($null -eq $script:WebSocketClient) {
            Write-Warning 'Could not find session.'
        }
        elseif ($script:WebSocketClient.State -ne [System.Net.WebSockets.WebSocketState]::Open) {
            Write-Warning 'Session already closed.'
        }
        else {
            Write-Verbose 'Closing session.'
            try {
                # Close with timeout
                $_cts = [System.Threading.CancellationTokenSource]::new()
                $_cts.CancelAfter([timespan]::FromSeconds(5))
                $closeTask = $script:WebSocketClient.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, '', $_cts.Token)

                # Wait for close
                do {
                    Start-Sleep -Milliseconds 100
                } while (-not $closetask.IsCompleted)
                Write-Verbose 'Session closed.'
                Write-Host 'Session closed.' -ForegroundColor Green
            }
            finally {
                if ($null -ne $_cts) {
                    $_cts.Dispose()
                }
                if ($null -ne $script:WebSocketClient) {
                    $script:WebSocketClient.Dispose()
                    $script:WebSocketClient = $null
                }
            }
        }

        if ($null -ne $script:ReceiveMessageJob) {
            try {
                $script:ReceiveMessageJob.Stop()
                $script:ReceiveMessageJob.Dispose()
                $script:ReceiveMessageJob = $null
            }
            catch {
                Write-Error -Exception $_.Exception
            }
        }

        if (Test-Path -LiteralPath 'Function:/Stop-RealtimeSessionAudioOutput') {
            PSOpenAI\Stop-RealtimeSessionAudioOutput
        }

        if (Test-Path -LiteralPath 'Function:/Stop-RealtimeSessionAudioInput') {
            PSOpenAI\Stop-RealtimeSessionAudioInput
        }

        $global:PSRealtimeSessionLock = $false
    }
}