patchwarden 0.6.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PatchWarden-Control-Tray.cmd +11 -0
- package/PatchWarden-Control.cmd +6 -0
- package/PatchWarden-Desktop.cmd +5 -0
- package/PatchWarden.cmd +1 -1
- package/README.en.md +112 -24
- package/README.md +36 -25
- package/Restart-PatchWarden-Control.cmd +6 -0
- package/Stop-PatchWarden.cmd +11 -0
- package/dist/agents/agentRouter.d.ts +40 -0
- package/dist/agents/agentRouter.js +95 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +6 -2
- package/dist/controlCenter.d.ts +14 -0
- package/dist/controlCenter.js +2015 -0
- package/dist/doctor.js +35 -4
- package/dist/goal/acceptanceEngine.d.ts +62 -0
- package/dist/goal/acceptanceEngine.js +103 -0
- package/dist/goal/acceptanceTemplate.d.ts +10 -0
- package/dist/goal/acceptanceTemplate.js +104 -0
- package/dist/goal/goalGraph.d.ts +58 -0
- package/dist/goal/goalGraph.js +189 -0
- package/dist/goal/goalProgress.d.ts +81 -0
- package/dist/goal/goalProgress.js +216 -0
- package/dist/goal/goalStatus.d.ts +60 -0
- package/dist/goal/goalStatus.js +137 -0
- package/dist/goal/goalStore.d.ts +79 -0
- package/dist/goal/goalStore.js +211 -0
- package/dist/goal/handoffExport.d.ts +34 -0
- package/dist/goal/handoffExport.js +183 -0
- package/dist/goal/subgoalSync.d.ts +40 -0
- package/dist/goal/subgoalSync.js +72 -0
- package/dist/goal/worktreeManager.d.ts +96 -0
- package/dist/goal/worktreeManager.js +292 -0
- package/dist/logging.d.ts +44 -0
- package/dist/logging.js +68 -0
- package/dist/release/releaseGate.d.ts +99 -0
- package/dist/release/releaseGate.js +475 -0
- package/dist/runner/postTaskCleanup.d.ts +13 -0
- package/dist/runner/postTaskCleanup.js +147 -0
- package/dist/runner/runTask.js +50 -10
- package/dist/security/discoveryTokenStore.d.ts +62 -0
- package/dist/security/discoveryTokenStore.js +100 -0
- package/dist/security/toolInvocationGuard.d.ts +35 -0
- package/dist/security/toolInvocationGuard.js +153 -0
- package/dist/smoke-test.js +18 -10
- package/dist/taskRuntime.d.ts +17 -0
- package/dist/test/unit/acceptance-engine.test.d.ts +1 -0
- package/dist/test/unit/acceptance-engine.test.js +228 -0
- package/dist/test/unit/agent-router.test.d.ts +1 -0
- package/dist/test/unit/agent-router.test.js +287 -0
- package/dist/test/unit/audit-checks.test.d.ts +1 -0
- package/dist/test/unit/audit-checks.test.js +350 -0
- package/dist/test/unit/diagnose-task.test.d.ts +1 -0
- package/dist/test/unit/diagnose-task.test.js +457 -0
- package/dist/test/unit/discovery-token-store.test.d.ts +1 -0
- package/dist/test/unit/discovery-token-store.test.js +139 -0
- package/dist/test/unit/goal-graph.test.d.ts +1 -0
- package/dist/test/unit/goal-graph.test.js +298 -0
- package/dist/test/unit/goal-progress.test.d.ts +1 -0
- package/dist/test/unit/goal-progress.test.js +381 -0
- package/dist/test/unit/goal-status.test.d.ts +1 -0
- package/dist/test/unit/goal-status.test.js +215 -0
- package/dist/test/unit/goal-store.test.d.ts +1 -0
- package/dist/test/unit/goal-store.test.js +253 -0
- package/dist/test/unit/goal-subgoal-task.test.d.ts +1 -0
- package/dist/test/unit/goal-subgoal-task.test.js +55 -0
- package/dist/test/unit/goal-tools-registry.test.d.ts +1 -0
- package/dist/test/unit/goal-tools-registry.test.js +190 -0
- package/dist/test/unit/handoff-export.test.d.ts +1 -0
- package/dist/test/unit/handoff-export.test.js +263 -0
- package/dist/test/unit/invoke-discovered-tool.test.d.ts +1 -0
- package/dist/test/unit/invoke-discovered-tool.test.js +167 -0
- package/dist/test/unit/logging.test.js +127 -5
- package/dist/test/unit/post-task-cleanup.test.d.ts +1 -0
- package/dist/test/unit/post-task-cleanup.test.js +48 -0
- package/dist/test/unit/reconcile-tasks.test.d.ts +1 -0
- package/dist/test/unit/reconcile-tasks.test.js +456 -0
- package/dist/test/unit/release-gate.test.d.ts +1 -0
- package/dist/test/unit/release-gate.test.js +242 -0
- package/dist/test/unit/safe-views.test.d.ts +1 -0
- package/dist/test/unit/safe-views.test.js +171 -0
- package/dist/test/unit/schema-drift-check.test.d.ts +1 -0
- package/dist/test/unit/schema-drift-check.test.js +175 -0
- package/dist/test/unit/subgoal-sync.test.d.ts +1 -0
- package/dist/test/unit/subgoal-sync.test.js +183 -0
- package/dist/test/unit/tool-invocation-guard.test.d.ts +1 -0
- package/dist/test/unit/tool-invocation-guard.test.js +432 -0
- package/dist/test/unit/tool-usage-stats.test.d.ts +1 -0
- package/dist/test/unit/tool-usage-stats.test.js +300 -0
- package/dist/test/unit/toolSearch.test.d.ts +1 -0
- package/dist/test/unit/toolSearch.test.js +571 -0
- package/dist/test/unit/worktree-manager.test.d.ts +1 -0
- package/dist/test/unit/worktree-manager.test.js +176 -0
- package/dist/tools/auditTask.d.ts +103 -1
- package/dist/tools/auditTask.js +461 -8
- package/dist/tools/cancelTask.js +1 -1
- package/dist/tools/checkReleaseGate.d.ts +21 -0
- package/dist/tools/checkReleaseGate.js +22 -0
- package/dist/tools/createTask.d.ts +18 -2
- package/dist/tools/createTask.js +29 -1
- package/dist/tools/diagnoseTask.d.ts +45 -0
- package/dist/tools/diagnoseTask.js +347 -0
- package/dist/tools/discardWorktree.d.ts +24 -0
- package/dist/tools/discardWorktree.js +27 -0
- package/dist/tools/discoverTools.d.ts +11 -0
- package/dist/tools/discoverTools.js +39 -0
- package/dist/tools/explainTool.d.ts +11 -0
- package/dist/tools/explainTool.js +21 -0
- package/dist/tools/getTaskSummary.js +2 -1
- package/dist/tools/goalSubgoalTask.d.ts +51 -0
- package/dist/tools/goalSubgoalTask.js +110 -0
- package/dist/tools/healthCheck.d.ts +1 -0
- package/dist/tools/healthCheck.js +5 -1
- package/dist/tools/invokeDiscoveredTool.d.ts +37 -0
- package/dist/tools/invokeDiscoveredTool.js +112 -0
- package/dist/tools/listTasks.d.ts +3 -1
- package/dist/tools/listTasks.js +14 -1
- package/dist/tools/mergeWorktree.d.ts +24 -0
- package/dist/tools/mergeWorktree.js +27 -0
- package/dist/tools/reconcileTasks.d.ts +41 -0
- package/dist/tools/reconcileTasks.js +352 -0
- package/dist/tools/registry.js +550 -0
- package/dist/tools/safeStatus.d.ts +31 -1
- package/dist/tools/safeStatus.js +43 -1
- package/dist/tools/safeViews.d.ts +256 -0
- package/dist/tools/safeViews.js +250 -0
- package/dist/tools/schemaDriftCheck.d.ts +46 -0
- package/dist/tools/schemaDriftCheck.js +80 -0
- package/dist/tools/toolCatalog.d.ts +4 -3
- package/dist/tools/toolCatalog.js +33 -11
- package/dist/tools/toolRegistry.d.ts +61 -0
- package/dist/tools/toolRegistry.js +724 -0
- package/dist/tools/toolSearch.d.ts +110 -0
- package/dist/tools/toolSearch.js +331 -0
- package/dist/tools/toolUsageStats.d.ts +41 -0
- package/dist/tools/toolUsageStats.js +116 -0
- package/dist/tools/waitForTask.js +1 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/watcherStatus.d.ts +29 -0
- package/dist/watcherStatus.js +92 -1
- package/docs/control-center/README.md +33 -0
- package/docs/control-center/control-center-daily-driver.md +211 -0
- package/docs/control-center/control-center-mvp.md +205 -0
- package/docs/control-center/control-center-phase2.md +159 -0
- package/docs/demo.md +3 -0
- package/docs/release-v0.6.4.md +45 -0
- package/examples/openai-tunnel/README.md +5 -5
- package/examples/openai-tunnel/tunnel-client.example.yaml +3 -3
- package/package.json +25 -16
- package/scripts/README.md +47 -0
- package/scripts/{brand-check.js → checks/brand-check.js} +2 -2
- package/scripts/checks/control-center-smoke.js +1098 -0
- package/scripts/{control-smoke.js → checks/control-smoke.js} +19 -5
- package/scripts/{doctor-smoke.js → checks/doctor-smoke.js} +2 -1
- package/scripts/{http-mcp-smoke.js → checks/http-mcp-smoke.js} +2 -2
- package/scripts/{lifecycle-smoke.js → checks/lifecycle-smoke.js} +25 -21
- package/scripts/{mcp-manifest-check.js → checks/mcp-manifest-check.js} +54 -7
- package/scripts/{mcp-smoke.js → checks/mcp-smoke.js} +40 -11
- package/scripts/{package-manifest-check.js → checks/package-manifest-check.js} +2 -1
- package/scripts/{tunnel-supervisor-smoke.js → checks/tunnel-supervisor-smoke.js} +2 -2
- package/scripts/{unit-tests.js → checks/unit-tests.js} +1 -1
- package/scripts/{watcher-supervisor-smoke.js → checks/watcher-supervisor-smoke.js} +13 -7
- package/scripts/control/control-center-tray.ps1 +281 -0
- package/scripts/{get-patchwarden-health.ps1 → control/get-patchwarden-health.ps1} +3 -3
- package/scripts/{manage-patchwarden.ps1 → control/manage-patchwarden.ps1} +30 -4
- package/scripts/control/restart-control-center.ps1 +173 -0
- package/scripts/{restart-patchwarden.ps1 → control/restart-patchwarden.ps1} +1 -1
- package/scripts/control/start-control-center.ps1 +263 -0
- package/scripts/{start-patchwarden-tunnel.ps1 → control/start-patchwarden-tunnel.ps1} +48 -6
- package/scripts/control/stop-patchwarden.ps1 +114 -0
- package/scripts/launchers/Check-PatchWarden-Health.cmd +1 -1
- package/scripts/launchers/Reset-PatchWarden-Tunnel-Key.cmd +1 -1
- package/scripts/launchers/Restart-PatchWarden.cmd +1 -1
- package/scripts/launchers/Start-PatchWarden-Direct-Tunnel.cmd +1 -1
- package/scripts/launchers/Start-PatchWarden-Tunnel.cmd +1 -1
- package/scripts/{patchwarden-mcp-direct.cmd → mcp/patchwarden-mcp-direct.cmd} +1 -1
- package/scripts/{patchwarden-mcp-stdio.cmd → mcp/patchwarden-mcp-stdio.cmd} +1 -1
- package/scripts/{pack-clean.js → release/pack-clean.js} +9 -1
- package/src/agents/agentRouter.ts +149 -0
- package/src/config.ts +9 -3
- package/src/controlCenter.ts +2166 -0
- package/src/doctor.ts +40 -5
- package/src/goal/acceptanceEngine.ts +160 -0
- package/src/goal/acceptanceTemplate.ts +121 -0
- package/src/goal/goalGraph.ts +225 -0
- package/src/goal/goalProgress.ts +301 -0
- package/src/goal/goalStatus.ts +234 -0
- package/src/goal/goalStore.ts +306 -0
- package/src/goal/handoffExport.ts +211 -0
- package/src/goal/subgoalSync.ts +82 -0
- package/src/goal/worktreeManager.ts +404 -0
- package/src/logging.ts +91 -0
- package/src/release/releaseGate.ts +567 -0
- package/src/runner/postTaskCleanup.ts +154 -0
- package/src/runner/runTask.ts +49 -10
- package/src/security/discoveryTokenStore.ts +157 -0
- package/src/security/toolInvocationGuard.ts +251 -0
- package/src/smoke-test.ts +15 -7
- package/src/taskRuntime.ts +17 -0
- package/src/test/unit/acceptance-engine.test.ts +261 -0
- package/src/test/unit/agent-router.test.ts +342 -0
- package/src/test/unit/audit-checks.test.ts +567 -0
- package/src/test/unit/diagnose-task.test.ts +544 -0
- package/src/test/unit/discovery-token-store.test.ts +181 -0
- package/src/test/unit/goal-graph.test.ts +347 -0
- package/src/test/unit/goal-progress.test.ts +538 -0
- package/src/test/unit/goal-status.test.ts +270 -0
- package/src/test/unit/goal-store.test.ts +318 -0
- package/src/test/unit/goal-subgoal-task.test.ts +72 -0
- package/src/test/unit/goal-tools-registry.test.ts +243 -0
- package/src/test/unit/handoff-export.test.ts +295 -0
- package/src/test/unit/invoke-discovered-tool.test.ts +216 -0
- package/src/test/unit/logging.test.ts +177 -5
- package/src/test/unit/post-task-cleanup.test.ts +53 -0
- package/src/test/unit/reconcile-tasks.test.ts +551 -0
- package/src/test/unit/release-gate.test.ts +314 -0
- package/src/test/unit/safe-views.test.ts +184 -0
- package/src/test/unit/schema-drift-check.test.ts +258 -0
- package/src/test/unit/subgoal-sync.test.ts +236 -0
- package/src/test/unit/tool-invocation-guard.test.ts +542 -0
- package/src/test/unit/tool-usage-stats.test.ts +384 -0
- package/src/test/unit/toolSearch.test.ts +756 -0
- package/src/test/unit/worktree-manager.test.ts +247 -0
- package/src/tools/auditTask.ts +831 -402
- package/src/tools/cancelTask.ts +1 -1
- package/src/tools/checkReleaseGate.ts +45 -0
- package/src/tools/createTask.ts +64 -6
- package/src/tools/diagnoseTask.ts +460 -0
- package/src/tools/discardWorktree.ts +42 -0
- package/src/tools/discoverTools.ts +51 -0
- package/src/tools/explainTool.ts +26 -0
- package/src/tools/getTaskSummary.ts +2 -1
- package/src/tools/goalSubgoalTask.ts +170 -0
- package/src/tools/healthCheck.ts +4 -1
- package/src/tools/invokeDiscoveredTool.ts +163 -0
- package/src/tools/listTasks.ts +16 -2
- package/src/tools/mergeWorktree.ts +42 -0
- package/src/tools/reconcileTasks.ts +464 -0
- package/src/tools/registry.ts +618 -1
- package/src/tools/safeStatus.ts +73 -2
- package/src/tools/safeViews.ts +271 -0
- package/src/tools/schemaDriftCheck.ts +120 -0
- package/src/tools/toolCatalog.ts +34 -11
- package/src/tools/toolRegistry.ts +786 -0
- package/src/tools/toolSearch.ts +464 -0
- package/src/tools/toolUsageStats.ts +151 -0
- package/src/tools/waitForTask.ts +1 -0
- package/src/version.ts +2 -2
- package/src/watcherStatus.ts +97 -1
- package/ui/colors_and_type.css +141 -0
- package/ui/pages/audit.html +743 -0
- package/ui/pages/dashboard.html +1154 -0
- package/ui/pages/direct-sessions.html +652 -0
- package/ui/pages/logs.html +502 -0
- package/ui/pages/task-detail.html +1229 -0
- package/ui/pages/tasks.html +702 -0
- package/ui/pages/workspace.html +947 -0
- package/ui/partials/project-shell.html +362 -0
- package/ui/vendor/lucide.js +12 -0
- package/ui/vendor/tailwindcss-browser.js +947 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#Requires -Version 5.1
|
|
2
|
+
param(
|
|
3
|
+
[switch]$NoBrowser,
|
|
4
|
+
[switch]$Foreground,
|
|
5
|
+
[switch]$Background
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
$ErrorActionPreference = "Stop"
|
|
9
|
+
|
|
10
|
+
# ── Argument reconciliation ──────────────────────────────────────
|
|
11
|
+
# -Foreground and -Background are mutually exclusive. When neither is
|
|
12
|
+
# supplied, default to -Background (detach node, exit after readiness).
|
|
13
|
+
if ($Foreground -and $Background) {
|
|
14
|
+
Write-Host "[error] -Foreground and -Background are mutually exclusive." -ForegroundColor Red
|
|
15
|
+
exit 1
|
|
16
|
+
}
|
|
17
|
+
if (-not $Foreground -and -not $Background) {
|
|
18
|
+
$Background = $true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
|
22
|
+
$ControlCenterEntry = Join-Path $ProjectRoot "dist\controlCenter.js"
|
|
23
|
+
$ControlCenterEntryFull = [System.IO.Path]::GetFullPath($ControlCenterEntry)
|
|
24
|
+
$ProjectRootFull = [System.IO.Path]::GetFullPath($ProjectRoot).TrimEnd("\")
|
|
25
|
+
$ListenPort = 8090
|
|
26
|
+
$ListenUrl = "http://127.0.0.1:$ListenPort/"
|
|
27
|
+
$RuntimeDirectory = Join-Path $env:LOCALAPPDATA "patchwarden\control-center"
|
|
28
|
+
$StatusFile = Join-Path $RuntimeDirectory "control-center-status.json"
|
|
29
|
+
$StdoutLog = Join-Path $RuntimeDirectory "control-center.stdout.log"
|
|
30
|
+
$StderrLog = Join-Path $RuntimeDirectory "control-center.stderr.log"
|
|
31
|
+
$MaxWaitSeconds = 15
|
|
32
|
+
$PollIntervalSeconds = 1
|
|
33
|
+
|
|
34
|
+
Set-Location -LiteralPath $ProjectRoot
|
|
35
|
+
|
|
36
|
+
# ── Helpers ──────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
function Test-ControlCenterCommandLine {
|
|
39
|
+
param([string]$CommandLine)
|
|
40
|
+
if (-not $CommandLine) { return $false }
|
|
41
|
+
$normalizedCommand = $CommandLine.Replace("/", "\").ToLowerInvariant()
|
|
42
|
+
$normalizedEntry = $ControlCenterEntryFull.ToLowerInvariant()
|
|
43
|
+
$normalizedRoot = $ProjectRootFull.ToLowerInvariant()
|
|
44
|
+
return $normalizedCommand.Contains($normalizedEntry) -or (
|
|
45
|
+
$normalizedCommand.Contains("dist\controlcenter.js") -and
|
|
46
|
+
$normalizedCommand.Contains($normalizedRoot)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function Get-ControlCenterProcesses {
|
|
51
|
+
Get-CimInstance Win32_Process -Filter "Name = 'node.exe'" -ErrorAction SilentlyContinue |
|
|
52
|
+
Where-Object { Test-ControlCenterCommandLine ([string]$_.CommandLine) }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function Read-StatusFile {
|
|
56
|
+
if (-not (Test-Path -LiteralPath $StatusFile)) { return $null }
|
|
57
|
+
try {
|
|
58
|
+
return Get-Content -LiteralPath $StatusFile -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
59
|
+
} catch {
|
|
60
|
+
return $null
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Test-PortOwnedByControlCenter {
|
|
65
|
+
# Returns $true if a process is listening on $ListenPort AND it is our control
|
|
66
|
+
# center node process. Returns $false if nothing is listening. Throws a
|
|
67
|
+
# descriptive message if a foreign process owns the port.
|
|
68
|
+
$listeners = @()
|
|
69
|
+
try {
|
|
70
|
+
$listeners = Get-NetTCPConnection -LocalPort $ListenPort -State Listen -ErrorAction Stop |
|
|
71
|
+
Sort-Object OwningProcess -Unique
|
|
72
|
+
} catch {
|
|
73
|
+
return $false # nothing listening
|
|
74
|
+
}
|
|
75
|
+
foreach ($listener in $listeners) {
|
|
76
|
+
$owner = Get-CimInstance Win32_Process -Filter "ProcessId = $($listener.OwningProcess)" -ErrorAction SilentlyContinue
|
|
77
|
+
if (-not $owner) { continue }
|
|
78
|
+
if (Test-ControlCenterCommandLine ([string]$owner.CommandLine)) {
|
|
79
|
+
return $true
|
|
80
|
+
} else {
|
|
81
|
+
Write-Host "[error] Port $ListenPort is already used by a non-PatchWarden process." -ForegroundColor Red
|
|
82
|
+
Write-Host "[error] PID $($owner.ProcessId): $($owner.CommandLine)" -ForegroundColor DarkRed
|
|
83
|
+
Write-Host "[error] Close that process manually, then rerun this script." -ForegroundColor Yellow
|
|
84
|
+
exit 1
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return $false
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function Get-StderrTail {
|
|
91
|
+
if (-not (Test-Path -LiteralPath $StderrLog)) { return "" }
|
|
92
|
+
try {
|
|
93
|
+
$content = Get-Content -LiteralPath $StderrLog -Raw -Encoding UTF8 -ErrorAction Stop
|
|
94
|
+
if (-not $content) { return "" }
|
|
95
|
+
$trimmed = ($content -replace '[\r\n]+', ' ').Trim()
|
|
96
|
+
if ($trimmed.Length -gt 500) { $trimmed = $trimmed.Substring(0, 500) }
|
|
97
|
+
return $trimmed
|
|
98
|
+
} catch {
|
|
99
|
+
return ""
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# ── Single-instance detection ────────────────────────────────────
|
|
104
|
+
# 1. Read the status file. If it points at a live control center (port
|
|
105
|
+
# responds AND pid is alive AND command line matches), just open the
|
|
106
|
+
# browser and exit — do NOT spawn a second server.
|
|
107
|
+
# 2. If the port is occupied by a foreign process, error out.
|
|
108
|
+
# 3. Otherwise start a fresh instance.
|
|
109
|
+
|
|
110
|
+
$existing = Read-StatusFile
|
|
111
|
+
if ($existing) {
|
|
112
|
+
$existingPid = 0
|
|
113
|
+
[int]::TryParse([string]$existing.pid, [ref]$existingPid) | Out-Null
|
|
114
|
+
$existingPort = 0
|
|
115
|
+
[int]::TryParse([string]$existing.port, [ref]$existingPort) | Out-Null
|
|
116
|
+
|
|
117
|
+
$pidAlive = $false
|
|
118
|
+
if ($existingPid -gt 0) {
|
|
119
|
+
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = $existingPid" -ErrorAction SilentlyContinue
|
|
120
|
+
if ($proc -and (Test-ControlCenterCommandLine ([string]$proc.CommandLine))) {
|
|
121
|
+
$pidAlive = $true
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if ($pidAlive -and $existingPort -gt 0) {
|
|
126
|
+
$probeUrl = "http://127.0.0.1:$existingPort/api/control-center-status"
|
|
127
|
+
try {
|
|
128
|
+
$resp = Invoke-WebRequest -Uri $probeUrl -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
|
|
129
|
+
if ($resp.StatusCode -eq 200) {
|
|
130
|
+
$body = $resp.Content | ConvertFrom-Json
|
|
131
|
+
if ($body.running -eq $true) {
|
|
132
|
+
$existingUrl = "http://127.0.0.1:$existingPort/"
|
|
133
|
+
Write-Host "[ok] PatchWarden Control Center is already running (PID $existingPid)." -ForegroundColor Green
|
|
134
|
+
Write-Host "[ok] URL: $existingUrl" -ForegroundColor Green
|
|
135
|
+
if (-not $NoBrowser) {
|
|
136
|
+
Write-Host "[open] Launching browser at $existingUrl"
|
|
137
|
+
Start-Process $existingUrl
|
|
138
|
+
}
|
|
139
|
+
exit 0
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch {
|
|
143
|
+
# Status file exists but the probe failed — stale entry. Fall through
|
|
144
|
+
# to a fresh start after cleaning up.
|
|
145
|
+
Write-Host "[warn] Status file exists but the server did not respond; starting a new instance." -ForegroundColor DarkYellow
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
Write-Host "[warn] Status file references a dead PID; starting a new instance." -ForegroundColor DarkYellow
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Detect foreign port occupation before spawning.
|
|
153
|
+
Test-PortOwnedByControlCenter | Out-Null
|
|
154
|
+
# If we reach here, either nothing is listening or our own (now-dead) process
|
|
155
|
+
# was the listener. Clean up any orphaned node processes for this entry point.
|
|
156
|
+
$orphans = @(Get-ControlCenterProcesses)
|
|
157
|
+
if ($orphans.Count -gt 0) {
|
|
158
|
+
Write-Host "[cleanup] Stopping $($orphans.Count) orphaned Control Center node process(es)." -ForegroundColor DarkYellow
|
|
159
|
+
foreach ($p in $orphans) {
|
|
160
|
+
try { Stop-Process -Id $p.ProcessId -Force -ErrorAction Stop } catch {}
|
|
161
|
+
}
|
|
162
|
+
Start-Sleep -Milliseconds 500
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
# ── Build if needed ──────────────────────────────────────────────
|
|
166
|
+
|
|
167
|
+
$nodeCommand = Get-Command node.exe -ErrorAction SilentlyContinue
|
|
168
|
+
if (-not $nodeCommand) {
|
|
169
|
+
Write-Host "[error] node.exe was not found on PATH." -ForegroundColor Red
|
|
170
|
+
exit 1
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (-not (Test-Path -LiteralPath $ControlCenterEntryFull)) {
|
|
174
|
+
Write-Host "[build] dist/controlCenter.js not found. Running npm.cmd run build..." -ForegroundColor Yellow
|
|
175
|
+
npm.cmd run build
|
|
176
|
+
if ($LASTEXITCODE -ne 0) {
|
|
177
|
+
Write-Host "[error] npm.cmd run build exited with code $LASTEXITCODE." -ForegroundColor Red
|
|
178
|
+
exit 1
|
|
179
|
+
}
|
|
180
|
+
if (-not (Test-Path -LiteralPath $ControlCenterEntryFull)) {
|
|
181
|
+
Write-Host "[error] Build completed but dist/controlCenter.js is still missing." -ForegroundColor Red
|
|
182
|
+
exit 1
|
|
183
|
+
}
|
|
184
|
+
Write-Host "[build] Build complete." -ForegroundColor Green
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
New-Item -ItemType Directory -Force -Path $RuntimeDirectory | Out-Null
|
|
188
|
+
Remove-Item -LiteralPath $StdoutLog, $StderrLog -Force -ErrorAction SilentlyContinue
|
|
189
|
+
|
|
190
|
+
# ── Foreground mode: node attached to this console, logs stream live ──
|
|
191
|
+
if ($Foreground) {
|
|
192
|
+
Write-Host "[run] Starting PatchWarden Control Center on $ListenUrl (foreground)" -ForegroundColor Cyan
|
|
193
|
+
Write-Host "[run] Press Ctrl+C to stop. Logs stream below."
|
|
194
|
+
# In foreground mode the node process inherits this console; the status file
|
|
195
|
+
# is still written by the server itself on listen().
|
|
196
|
+
& $nodeCommand.Source $ControlCenterEntryFull
|
|
197
|
+
exit $LASTEXITCODE
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# ── Background mode (default): detached node, this script exits after ready ──
|
|
201
|
+
Write-Host "[run] Starting PatchWarden Control Center on $ListenUrl (background)" -ForegroundColor Cyan
|
|
202
|
+
$process = Start-Process -FilePath $nodeCommand.Source `
|
|
203
|
+
-ArgumentList @($ControlCenterEntryFull) `
|
|
204
|
+
-WorkingDirectory $ProjectRoot `
|
|
205
|
+
-RedirectStandardOutput $StdoutLog `
|
|
206
|
+
-RedirectStandardError $StderrLog `
|
|
207
|
+
-PassThru -WindowStyle Hidden
|
|
208
|
+
|
|
209
|
+
Write-Host "[run] node PID $($process.Id)."
|
|
210
|
+
|
|
211
|
+
# Brief wait to detect truly immediate exits.
|
|
212
|
+
Start-Sleep -Milliseconds 500
|
|
213
|
+
if ($process.HasExited) {
|
|
214
|
+
$exitCode = $process.ExitCode
|
|
215
|
+
$stderrTail = Get-StderrTail
|
|
216
|
+
Write-Host "[error] node process exited immediately with code $exitCode." -ForegroundColor Red
|
|
217
|
+
if ($stderrTail) {
|
|
218
|
+
Write-Host "[error] stderr: $stderrTail" -ForegroundColor DarkRed
|
|
219
|
+
}
|
|
220
|
+
exit 1
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
# Poll for port readiness.
|
|
224
|
+
$ready = $false
|
|
225
|
+
for ($attempt = 1; $attempt -le $MaxWaitSeconds; $attempt++) {
|
|
226
|
+
try { $process.Refresh() } catch {}
|
|
227
|
+
if ($process.HasExited) {
|
|
228
|
+
$exitCode = $process.ExitCode
|
|
229
|
+
$stderrTail = Get-StderrTail
|
|
230
|
+
Write-Host "[error] node process exited with code $exitCode before the port became ready." -ForegroundColor Red
|
|
231
|
+
if ($stderrTail) {
|
|
232
|
+
Write-Host "[error] stderr: $stderrTail" -ForegroundColor DarkRed
|
|
233
|
+
}
|
|
234
|
+
exit 1
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
$response = Invoke-WebRequest -Uri $ListenUrl -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
|
|
238
|
+
if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 500) {
|
|
239
|
+
$ready = $true
|
|
240
|
+
break
|
|
241
|
+
}
|
|
242
|
+
} catch {
|
|
243
|
+
# Not ready yet; keep polling.
|
|
244
|
+
}
|
|
245
|
+
Start-Sleep -Seconds $PollIntervalSeconds
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (-not $ready) {
|
|
249
|
+
Write-Host "[error] Control Center did not become ready on $ListenUrl within $MaxWaitSeconds seconds." -ForegroundColor Red
|
|
250
|
+
try { Stop-Process -Id $process.Id -Force -ErrorAction Stop } catch {}
|
|
251
|
+
exit 1
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
Write-Host "[ok] PatchWarden Control Center is ready at $ListenUrl" -ForegroundColor Green
|
|
255
|
+
|
|
256
|
+
if (-not $NoBrowser) {
|
|
257
|
+
Write-Host "[open] Launching default browser at $ListenUrl"
|
|
258
|
+
Start-Process $ListenUrl
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
Write-Host "[info] node PID $($process.Id); stdout log: $StdoutLog; stderr log: $StderrLog"
|
|
262
|
+
Write-Host "[info] Re-run this script to open the existing instance instead of starting a new one."
|
|
263
|
+
Write-Host "[info] Stop with: Stop-Process -Id $($process.Id)"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
param(
|
|
1
|
+
param(
|
|
2
2
|
[string]$TunnelId = $env:PATCHWARDEN_TUNNEL_ID,
|
|
3
3
|
[string]$Profile = "patchwarden",
|
|
4
4
|
[ValidateSet("chatgpt_core", "chatgpt_direct")]
|
|
5
5
|
[string]$ToolProfile = "chatgpt_core",
|
|
6
6
|
[string]$ProxyUrl = $(if ($env:HTTPS_PROXY) { $env:HTTPS_PROXY } else { "http://127.0.0.1:7892" }),
|
|
7
|
-
[string]$TunnelClientExe = $env:TUNNEL_CLIENT_EXE,
|
|
7
|
+
[string]$TunnelClientExe = $(if ($env:TUNNEL_CLIENT_EXE) { $env:TUNNEL_CLIENT_EXE } else { $env:PATCHWARDEN_TUNNEL_CLIENT_EXE }),
|
|
8
8
|
[string]$OpencodeBin = $env:OPENCODE_BIN_DIR,
|
|
9
9
|
[string]$ConfigPath = $env:PATCHWARDEN_CONFIG,
|
|
10
10
|
[string]$CredentialPath = $(if ($env:PATCHWARDEN_CREDENTIAL_PATH) { $env:PATCHWARDEN_CREDENTIAL_PATH } else { Join-Path $env:APPDATA "patchwarden\control-plane-api-key.dpapi" }),
|
|
@@ -16,6 +16,7 @@ param(
|
|
|
16
16
|
[int]$WatcherHealthyResetSeconds = 60,
|
|
17
17
|
[switch]$SkipWatcher,
|
|
18
18
|
[switch]$ForgetSavedApiKey,
|
|
19
|
+
[switch]$NoTunnelWebUi,
|
|
19
20
|
[string]$HealthListenAddr = ""
|
|
20
21
|
)
|
|
21
22
|
|
|
@@ -29,12 +30,12 @@ if ([string]::IsNullOrWhiteSpace($HealthListenAddr)) {
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
|
33
|
+
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
|
33
34
|
if (-not $ConfigPath) {
|
|
34
35
|
$ConfigPath = Join-Path $ProjectRoot "patchwarden.config.json"
|
|
35
36
|
}
|
|
36
37
|
$McpLauncherName = if ($ToolProfile -eq "chatgpt_direct") { "patchwarden-mcp-direct.cmd" } else { "patchwarden-mcp-stdio.cmd" }
|
|
37
|
-
$McpStdioLauncher = Join-Path $ProjectRoot "scripts\$McpLauncherName"
|
|
38
|
+
$McpStdioLauncher = Join-Path $ProjectRoot "scripts\mcp\$McpLauncherName"
|
|
38
39
|
$McpStdioLauncherForTunnel = $McpStdioLauncher -replace "\\", "/"
|
|
39
40
|
$OpencodeConfigHome = Join-Path $env:LOCALAPPDATA "patchwarden\opencode-config"
|
|
40
41
|
$ProfilePath = Join-Path $env:APPDATA "tunnel-client\$Profile.yaml"
|
|
@@ -57,6 +58,7 @@ $script:WatcherManaged = $false
|
|
|
57
58
|
$script:WatcherRestartAttempts = 0
|
|
58
59
|
$script:WatcherHealthySince = $null
|
|
59
60
|
$script:WatcherRestartExhausted = $false
|
|
61
|
+
$DefaultTunnelClientPath = "D:\ai_agent\tunnel-client-v0.0.9--context-conduit-topaz-windows-amd64\tunnel-client.exe"
|
|
60
62
|
|
|
61
63
|
if ($ToolProfile -eq "chatgpt_direct") {
|
|
62
64
|
$SkipWatcher = $true
|
|
@@ -501,7 +503,34 @@ if (-not $TunnelClientExe) {
|
|
|
501
503
|
}
|
|
502
504
|
}
|
|
503
505
|
|
|
506
|
+
# Search common installation locations
|
|
507
|
+
$commonPaths = @(
|
|
508
|
+
$DefaultTunnelClientPath
|
|
509
|
+
Join-Path $env:LOCALAPPDATA "patchwarden\tunnel-client.exe"
|
|
510
|
+
Join-Path $env:APPDATA "tunnel-client\tunnel-client.exe"
|
|
511
|
+
Join-Path $env:USERPROFILE "tunnel-client\tunnel-client.exe"
|
|
512
|
+
)
|
|
513
|
+
if (-not $TunnelClientExe) {
|
|
514
|
+
foreach ($candidate in $commonPaths) {
|
|
515
|
+
if (Test-Path -LiteralPath $candidate) {
|
|
516
|
+
$TunnelClientExe = $candidate
|
|
517
|
+
Write-Host "[detect] Found tunnel-client.exe: $TunnelClientExe" -ForegroundColor Green
|
|
518
|
+
break
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
504
523
|
if (-not $TunnelClientExe) {
|
|
524
|
+
Write-Host ""
|
|
525
|
+
Write-Host "[input] tunnel-client.exe not found on PATH or common locations." -ForegroundColor Yellow
|
|
526
|
+
Write-Host " Please provide the full path."
|
|
527
|
+
Write-Host ""
|
|
528
|
+
Write-Host " To search for it manually, try one of these commands:" -ForegroundColor Cyan
|
|
529
|
+
Write-Host " Get-ChildItem -Path `$env:LOCALAPPDATA -Recurse -Filter tunnel-client.exe -ErrorAction SilentlyContinue" -ForegroundColor Gray
|
|
530
|
+
Write-Host " Get-ChildItem -Path `$env:APPDATA -Recurse -Filter tunnel-client.exe -ErrorAction SilentlyContinue" -ForegroundColor Gray
|
|
531
|
+
Write-Host " Get-ChildItem -Path C:\ -Recurse -Filter tunnel-client.exe -ErrorAction SilentlyContinue" -ForegroundColor Gray
|
|
532
|
+
Write-Host " Or download it from: https://platform.openai.com/docs/guides/mcp-connector" -ForegroundColor Cyan
|
|
533
|
+
Write-Host ""
|
|
505
534
|
$TunnelClientExe = Read-Host "Path to tunnel-client.exe"
|
|
506
535
|
}
|
|
507
536
|
|
|
@@ -521,6 +550,19 @@ Assert-File -Path $TunnelClientExe -Name "tunnel-client.exe"
|
|
|
521
550
|
Assert-File -Path $ConfigPath -Name "patchwarden.config.json"
|
|
522
551
|
Assert-File -Path $McpStdioLauncher -Name $McpLauncherName
|
|
523
552
|
|
|
553
|
+
# Auto-read Tunnel ID from existing profile YAML if not already set
|
|
554
|
+
if (-not $TunnelId -and (Test-Path -LiteralPath $ProfilePath)) {
|
|
555
|
+
try {
|
|
556
|
+
$profileContent = Get-Content -LiteralPath $ProfilePath -Raw -Encoding UTF8
|
|
557
|
+
if ($profileContent -match 'tunnel_id:\s*"([^"]+)"') {
|
|
558
|
+
$TunnelId = $matches[1]
|
|
559
|
+
Write-Host "[detect] Tunnel ID read from profile $Profile`: $TunnelId" -ForegroundColor Green
|
|
560
|
+
}
|
|
561
|
+
} catch {
|
|
562
|
+
Write-Host "[warn] Could not read Tunnel ID from $ProfilePath`: $($_.Exception.Message)" -ForegroundColor Yellow
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
524
566
|
if (-not $TunnelId) {
|
|
525
567
|
$TunnelId = Read-Host "Tunnel ID"
|
|
526
568
|
}
|
|
@@ -538,7 +580,7 @@ if (-not (Test-Path -LiteralPath (Join-Path $ProjectRoot "dist\index.js"))) {
|
|
|
538
580
|
New-Item -ItemType Directory -Force -Path $RuntimeDirectory | Out-Null
|
|
539
581
|
$env:PATCHWARDEN_CONFIG = $ConfigPath
|
|
540
582
|
Write-Host "[manifest] Verifying the exact $ToolProfile stdio MCP tool catalog..."
|
|
541
|
-
$manifestOutput = (& node (Join-Path $ProjectRoot "scripts\mcp-manifest-check.js") --profile $ToolProfile --json 2>&1 | Out-String).Trim()
|
|
583
|
+
$manifestOutput = (& node (Join-Path $ProjectRoot "scripts\checks\mcp-manifest-check.js") --profile $ToolProfile --json 2>&1 | Out-String).Trim()
|
|
542
584
|
if ($LASTEXITCODE -ne 0) {
|
|
543
585
|
Write-TunnelStatus -Status "stopped" -ReasonCode "tool_manifest_check_failed" -LastError "The tunnel MCP tool manifest preflight failed."
|
|
544
586
|
throw "Tool manifest preflight failed: $manifestOutput"
|
|
@@ -630,7 +672,7 @@ Write-Host "[run-config] cwd: $ProjectRoot"
|
|
|
630
672
|
Write-Host ""
|
|
631
673
|
|
|
632
674
|
$attempt = 0
|
|
633
|
-
$openUi = $
|
|
675
|
+
$openUi = -not $NoTunnelWebUi
|
|
634
676
|
try {
|
|
635
677
|
while ($true) {
|
|
636
678
|
$attempt++
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#Requires -Version 5.1
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
One-click shutdown for PatchWarden desktop use.
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Stops Core/Direct through the consolidated manager, then closes the local
|
|
7
|
+
Control Center and tray processes that belong to this project path.
|
|
8
|
+
#>
|
|
9
|
+
param(
|
|
10
|
+
[switch]$KeepControlCenter,
|
|
11
|
+
[switch]$KeepTray
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
$ErrorActionPreference = "Stop"
|
|
15
|
+
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
|
16
|
+
$ProjectRootFull = [System.IO.Path]::GetFullPath($ProjectRoot).TrimEnd("\")
|
|
17
|
+
$Manager = Join-Path $PSScriptRoot "manage-patchwarden.ps1"
|
|
18
|
+
$ControlCenterEntry = Join-Path $ProjectRoot "dist\controlCenter.js"
|
|
19
|
+
$ControlCenterEntryFull = [System.IO.Path]::GetFullPath($ControlCenterEntry)
|
|
20
|
+
$TrayScript = Join-Path $PSScriptRoot "control-center-tray.ps1"
|
|
21
|
+
$TrayScriptFull = [System.IO.Path]::GetFullPath($TrayScript)
|
|
22
|
+
$RuntimeDirectory = Join-Path $env:LOCALAPPDATA "patchwarden\control-center"
|
|
23
|
+
$StatusFile = Join-Path $RuntimeDirectory "control-center-status.json"
|
|
24
|
+
|
|
25
|
+
Set-Location -LiteralPath $ProjectRoot
|
|
26
|
+
|
|
27
|
+
function Normalize-CommandLine {
|
|
28
|
+
param([string]$CommandLine)
|
|
29
|
+
if (-not $CommandLine) { return "" }
|
|
30
|
+
return $CommandLine.Replace("/", "\").ToLowerInvariant()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function Test-ControlCenterProcess {
|
|
34
|
+
param($ProcessInfo)
|
|
35
|
+
$normalizedCommand = Normalize-CommandLine ([string]$ProcessInfo.CommandLine)
|
|
36
|
+
$normalizedEntry = $ControlCenterEntryFull.ToLowerInvariant()
|
|
37
|
+
$normalizedRoot = $ProjectRootFull.ToLowerInvariant()
|
|
38
|
+
return $normalizedCommand.Contains($normalizedEntry) -or (
|
|
39
|
+
$normalizedCommand.Contains("dist\controlcenter.js") -and
|
|
40
|
+
$normalizedCommand.Contains($normalizedRoot)
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Test-TrayProcess {
|
|
45
|
+
param($ProcessInfo)
|
|
46
|
+
$normalizedCommand = Normalize-CommandLine ([string]$ProcessInfo.CommandLine)
|
|
47
|
+
$normalizedTray = $TrayScriptFull.ToLowerInvariant()
|
|
48
|
+
$normalizedRoot = $ProjectRootFull.ToLowerInvariant()
|
|
49
|
+
return $normalizedCommand.Contains($normalizedTray) -or (
|
|
50
|
+
$normalizedCommand.Contains("control-center-tray.ps1") -and
|
|
51
|
+
$normalizedCommand.Contains($normalizedRoot)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function Stop-MatchingProcesses {
|
|
56
|
+
param(
|
|
57
|
+
[Parameter(Mandatory = $true)][string]$Label,
|
|
58
|
+
[Parameter(Mandatory = $true)][scriptblock]$Predicate
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
$processes = @(
|
|
62
|
+
Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
|
63
|
+
Where-Object {
|
|
64
|
+
[int]$_.ProcessId -ne $PID -and (& $Predicate $_)
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if ($processes.Count -eq 0) {
|
|
69
|
+
Write-Host "[stop] No $Label process found." -ForegroundColor DarkGray
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
foreach ($proc in $processes) {
|
|
74
|
+
Write-Host "[stop] Closing $Label PID $($proc.ProcessId)." -ForegroundColor Yellow
|
|
75
|
+
try {
|
|
76
|
+
Stop-Process -Id $proc.ProcessId -ErrorAction SilentlyContinue
|
|
77
|
+
} catch {
|
|
78
|
+
Write-Host "[stop] PID $($proc.ProcessId) already exited or is inaccessible." -ForegroundColor DarkGray
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Start-Sleep -Milliseconds 800
|
|
83
|
+
|
|
84
|
+
foreach ($proc in $processes) {
|
|
85
|
+
$stillRunning = Get-Process -Id $proc.ProcessId -ErrorAction SilentlyContinue
|
|
86
|
+
if ($stillRunning) {
|
|
87
|
+
Write-Host "[stop] PID $($proc.ProcessId) did not exit cleanly; forcing stop." -ForegroundColor Yellow
|
|
88
|
+
Stop-Process -Id $proc.ProcessId -Force -ErrorAction SilentlyContinue
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (-not (Test-Path -LiteralPath $Manager)) {
|
|
94
|
+
throw "Manager script not found: $Manager"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Write-Host "[stop] Stopping PatchWarden Core/Direct services..." -ForegroundColor Cyan
|
|
98
|
+
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $Manager stop all
|
|
99
|
+
if ($LASTEXITCODE -ne 0) {
|
|
100
|
+
exit $LASTEXITCODE
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (-not $KeepControlCenter) {
|
|
104
|
+
Stop-MatchingProcesses -Label "Control Center" -Predicate ${function:Test-ControlCenterProcess}
|
|
105
|
+
if (Test-Path -LiteralPath $StatusFile) {
|
|
106
|
+
Remove-Item -LiteralPath $StatusFile -Force -ErrorAction SilentlyContinue
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (-not $KeepTray) {
|
|
111
|
+
Stop-MatchingProcesses -Label "tray" -Predicate ${function:Test-TrayProcess}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Write-Host "[ok] PatchWarden shutdown complete." -ForegroundColor Green
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@echo off
|
|
2
2
|
setlocal
|
|
3
3
|
cd /d "%~dp0..\.."
|
|
4
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\manage-patchwarden.ps1" status all
|
|
4
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\control\manage-patchwarden.ps1" status all
|
|
5
5
|
echo.
|
|
6
6
|
pause
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@echo off
|
|
2
2
|
setlocal
|
|
3
3
|
cd /d "%~dp0..\.."
|
|
4
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\start-patchwarden-tunnel.ps1" -ForgetSavedApiKey
|
|
4
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\control\start-patchwarden-tunnel.ps1" -ForgetSavedApiKey
|
|
5
5
|
echo.
|
|
6
6
|
pause
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@echo off
|
|
2
2
|
setlocal
|
|
3
3
|
cd /d "%~dp0..\.."
|
|
4
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\manage-patchwarden.ps1" restart core
|
|
4
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\control\manage-patchwarden.ps1" restart core
|
|
5
5
|
echo.
|
|
6
6
|
pause
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@echo off
|
|
2
2
|
setlocal
|
|
3
3
|
cd /d "%~dp0..\.."
|
|
4
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\start-patchwarden-tunnel.ps1" -ToolProfile chatgpt_direct -Profile patchwarden-direct -HealthListenAddr 127.0.0.1:8081 -SkipWatcher
|
|
4
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\control\start-patchwarden-tunnel.ps1" -ToolProfile chatgpt_direct -Profile patchwarden-direct -HealthListenAddr 127.0.0.1:8081 -SkipWatcher
|
|
5
5
|
echo.
|
|
6
6
|
echo PatchWarden Direct tunnel launcher exited.
|
|
7
7
|
pause
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@echo off
|
|
2
2
|
setlocal
|
|
3
3
|
cd /d "%~dp0..\.."
|
|
4
|
-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\start-patchwarden-tunnel.ps1" -ToolProfile chatgpt_core -Profile patchwarden -HealthListenAddr 127.0.0.1:8080
|
|
4
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0..\control\start-patchwarden-tunnel.ps1" -ToolProfile chatgpt_core -Profile patchwarden -HealthListenAddr 127.0.0.1:8080
|
|
5
5
|
echo.
|
|
6
6
|
echo PatchWarden Core tunnel launcher exited.
|
|
7
7
|
pause
|
|
@@ -15,7 +15,7 @@ import { join, relative, resolve } from "node:path";
|
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
|
|
17
17
|
const scriptDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
|
|
18
|
-
const root = resolve(scriptDir, "..");
|
|
18
|
+
const root = resolve(scriptDir, "..", "..");
|
|
19
19
|
const releaseDir = resolve(root, "release");
|
|
20
20
|
const archivePath = resolve(root, "patchwarden-release.tar.gz");
|
|
21
21
|
|
|
@@ -29,7 +29,13 @@ const include = [
|
|
|
29
29
|
"examples",
|
|
30
30
|
"scripts",
|
|
31
31
|
"src",
|
|
32
|
+
"ui",
|
|
32
33
|
"PatchWarden.cmd",
|
|
34
|
+
"PatchWarden-Control.cmd",
|
|
35
|
+
"PatchWarden-Control-Tray.cmd",
|
|
36
|
+
"PatchWarden-Desktop.cmd",
|
|
37
|
+
"Restart-PatchWarden-Control.cmd",
|
|
38
|
+
"Stop-PatchWarden.cmd",
|
|
33
39
|
".gitignore",
|
|
34
40
|
"LICENSE",
|
|
35
41
|
"README.md",
|
|
@@ -42,6 +48,8 @@ const forbidden = [
|
|
|
42
48
|
/(^|[\\/])node_modules([\\/]|$)/,
|
|
43
49
|
/(^|[\\/])\.patchwarden([\\/]|$)/,
|
|
44
50
|
/(^|[\\/])\.safe-bifrost([\\/]|$)/,
|
|
51
|
+
/(^|[\\/])\.local([\\/]|$)/,
|
|
52
|
+
/(^|[\\/])\.tmp([\\/]|$)/,
|
|
45
53
|
/(^|[\\/])patchwarden\.config\.json$/,
|
|
46
54
|
/(^|[\\/])safe-bifrost\.config\.json$/,
|
|
47
55
|
/\.local\.(cmd|ps1)$/i,
|