Initial server source import
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateRange(15, 10080)]
|
||||
[int]$MinAgeMinutes = 120,
|
||||
|
||||
[switch]$Apply
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
throw 'Docker development copy: runtime control is disabled until container isolation is ready. See DOCKER_MIGRATION.md.'
|
||||
$now = Get-Date
|
||||
$agentVitePattern = 'AgentUI_2\.01.*frontend-next.*vite\\bin\\vite\.js'
|
||||
$npxVitePattern = 'npx-cli\.js.*\bvite\b'
|
||||
$agentEsbuildPattern = 'AgentUI_2\.01.*frontend-next.*@esbuild'
|
||||
|
||||
function Get-VitePort {
|
||||
param([string]$CommandLine)
|
||||
|
||||
if ($CommandLine -match '--port\s+(\d+)') {
|
||||
return $matches[1]
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
$processes = @(Get-CimInstance Win32_Process)
|
||||
$agentNodes = @(
|
||||
$processes | Where-Object {
|
||||
$_.Name -eq 'node.exe' -and [string]$_.CommandLine -match $agentVitePattern
|
||||
}
|
||||
)
|
||||
$ports = @{}
|
||||
foreach ($process in $agentNodes) {
|
||||
$port = Get-VitePort ([string]$process.CommandLine)
|
||||
if ($port) {
|
||||
$ports[$port] = $true
|
||||
}
|
||||
}
|
||||
$npxNodes = @(
|
||||
$processes | Where-Object {
|
||||
if ($_.Name -ne 'node.exe' -or [string]$_.CommandLine -notmatch $npxVitePattern) {
|
||||
return $false
|
||||
}
|
||||
$port = Get-VitePort ([string]$_.CommandLine)
|
||||
return $port -and $ports.ContainsKey($port)
|
||||
}
|
||||
)
|
||||
|
||||
$connectedPids = @{}
|
||||
try {
|
||||
Get-NetTCPConnection -State Established -ErrorAction Stop | ForEach-Object {
|
||||
$connectedPids[[int]$_.OwningProcess] = $true
|
||||
}
|
||||
} catch {
|
||||
throw "Refusing cleanup because established TCP connections could not be inspected: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
$protectedPorts = @{}
|
||||
$newestAgent = $agentNodes | Sort-Object CreationDate -Descending | Select-Object -First 1
|
||||
if ($newestAgent) {
|
||||
$newestPort = Get-VitePort ([string]$newestAgent.CommandLine)
|
||||
if ($newestPort) {
|
||||
$protectedPorts[$newestPort] = 'newest AgentUI Vite instance'
|
||||
}
|
||||
}
|
||||
foreach ($process in @($agentNodes + $npxNodes)) {
|
||||
$port = Get-VitePort ([string]$process.CommandLine)
|
||||
if (-not $port) {
|
||||
continue
|
||||
}
|
||||
$created = [datetime]$process.CreationDate
|
||||
$ageMinutes = ($now - $created).TotalMinutes
|
||||
if ($ageMinutes -lt $MinAgeMinutes) {
|
||||
$protectedPorts[$port] = "younger than $MinAgeMinutes minutes"
|
||||
}
|
||||
if ($connectedPids.ContainsKey([int]$process.ProcessId)) {
|
||||
$protectedPorts[$port] = 'has an established TCP connection'
|
||||
}
|
||||
}
|
||||
|
||||
$targetAgentNodes = @(
|
||||
$agentNodes | Where-Object {
|
||||
$port = Get-VitePort ([string]$_.CommandLine)
|
||||
$port -and -not $protectedPorts.ContainsKey($port)
|
||||
}
|
||||
)
|
||||
$targetPorts = @{}
|
||||
$targetAgentPids = @{}
|
||||
foreach ($process in $targetAgentNodes) {
|
||||
$targetPorts[(Get-VitePort ([string]$process.CommandLine))] = $true
|
||||
$targetAgentPids[[int]$process.ProcessId] = $true
|
||||
}
|
||||
$targetNpxNodes = @(
|
||||
$npxNodes | Where-Object {
|
||||
$port = Get-VitePort ([string]$_.CommandLine)
|
||||
$port -and $targetPorts.ContainsKey($port)
|
||||
}
|
||||
)
|
||||
$targetEsbuild = @(
|
||||
$processes | Where-Object {
|
||||
$_.Name -eq 'esbuild.exe' -and
|
||||
[string]$_.ExecutablePath -match $agentEsbuildPattern -and
|
||||
$targetAgentPids.ContainsKey([int]$_.ParentProcessId)
|
||||
}
|
||||
)
|
||||
$targetIds = @(
|
||||
@($targetEsbuild + $targetAgentNodes + $targetNpxNodes).ProcessId |
|
||||
Where-Object { $null -ne $_ -and [int]$_ -gt 0 } |
|
||||
ForEach-Object { [int]$_ } |
|
||||
Sort-Object -Unique
|
||||
)
|
||||
|
||||
Write-Output "AgentUI Vite instances: $($agentNodes.Count)"
|
||||
Write-Output "Protected ports: $($protectedPorts.Count)"
|
||||
Write-Output "Stale ports: $($targetPorts.Count)"
|
||||
Write-Output "Target processes: $($targetIds.Count)"
|
||||
|
||||
if (-not $Apply) {
|
||||
Write-Output 'Dry run only. Re-run with -Apply to terminate the exact stale process set.'
|
||||
exit 0
|
||||
}
|
||||
|
||||
if ($targetIds.Count -eq 0) {
|
||||
Write-Output 'No stale AgentUI Vite processes require cleanup.'
|
||||
exit 0
|
||||
}
|
||||
|
||||
Stop-Process -Id $targetIds -Force -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
$remaining = @(
|
||||
Get-CimInstance Win32_Process | Where-Object {
|
||||
$targetIds -contains [int]$_.ProcessId -and (
|
||||
($_.Name -eq 'node.exe' -and (
|
||||
[string]$_.CommandLine -match $agentVitePattern -or
|
||||
[string]$_.CommandLine -match $npxVitePattern
|
||||
)) -or
|
||||
($_.Name -eq 'esbuild.exe' -and [string]$_.ExecutablePath -match $agentEsbuildPattern)
|
||||
)
|
||||
}
|
||||
)
|
||||
if ($remaining.Count -gt 0) {
|
||||
Write-Error "Cleanup left $($remaining.Count) exact target process(es) running."
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Output "Terminated $($targetIds.Count) stale AgentUI Vite process(es)."
|
||||
Reference in New Issue
Block a user