mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 07:03:15 +08:00
This aligns Weixin/WhatsApp with admin-managed model routing by adding channel/account-level specialist controls, improves OSS startup resilience by skipping missing sidecars gracefully, and refreshes runbook/readme guidance for the new default behavior and Weixin OpenAI-key silent handling. Made-with: Cursor
151 lines
5.2 KiB
PowerShell
151 lines
5.2 KiB
PowerShell
param(
|
|
[string]$BindHost = "127.0.0.1",
|
|
[int]$Port = 8787,
|
|
[switch]$WithoutWeixin = $false,
|
|
[switch]$WithoutWhatsApp = $false,
|
|
[switch]$WithWikiWorker = $false,
|
|
[string]$WeixinChannelId = "oclaw-weixin",
|
|
[string]$WhatsAppChannelId = "whatsapp"
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
function Write-Step([string]$msg) {
|
|
Write-Host "==> $msg" -ForegroundColor Cyan
|
|
}
|
|
|
|
function Warn([string]$msg) {
|
|
Write-Host "[WARN] $msg" -ForegroundColor Yellow
|
|
}
|
|
|
|
$runDir = Join-Path $PSScriptRoot ".run"
|
|
$null = New-Item -ItemType Directory -Force -Path $runDir -ErrorAction SilentlyContinue
|
|
$gwPidFile = Join-Path $runDir "gateway.pid"
|
|
$desktopPidFile = Join-Path $runDir "desktop.pid"
|
|
|
|
Write-Step "URLs"
|
|
Write-Host "Admin: http://$BindHost`:$Port/admin"
|
|
Write-Host "Chat: http://$BindHost`:$Port/chat"
|
|
Write-Host "WS: ws://$BindHost`:$Port/ws"
|
|
Write-Host ""
|
|
|
|
Write-Step "PID files"
|
|
if (Test-Path $gwPidFile) {
|
|
$gwPid = (Get-Content $gwPidFile -ErrorAction SilentlyContinue | Select-Object -First 1)
|
|
Write-Host "gateway.pid: $gwPidFile => $gwPid"
|
|
} else {
|
|
Warn "gateway.pid not found: $gwPidFile"
|
|
}
|
|
if (Test-Path $desktopPidFile) {
|
|
$deskPid = (Get-Content $desktopPidFile -ErrorAction SilentlyContinue | Select-Object -First 1)
|
|
Write-Host "desktop.pid: $desktopPidFile => $deskPid"
|
|
} else {
|
|
Warn "desktop.pid not found: $desktopPidFile"
|
|
}
|
|
Write-Host ""
|
|
|
|
Write-Step "Port listener"
|
|
try {
|
|
$conns = Get-NetTCPConnection -LocalPort $Port -State Listen -ErrorAction SilentlyContinue
|
|
if (-not $conns) {
|
|
Warn "No listener on port $Port"
|
|
exit 0
|
|
}
|
|
$pids = $conns | Select-Object -ExpandProperty OwningProcess -Unique
|
|
Write-Host "Listening on port $Port; OwningProcess: $($pids -join ', ')"
|
|
|
|
# Self-heal: if we have a single owning pid and no gateway.pid, write it back.
|
|
if (-not (Test-Path $gwPidFile)) {
|
|
$pidList = @()
|
|
foreach ($x in @($pids)) {
|
|
$n = 0
|
|
if ([int]::TryParse([string]$x, [ref]$n) -and $n -gt 0) {
|
|
$pidList += $n
|
|
}
|
|
}
|
|
if ($pidList.Count -eq 1) {
|
|
$procId = [int]$pidList[0]
|
|
try {
|
|
$null = Get-Process -Id $procId -ErrorAction Stop
|
|
Set-Content -Path $gwPidFile -Value "$procId" -Encoding ascii
|
|
Write-Host "Wrote gateway.pid => $procId" -ForegroundColor Green
|
|
} catch {
|
|
Warn "Cannot verify process for PID=$procId; not writing pid file."
|
|
}
|
|
} else {
|
|
# Heuristic: try to pick the gateway python/uvicorn process.
|
|
$candidates = @()
|
|
foreach ($p in $pidList) {
|
|
try {
|
|
$proc = Get-Process -Id $p -ErrorAction Stop
|
|
$name = [string]$proc.ProcessName
|
|
} catch {
|
|
continue
|
|
}
|
|
$cmd = ""
|
|
try {
|
|
$wmi = Get-CimInstance Win32_Process -Filter "ProcessId=$p" -ErrorAction SilentlyContinue
|
|
if ($wmi -and $wmi.CommandLine) { $cmd = [string]$wmi.CommandLine }
|
|
} catch {
|
|
$cmd = ""
|
|
}
|
|
if ($cmd) {
|
|
$low = ([string]$cmd).ToLowerInvariant()
|
|
} else {
|
|
$low = ""
|
|
}
|
|
$score = 0
|
|
if ($name -match "python") { $score += 2 }
|
|
if ($low -match "uvicorn") { $score += 2 }
|
|
if ($low -match "src\.ops") { $score += 2 }
|
|
if ($low -match "gateway\s+start") { $score += 2 }
|
|
if ($low -match "fastapi_app") { $score += 1 }
|
|
$candidates += [pscustomobject]@{ Pid = [int]$p; Name = $name; Score = [int]$score; Cmd = $cmd }
|
|
}
|
|
$best = $candidates | Sort-Object -Property Score -Descending | Select-Object -First 1
|
|
if ($best -and $best.Score -ge 2) {
|
|
try {
|
|
$null = Get-Process -Id $best.Pid -ErrorAction Stop
|
|
Set-Content -Path $gwPidFile -Value "$($best.Pid)" -Encoding ascii
|
|
Write-Host "Wrote gateway.pid => $($best.Pid) ($($best.Name))" -ForegroundColor Green
|
|
} catch {
|
|
Warn "Cannot verify process for PID=$($best.Pid); not writing pid file."
|
|
}
|
|
} else {
|
|
Warn "Multiple owning processes for port $Port; cannot confidently pick gateway PID."
|
|
}
|
|
}
|
|
}
|
|
} catch {
|
|
Warn "Get-NetTCPConnection failed: $($_.Exception.Message)"
|
|
}
|
|
|
|
if (-not $WithoutWeixin) {
|
|
Write-Host ""
|
|
Write-Step "Weixin sidecar"
|
|
try {
|
|
& "$PSScriptRoot/weixin_status.ps1" -ChannelId $WeixinChannelId
|
|
} catch {
|
|
Warn "weixin status failed: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
if (-not $WithoutWhatsApp) {
|
|
Write-Host ""
|
|
Write-Step "WhatsApp sidecar"
|
|
try {
|
|
& "$PSScriptRoot/whatsapp_status.ps1" -ChannelId $WhatsAppChannelId
|
|
} catch {
|
|
Warn "whatsapp status failed: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
if ($WithWikiWorker) {
|
|
Write-Host ""
|
|
Write-Step "Wiki worker"
|
|
try {
|
|
& "$PSScriptRoot/status_wiki_worker.ps1"
|
|
} catch {
|
|
Warn "wiki worker status failed: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|