assists/pwsh-assist.ps1

function global:f(
    [ValidateScript({
        (IsEnable $_) -or (IsDisable $_) -or (!$_)
    })]
    $switch
) {
    if ($switch -ne $null) {
        $Global:FountAssist.Enabled = IsEnable $switch
        Write-Host "fount assist is $(@('disabled','enabled')[$Global:FountAssist.Enabled])"
        return
    }
    $requst = @{
        charname                 = $Global:FountAssist.AssistCharname
        UserCharname             = $Global:FountAssist.UserCharname
        shelltype                = "powershell"
        shellhistory             = $Global:FountAssist.shellhistory
        command_now              = $Global:FountAssist.last_commaned.command
        command_error            = $Error | Select-Object -SkipLast $Global:FountAssist.HistoryErrorCount | Out-String -Width 65536
        rejected_commands        = $Global:FountAssist.rejected_commands
        chat_scoped_char_memorys = $Global:FountAssist.chat_scoped_char_memorys
        pwd                      = "$pwd"
    }
    $result = Invoke-FountShell $Global:FountAssist.FountUsername 'shellassist' $requst
    if ($result.chat_scoped_char_memorys) {
        $Global:FountAssist.chat_scoped_char_memorys = $result.chat_scoped_char_memorys
    }
    if ($result.shellhistory) {
        $Global:FountAssist.shellhistory = [System.Collections.ArrayList]$result.shellhistory
    }

    if ($result.content -or $result.recommend_command) {
        Write-Host
    }
    if ($result.content) {
        $Global:FountAssist.shellhistory.Add(@{
            name      = $result.name
            avatar    = $result.avatar
            role      = "char"
            content   = $result.content
            extension = $result.extension
        }) | Out-Null
        Write-Host $result.content
    }
    if ($result.recommend_command) {
        # 显示并询问是否执行或重新推荐
        Write-Host "use `"" -NoNewline
        Write-Host $result.recommend_command -ForegroundColor Yellow -NoNewline
        Write-Host "`" as command? " -NoNewline
        Write-Host "[" -NoNewline
        Write-Host "enter" -ForegroundColor Green -NoNewline
        Write-Host "/" -NoNewline
        Write-Host "n" -ForegroundColor Blue -NoNewline
        Write-Host " (next)/" -NoNewline
        Write-Host "ctrl+c" -ForegroundColor Red -NoNewline
        Write-Host "]"
        [console]::TreatControlCAsInput = $true
        while ($true) {
            Start-Sleep -Milliseconds 100
            if ([console]::KeyAvailable) {
                $key = [console]::ReadKey($true)
                if ($key.Key -eq "Enter") {
                    [console]::TreatControlCAsInput = $false
                    [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($result.recommend_command)
                    $StartExecutionTime = Get-Date
                    Invoke-Expression $result.recommend_command | Out-String | Write-Host
                    $EndExecutionTime = Get-Date
                    [PSCustomObject](@{
                        CommandLine        = $result.recommend_command
                        ExecutionStatus    = "Completed"
                        StartExecutionTime = $StartExecutionTime
                        EndExecutionTime   = $EndExecutionTime
                    }) | Add-History
                    return
                }
                if ($key.Key -eq "N") {
                    $Global:FountAssist.rejected_commands.Add($result.recommend_command) | Out-Null
                    f
                    return
                }
                if ($key.Key -eq "C" -and $key.Modifiers -eq "Control") {
                    [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
                    return
                }
            }
        }
    }
}
$Global:FountAssist.HistoryErrorCount = $Error.Count
Set-PSReadLineKeyHandler -Key Enter -ScriptBlock {
    $line = $null
    $cursor = $null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

    if ($Global:FountAssist.last_commaned) {
        $Global:FountAssist.last_commaned.output = $($ans | Out-String) -join "`n"
        $Global:FountAssist.last_commaned.error = $Error | Select-Object -SkipLast $Global:FountAssist.HistoryErrorCount | Out-String -Width 65536
        $Global:FountAssist.shellhistory.Add($Global:FountAssist.last_commaned) | Out-Null
    }

    $Global:FountAssist.last_commaned = @{
        command = $line
        time    = Get-Date
    }

    # keep shellhistory's last 30 records
    while ($Global:FountAssist.shellhistory.Count -gt 30) {
        $Global:FountAssist.shellhistory.RemoveAt(0)
    }
    $Global:FountAssist.rejected_commands = [System.Collections.ArrayList]@()
    $Global:FountAssist.HistoryErrorCount = $Error.Count

    if (!$Global:FountAssist.Enabled) {
        [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
        return
    }

    $parseError = $null
    $ast = [System.Management.Automation.Language.Parser]::ParseInput($line, [ref]$null, [ref]$parseError)

    $bad_expr = $false
    if ($parseError) {
        [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
        return
    }
    $Commands = $ast.FindAll({param($ast) $ast -is [System.Management.Automation.Language.CommandAst] }, $true)
    foreach ($Command in $Commands) {
        if (!(Get-Command $Command.CommandElements[0] -ErrorAction Ignore)) {
            $bad_expr = $true
            break
        }
    }

    #若当前表达式是合法ps脚本但不是合法命令
    if ($bad_expr -and !$PSDebugContext) {
        f
        $YIndexBackup = $host.UI.RawUI.CursorPosition.Y
        [Microsoft.PowerShell.PSConsoleReadLine]::CancelLine()
        Write-Host "`b`b " -NoNewline
        try {
            if ($host.UI.RawUI.CursorPosition.Y -ne $YIndexBackup) {
                $host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates 0, $YIndexBackup
            }
        } catch { }
        Write-Host
    }
    else {
        [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
    }
}
if (-not $Global:FountAssist.OriginalPrompt) {
    $Global:FountAssist.OriginalPrompt = Get-Content function:\prompt
}
function global:prompt {
    if (-not $PSDebugContext -and -not $? -and $Global:FountAssist.NonZeroReturnWhiteList -notcontains (($expr_now -split '\s')[0])) {
        if ($Global:FountAssist.Enabled) {
            try { f } catch {}
        }
    }
    & $Global:FountAssist.OriginalPrompt
}