mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-21 03:39:54 +00:00
fix(install.ps1): Stage-Node honest reporting + reject empty -Stage
Two protocol-correctness gaps from review:
1. Stage-Node used [void](Test-Node) which discarded Test-Node's return
value, so the JSON frame always reported ok=true even when Node
install fully failed. A GUI driver consuming the manifest couldn't
tell 'node ready' from 'node missing'. Wire a soft-skip channel
($script:_StageSkippedReason) that workers can populate to surface
'ran, but the thing it was supposed to set up is not available' as
skipped=true with a reason in the JSON, without aborting the install
(Node is optional -- browser tools degrade gracefully, matches
Write-Completion's existing 'Note: Node.js could not be installed'
behavior). Reset before each stage so a prior reason can't leak.
2. The -Stage dispatch used 'if ($Stage)' which is falsy for empty
string, so 'install.ps1 -Stage ""' fell through to Main and silently
kicked off a full destructive install. Switch to
PSBoundParameters.ContainsKey('Stage') so an explicit empty value
surfaces as unknown-stage exit 2 with a structured JSON frame, the
way every other bad stage name does.
This commit is contained in:
+30
-2
@@ -1926,7 +1926,17 @@ $InstallStages = @(
|
||||
function Stage-Uv { if (-not (Install-Uv)) { throw "uv installation failed" } }
|
||||
function Stage-Python { Resolve-UvCmd; if (-not (Test-Python)) { throw "Python $PythonVersion not available" } }
|
||||
function Stage-Git { if (-not (Install-Git)) { throw "Git not available and auto-install failed -- install from https://git-scm.com/download/win then re-run" } }
|
||||
function Stage-Node { [void](Test-Node) }
|
||||
# Node is optional (browser tools degrade gracefully without it). Surface
|
||||
# failure to the JSON contract as skipped=true / reason rather than ok=true,
|
||||
# so a GUI driver consuming the manifest can distinguish "node ready" from
|
||||
# "node missing". Install flow continues either way -- matches the
|
||||
# existing Write-Completion behavior that prints a "Note: Node.js could
|
||||
# not be installed" hint instead of aborting.
|
||||
function Stage-Node {
|
||||
if (-not (Test-Node)) {
|
||||
$script:_StageSkippedReason = "Node.js not available; browser tools will be unavailable until node is installed manually from https://nodejs.org/en/download/"
|
||||
}
|
||||
}
|
||||
function Stage-SystemPackages { Install-SystemPackages }
|
||||
function Stage-Repository { Install-Repository }
|
||||
function Stage-Venv { Resolve-UvCmd; Install-Venv }
|
||||
@@ -1975,6 +1985,15 @@ function Invoke-Stage {
|
||||
# foreach pass; cross-process drivers get the necessary freshening).
|
||||
Sync-EnvPath
|
||||
|
||||
# Per-stage soft-skip channel. A worker can populate
|
||||
# $script:_StageSkippedReason to surface "ran, but the thing it was
|
||||
# supposed to set up is not available" as skipped=true in the JSON
|
||||
# frame, without throwing. Used by Stage-Node so the install flow
|
||||
# doesn't abort when an optional capability is missing while still
|
||||
# being honest in the protocol contract. Reset before each stage so
|
||||
# a prior stage's reason can never leak into a later stage's frame.
|
||||
$script:_StageSkippedReason = $null
|
||||
|
||||
$start = [DateTime]::UtcNow
|
||||
$result = @{
|
||||
stage = $StageDef.Name
|
||||
@@ -1987,6 +2006,10 @@ function Invoke-Stage {
|
||||
try {
|
||||
& $StageDef.Worker
|
||||
$result.ok = $true
|
||||
if ($script:_StageSkippedReason) {
|
||||
$result.skipped = $true
|
||||
$result.reason = $script:_StageSkippedReason
|
||||
}
|
||||
} catch {
|
||||
$result.ok = $false
|
||||
$result.reason = "$_"
|
||||
@@ -2060,7 +2083,12 @@ try {
|
||||
exit 0
|
||||
}
|
||||
|
||||
if ($Stage) {
|
||||
# Use PSBoundParameters rather than $Stage truthiness so that an
|
||||
# explicit `-Stage ""` from a misbehaving driver doesn't fall through
|
||||
# to the full-install Main path and silently kick off a destructive
|
||||
# operation. Empty string is a contract violation; surface it as
|
||||
# unknown-stage exit 2 with a structured JSON frame.
|
||||
if ($PSBoundParameters.ContainsKey("Stage")) {
|
||||
$def = Get-InstallStage -Name $Stage
|
||||
if (-not $def) {
|
||||
$err = @{
|
||||
|
||||
Reference in New Issue
Block a user