param( [Parameter(Mandatory=$true, Position=0)][string]$Prompt, [string]$TargetHost = "100.101.128.33", [int]$Port = 4096, [string]$SessionId = "", [string]$Title = "ask-remote $(Get-Date -Format 'yyyyMMdd-HHmmss')", [string]$Password = $env:OPENCODE_SERVER_PASSWORD, [string]$ModelProvider = "9router", [string]$ModelID = "oc/deepseek-v4-flash-free", [int]$TimeoutSec = 300 ) $base = "http://${TargetHost}:${Port}" $headers = @{} if ($Password) { $headers.Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("opencode:$Password")) } function New-Session { $body = @{ title = $Title } | ConvertTo-Json Invoke-RestMethod -Method Post -Uri "$base/session" -Headers $headers -ContentType "application/json" -Body $body -TimeoutSec $TimeoutSec } function Send-Prompt([string]$sid) { $body = @{ parts = @(@{ type = "text"; text = $Prompt }); model = @{ providerID = $ModelProvider; modelID = $ModelID } } | ConvertTo-Json -Depth 5 Invoke-RestMethod -Method Post -Uri "$base/session/$sid/prompt_async" -Headers $headers -ContentType "application/json" -Body $body -TimeoutSec 30 | Out-Null for ($i = 0; $i -lt 60; $i++) { Start-Sleep -Seconds 5 $msgs = (Invoke-RestMethod -Uri "$base/session/$sid/message" -Headers $headers -TimeoutSec 30) $reply = $msgs | Where-Object { $_.info.role -eq "assistant" -and ($_.parts | Where-Object { $_.type -eq "text" -and $_.text }) } | Select-Object -Last 1 if ($reply) { $text = ($reply.parts | Where-Object { $_.type -eq "text" } | ForEach-Object { $_.text }) -join "`n" return [pscustomobject]@{ sessionId = $sid; text = $text } } } throw "Timeout menunggu balasan remote (>300s)" } if (-not $SessionId) { $s = New-Session $SessionId = $s.id } try { $out = Send-Prompt $SessionId "SESSION: $($out.sessionId)" "---REPLY---" $out.text } catch { "ERROR: $($_.Exception.Message)" if ($_.Exception.Response) { try { $stream = $_.Exception.Response.GetResponseStream() $reader = New-Object IO.StreamReader($stream) $reader.ReadToEnd() } catch {} } }