fix(install): detect TLS cert-trust failures during npm install on Windows (#40588)

* fix: respect disabled auto-compaction on context overflow

Port from anomalyco/opencode#30749.

When compression.enabled is false, NO automatic compaction trigger may
fire. The proactive token-threshold paths (preflight + post-response
should_compress gate) already honoured the setting, but the three
provider-overflow recovery paths in the agent loop — long-context-tier
429, 413 payload-too-large, and context-overflow — called
_compress_context() unconditionally, silently compressing and rotating
the session against the user's explicit choice.

Add a single guard at the top of the overflow-recovery dispatch: when
compression is disabled and the error is one of those three overflow
classes, surface a terminal error (compaction_disabled: True) telling the
user to /compress manually, /new, switch to a larger-context model, or
reduce attachments. Manual /compress (force=True) is unaffected — it never
enters this loop.

Tests: new TestOverflowWithCompactionDisabled (413 + 400 overflow don't
compress when disabled; control case still compresses when enabled).
Existing overflow-recovery tests updated to enable compaction explicitly
(they verify the recovery fires); fixture defaults flipped to True to
match production (compression.enabled defaults to True).

* fix(install): detect TLS cert-trust failures during npm install on Windows

Corporate MITM proxies and missing root CAs surface as 'unable to get
local issuer certificate' while npm (most often Electron's install.js
postinstall) downloads over HTTPS. The installer surfaced this as an
opaque 'desktop workspace npm install failed (exit 1)', so users
misread it as a permissions/admin-rights problem (issue #38016).

Add a shared Show-NpmCertHint detector and route all three npm-install
failure paths (agent-browser global install, browser-tools workspace,
desktop workspace) through it. On a cert error it prints actionable
NODE_EXTRA_CA_CERTS / strict-ssl remediation; on any other failure it
stays silent.
This commit is contained in:
Teknium 2026-06-06 09:00:15 -07:00 committed by GitHub
parent 54e7b74f7f
commit fd234bad62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -185,6 +185,35 @@ function Write-Err {
Write-Host "[X] $Message" -ForegroundColor Red
}
# Inspect npm output for a TLS-trust failure and, if found, print actionable
# remediation. npm/Node surface corporate MITM proxies and missing root CAs as
# "unable to get local issuer certificate" / "self-signed certificate in
# certificate chain" / UNABLE_TO_GET_ISSUER_CERT_LOCALLY -- most commonly while
# Electron's install.js postinstall downloads the Electron binary. The reporter
# usually misreads this as an admin-rights or generic install failure (see
# issue #38016), so detect it once here and route every npm stage through this
# hint. Returns $true when a cert error was detected (caller may adjust its own
# messaging), $false otherwise.
function Show-NpmCertHint {
param([string]$NpmOutput)
if (-not $NpmOutput) { return $false }
$isCertError = $NpmOutput -match "unable to get local issuer certificate" `
-or $NpmOutput -match "self.signed certificate" `
-or $NpmOutput -match "UNABLE_TO_GET_ISSUER_CERT_LOCALLY" `
-or $NpmOutput -match "SELF_SIGNED_CERT_IN_CHAIN" `
-or $NpmOutput -match "CERT_HAS_EXPIRED"
if (-not $isCertError) { return $false }
Write-Warn "This looks like a TLS certificate-trust failure, not a permissions problem."
Write-Info " A corporate proxy or antivirus is likely intercepting HTTPS and presenting a"
Write-Info " certificate Node.js doesn't trust. To fix, point Node at your org's root CA:"
Write-Info " 1. Get the corporate root CA as a .pem/.crt from your IT team."
Write-Info " 2. setx NODE_EXTRA_CA_CERTS `"C:\path\to\corp-ca.pem`""
Write-Info " 3. Open a NEW terminal (so the env var takes effect) and re-run the installer."
Write-Info " Quick (less secure) alternative -- disable TLS verification just for the install:"
Write-Info " npm config set strict-ssl false (re-enable afterwards: npm config set strict-ssl true)"
return $true
}
# --- Ensure-mode helpers ---
function Resolve-NpmCmd {
@ -252,6 +281,7 @@ function Install-AgentBrowser {
$npmDetail = Get-Content $npmLog -Raw -ErrorAction SilentlyContinue
Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
Write-Err "npm install -g failed (exit $npmExit): $npmDetail"
Show-NpmCertHint $npmDetail | Out-Null
throw "npm install failed"
}
Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
@ -1873,6 +1903,7 @@ function Install-NodeDeps {
Write-Host " $line" -ForegroundColor DarkGray
}
Write-Info " Full log: $logPath"
Show-NpmCertHint $errText | Out-Null
}
}
Write-Info "Run manually later: cd `"$installDir`"; npm install"
@ -2127,15 +2158,22 @@ function Install-Desktop {
# tsc/typescript unresolved so `npm run pack`'s `tsc -b` dies with
# no obvious cause. Fall back to `npm install` only if `npm ci`
# fails (lockfile out of sync / very old npm without ci).
& $npmExe ci 2>&1 | ForEach-Object { "$_" }
#
# Tee the merged output into $npmOut while still emitting every line
# live. We don't need a side log file (the bootstrap streaming sink
# is the artifact), but on failure we scan $npmOut for the TLS-trust
# signature so corporate-proxy users get the NODE_EXTRA_CA_CERTS hint
# instead of an opaque "exit 1" (issue #38016).
& $npmExe ci 2>&1 | ForEach-Object { "$_" } | Tee-Object -Variable npmOut
$code = $LASTEXITCODE
if ($code -ne 0) {
Write-Info " npm ci failed (exit $code) -- retrying with npm install..."
& $npmExe install 2>&1 | ForEach-Object { "$_" }
& $npmExe install 2>&1 | ForEach-Object { "$_" } | Tee-Object -Variable npmOut
$code = $LASTEXITCODE
}
$ErrorActionPreference = $prevEAP
if ($code -ne 0) {
Show-NpmCertHint ($npmOut -join "`n") | Out-Null
throw "desktop workspace npm install failed (exit $code) -- see lines above for cause"
}
Write-Success "Desktop workspace dependencies installed"