@beeos-ai/cli 1.0.24 → 1.1.1
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/README.md +116 -34
- package/dist/index.js +884 -118
- package/package.json +1 -1
- package/scripts/install.Tests.ps1 +64 -1
- package/scripts/install.ps1 +173 -12
- package/scripts/install.sh +240 -2
package/package.json
CHANGED
|
@@ -80,7 +80,18 @@ Describe "install.ps1 parse-time integrity" {
|
|
|
80
80
|
"Invoke-BeeosCli",
|
|
81
81
|
# P2-8: PSCore + RunAs auto-elevation helpers.
|
|
82
82
|
"Test-IsAdministrator",
|
|
83
|
-
"Request-Elevation"
|
|
83
|
+
"Request-Elevation",
|
|
84
|
+
# Multi-OS install-link refactor Phase 2: TightVNC
|
|
85
|
+
# pre-check. install.sh has a parallel `test_vnc_server`
|
|
86
|
+
# function for Linux. Listed here so a future cleanup
|
|
87
|
+
# that drops the helper triggers a Pester failure
|
|
88
|
+
# before reaching customers.
|
|
89
|
+
"Test-VncServer",
|
|
90
|
+
# EACCES auto-recovery (Phase 3 of the install pipeline).
|
|
91
|
+
# install.sh has the parallel `recover_eacces_prefix`.
|
|
92
|
+
# Dropping this helper would silently regress the Phase 3
|
|
93
|
+
# self-healing path back to "hint + exit 3".
|
|
94
|
+
"Invoke-RecoverEaccesPrefix"
|
|
84
95
|
)
|
|
85
96
|
|
|
86
97
|
foreach ($name in $expected) {
|
|
@@ -161,6 +172,58 @@ Describe "install.ps1 stderr log file (P1-I)" {
|
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
174
|
|
|
175
|
+
# ── EACCES auto-recovery (Phase 3) ───────────────────────────
|
|
176
|
+
#
|
|
177
|
+
# Static / structural guards for the Phase 3 self-healing path.
|
|
178
|
+
# Mirrors the install.sh design: when `npm install -g` fails with
|
|
179
|
+
# EACCES on the global node_modules, swap the npm prefix to a
|
|
180
|
+
# user-owned directory and retry exactly once. We deliberately do
|
|
181
|
+
# NOT mock `npm` / `[Environment]::SetEnvironmentVariable` here —
|
|
182
|
+
# Pester mocks for static .NET methods are fragile, and the rest of
|
|
183
|
+
# this test file uses structural / regex assertions for the same
|
|
184
|
+
# reason. Behaviour is exercised end-to-end via the staging EACCES
|
|
185
|
+
# soak (see `.cursor/skills/deploy-staging/install-verify.md`).
|
|
186
|
+
|
|
187
|
+
Describe "install.ps1 EACCES auto-recovery" {
|
|
188
|
+
It "writes to User-scope PATH (never Machine, to avoid UAC)" {
|
|
189
|
+
$content = Get-Content -Raw -Path $script:ScriptPath
|
|
190
|
+
# The recovery MUST persist on User scope; Machine-scope writes
|
|
191
|
+
# would silently re-prompt UAC and undo the whole point of
|
|
192
|
+
# falling back to a user-owned prefix.
|
|
193
|
+
$content | Should -Match 'SetEnvironmentVariable\(\s*"PATH"\s*,[^,]+,\s*"User"\s*\)'
|
|
194
|
+
$content | Should -Not -Match 'SetEnvironmentVariable\(\s*"PATH"\s*,[^,]+,\s*"Machine"\s*\)'
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
It "honours BEEOS_NO_NPM_PREFIX_FIX=1 as an opt-out" {
|
|
198
|
+
$content = Get-Content -Raw -Path $script:ScriptPath
|
|
199
|
+
$content | Should -Match "BEEOS_NO_NPM_PREFIX_FIX"
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
It "matches the EACCES fingerprint in the npm log" {
|
|
203
|
+
$content = Get-Content -Raw -Path $script:ScriptPath
|
|
204
|
+
# Same fingerprint string as install.sh's `grep -qE` — keeps
|
|
205
|
+
# the two scripts' classifier behaviour aligned. If you tighten
|
|
206
|
+
# the regex on one side, tighten it here too (and on
|
|
207
|
+
# install.sh) so a real EACCES on either platform still
|
|
208
|
+
# triggers recovery.
|
|
209
|
+
$content | Should -Match 'EACCES.*permission denied.*node_modules'
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
It "emits install.bootstrap.npm_recovered on retry success" {
|
|
213
|
+
$content = Get-Content -Raw -Path $script:ScriptPath
|
|
214
|
+
$content | Should -Match 'install\.bootstrap\.npm_recovered'
|
|
215
|
+
$content | Should -Match 'eacces_prefix'
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
It "still falls through to exit 3 when recovery is skipped or fails" {
|
|
219
|
+
$content = Get-Content -Raw -Path $script:ScriptPath
|
|
220
|
+
# Regression guard: the original hint + exit 3 path MUST stay
|
|
221
|
+
# reachable for non-EACCES failure modes (ETIMEDOUT, EBADENGINE,
|
|
222
|
+
# ENOSPC ...) and for the case where recovery itself bails.
|
|
223
|
+
$content | Should -Match 'exit 3'
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
164
227
|
# ── Dry-run hook ─────────────────────────────────────────────
|
|
165
228
|
|
|
166
229
|
Describe "install.ps1 dry-run hook" {
|
package/scripts/install.ps1
CHANGED
|
@@ -24,8 +24,23 @@
|
|
|
24
24
|
$env:BEEOS_DASHBOARD_URL Dashboard base (OAuth / bind redirect).
|
|
25
25
|
$env:BEEOS_INSTALL_DRY_RUN=1 CI smoke-test escape hatch.
|
|
26
26
|
$env:BEEOS_NO_TELEMETRY=1 Disable script-level telemetry POSTs.
|
|
27
|
+
$env:BEEOS_NO_DESKTOP=1 Skip TightVNC detection/install hint.
|
|
28
|
+
Forwarded to `beeos init` so the
|
|
29
|
+
CLI's desktop pipeline also stays
|
|
30
|
+
dormant (Phase 2 of the multi-OS
|
|
31
|
+
install-link refactor).
|
|
27
32
|
$env:BEEOS_USE_NPX = "1" Power-user throwaway install (beeos
|
|
28
33
|
won't persist on PATH).
|
|
34
|
+
$env:BEEOS_NO_NPM_PREFIX_FIX="1" Disable Phase 3 EACCES auto-recovery.
|
|
35
|
+
Recovery (default ON) detects
|
|
36
|
+
"EACCES on lib/node_modules" in the
|
|
37
|
+
npm log, switches the npm prefix
|
|
38
|
+
to %APPDATA%\npm, prepends it on
|
|
39
|
+
User-scope PATH (NEVER Machine —
|
|
40
|
+
that would re-trigger UAC), and
|
|
41
|
+
retries `npm install -g` once.
|
|
42
|
+
Set to 1 to fall back to the legacy
|
|
43
|
+
"hint + exit 3" behaviour.
|
|
29
44
|
|
|
30
45
|
IMPORTANT (env inheritance):
|
|
31
46
|
$env:BEEOS_API_URL / BEEOS_AGENT_GATEWAY_URL / BEEOS_DASHBOARD_URL
|
|
@@ -426,6 +441,80 @@ function Show-InstallHints {
|
|
|
426
441
|
}
|
|
427
442
|
}
|
|
428
443
|
|
|
444
|
+
# ── EACCES auto-recovery (Phase 3) ────────────────────────────
|
|
445
|
+
#
|
|
446
|
+
# Mirror of `install.sh::recover_eacces_prefix`. Phase 2 (Node install)
|
|
447
|
+
# already self-heals via winget → choco; Phase 3 (`npm install -g`)
|
|
448
|
+
# historically just printed a hint and exited. EACCES on Windows is
|
|
449
|
+
# rarer than on macOS — the default npm prefix is already user-scoped
|
|
450
|
+
# (`%APPDATA%\npm`) — but it does happen when an Administrator-
|
|
451
|
+
# installed Node has flipped the prefix to `C:\Program Files\nodejs\
|
|
452
|
+
# node_modules`. The fix is symmetric to the POSIX path: switch the
|
|
453
|
+
# prefix back to a user-owned directory and persist on User-scope
|
|
454
|
+
# PATH. We DELIBERATELY do not touch Machine-scope PATH — that would
|
|
455
|
+
# require UAC and silently re-trigger the elevation prompt the user
|
|
456
|
+
# already declined when winget/choco asked.
|
|
457
|
+
#
|
|
458
|
+
# Escape hatch: `$env:BEEOS_NO_NPM_PREFIX_FIX = "1"` short-circuits
|
|
459
|
+
# this function so power users / strict-policy operators can opt out.
|
|
460
|
+
function Invoke-RecoverEaccesPrefix {
|
|
461
|
+
if ($env:BEEOS_NO_NPM_PREFIX_FIX -eq "1") {
|
|
462
|
+
Write-BeeInfo "BEEOS_NO_NPM_PREFIX_FIX=1 — skipping auto npm prefix switch."
|
|
463
|
+
return $false
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
$appData = $env:APPDATA
|
|
467
|
+
if (-not $appData -or $appData.Length -eq 0) {
|
|
468
|
+
Write-BeeWarn "APPDATA env not set — cannot pick a user prefix. Falling back to hint."
|
|
469
|
+
return $false
|
|
470
|
+
}
|
|
471
|
+
$prefix = Join-Path $appData "npm"
|
|
472
|
+
Write-BeeInfo "Switching npm global prefix to $prefix (user-owned)."
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
New-Item -ItemType Directory -Path $prefix -Force | Out-Null
|
|
476
|
+
} catch {
|
|
477
|
+
Write-BeeError "Could not create ${prefix}: $_"
|
|
478
|
+
return $false
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
try {
|
|
482
|
+
& npm config set prefix "$prefix" 2>&1 | Tee-Object -FilePath $BeeosInstallLog -Append | Out-Null
|
|
483
|
+
if ($LASTEXITCODE -ne 0) {
|
|
484
|
+
Write-BeeError "npm config set prefix failed (exit $LASTEXITCODE)."
|
|
485
|
+
return $false
|
|
486
|
+
}
|
|
487
|
+
} catch {
|
|
488
|
+
Write-BeeError "npm config set prefix threw: $_"
|
|
489
|
+
return $false
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
# Make $prefix usable for the upcoming retry IN this session.
|
|
493
|
+
# Persistence (next terminal) happens via SetEnvironmentVariable
|
|
494
|
+
# below.
|
|
495
|
+
$env:Path = "$prefix;" + $env:Path
|
|
496
|
+
|
|
497
|
+
# Persist to User-scope PATH so a new terminal sees it. Idempotent —
|
|
498
|
+
# re-running on an already-fixed host MUST NOT append a duplicate
|
|
499
|
+
# entry (the User PATH is global to the account; appending without
|
|
500
|
+
# a contains-check would grow it unboundedly across re-runs).
|
|
501
|
+
try {
|
|
502
|
+
$userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
|
|
503
|
+
if (-not $userPath) { $userPath = "" }
|
|
504
|
+
if (($userPath -split ";") -notcontains $prefix) {
|
|
505
|
+
$newUserPath = if ($userPath.Length -gt 0) { "$prefix;$userPath" } else { "$prefix" }
|
|
506
|
+
[Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User")
|
|
507
|
+
Write-BeeInfo "Persisted PATH to user environment. Set BEEOS_NO_NPM_PREFIX_FIX=1 to skip on re-runs."
|
|
508
|
+
} else {
|
|
509
|
+
Write-BeeInfo "User PATH already contains $prefix — leaving as-is."
|
|
510
|
+
}
|
|
511
|
+
} catch {
|
|
512
|
+
Write-BeeWarn "Could not persist user PATH: $_"
|
|
513
|
+
Write-BeeWarn " Add $prefix to PATH manually to keep beeos discoverable in new terminals."
|
|
514
|
+
}
|
|
515
|
+
return $true
|
|
516
|
+
}
|
|
517
|
+
|
|
429
518
|
# ── Run CLI ──────────────────────────────────────────────────
|
|
430
519
|
|
|
431
520
|
function Invoke-BeeosCli {
|
|
@@ -464,18 +553,49 @@ function Invoke-BeeosCli {
|
|
|
464
553
|
& npm install -g $CliPackage 2>&1 | Tee-Object -FilePath $BeeosInstallLog -Append
|
|
465
554
|
$npmExit = $LASTEXITCODE
|
|
466
555
|
if ($npmExit -ne 0) {
|
|
467
|
-
#
|
|
468
|
-
#
|
|
469
|
-
#
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
556
|
+
# ── EACCES auto-recovery ──────────────────────────────────
|
|
557
|
+
# Mirror of install.sh's failure-branch recovery. We grep the
|
|
558
|
+
# teed log for the EACCES fingerprint; if it matches AND the
|
|
559
|
+
# user hasn't disabled the auto-fix, we swap the npm prefix
|
|
560
|
+
# to %APPDATA%\npm + persist to User PATH and retry exactly
|
|
561
|
+
# once. Other npm error classes (ENOSPC / E401 / EBADENGINE
|
|
562
|
+
# / ...) fall through to the existing hint+exit path —
|
|
563
|
+
# rarer, and need user judgement we can't safely automate.
|
|
564
|
+
$recovered = $false
|
|
565
|
+
$logContent = if (Test-Path $BeeosInstallLog) {
|
|
566
|
+
Get-Content -Raw -Path $BeeosInstallLog
|
|
567
|
+
} else { "" }
|
|
568
|
+
if ($logContent -match 'EACCES.*permission denied.*node_modules') {
|
|
569
|
+
Write-BeeWarn "Detected EACCES on global node_modules — attempting auto-recovery."
|
|
570
|
+
if (Invoke-RecoverEaccesPrefix) {
|
|
571
|
+
Write-BeeInfo "Retrying npm install with user-owned prefix..."
|
|
572
|
+
& npm install -g $CliPackage 2>&1 | Tee-Object -FilePath $BeeosInstallLog -Append
|
|
573
|
+
if ($LASTEXITCODE -eq 0) {
|
|
574
|
+
Send-Telemetry -Event "install.bootstrap.npm_recovered" -ErrorCode "eacces_prefix"
|
|
575
|
+
$recovered = $true
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
# ── End recovery ──────────────────────────────────────────
|
|
580
|
+
|
|
581
|
+
if (-not $recovered) {
|
|
582
|
+
# P0-A of the install-link review: fail-after-bootstrap signal.
|
|
583
|
+
# The `install.bootstrap.cli_installed` event is only emitted
|
|
584
|
+
# AFTER npm reports success.
|
|
585
|
+
Send-Telemetry -Event "install.bootstrap.npm_fail" -ErrorCode "npm_install_cli_failed" -Success $false
|
|
586
|
+
Write-BeeError "npm install -g $CliPackage failed."
|
|
587
|
+
Write-BeeError " Full log: $BeeosInstallLog"
|
|
588
|
+
Write-BeeError ""
|
|
589
|
+
Write-BeeError "Common fixes:"
|
|
590
|
+
Write-BeeError " - EEXIST on beeos from another package:"
|
|
591
|
+
Write-BeeError " npm uninstall -g @beeos-ai/cli # then re-run installer"
|
|
592
|
+
Write-BeeError " - EACCES / permission error:"
|
|
593
|
+
Write-BeeError " auto-recovery already attempted; if it failed, manually"
|
|
594
|
+
Write-BeeError " run ``npm config set prefix `"`$env:APPDATA\npm`"`` and"
|
|
595
|
+
Write-BeeError " add `$env:APPDATA\npm to your User PATH, then re-run installer."
|
|
596
|
+
Write-BeeError " (Set `$env:BEEOS_NO_NPM_PREFIX_FIX = '1' to disable auto-recovery.)"
|
|
597
|
+
exit 3
|
|
598
|
+
}
|
|
479
599
|
}
|
|
480
600
|
# Device-agent suite is intentionally NOT installed here; `beeos
|
|
481
601
|
# device attach` will auto-install it on first use via
|
|
@@ -562,6 +682,47 @@ if (-not (Test-NodeVersion)) {
|
|
|
562
682
|
$nodeVer = & node -v
|
|
563
683
|
Write-BeeOk "Node.js $nodeVer detected"
|
|
564
684
|
|
|
685
|
+
# ── TightVNC detection (Phase 2 of multi-OS install-link refactor) ────
|
|
686
|
+
#
|
|
687
|
+
# BeeOS desktop streaming on Windows uses TightVNC + the existing
|
|
688
|
+
# vnc-bridge sidecar (same RFB pipeline as macOS / Linux). The CLI's
|
|
689
|
+
# `DesktopPlatform.windows` adapter takes over once `beeos init` runs:
|
|
690
|
+
# it generates a viewer password, writes the TightVNC registry config
|
|
691
|
+
# under UAC, and starts/restarts `tvnserver`. This script's only job
|
|
692
|
+
# at install time is the user-facing hint — pointing the user at
|
|
693
|
+
# `winget install GlavSoft.TightVNC` so the cold-start has something
|
|
694
|
+
# to configure on the next `beeos init`.
|
|
695
|
+
#
|
|
696
|
+
# Skipped entirely when:
|
|
697
|
+
# - $env:BEEOS_NO_DESKTOP = "1" (hint AND CLI desktop pipeline off)
|
|
698
|
+
# - the user opted into `-Device` mode (device-attach flow has its
|
|
699
|
+
# own VNC handling via `--vnc-host`).
|
|
700
|
+
function Test-VncServer {
|
|
701
|
+
if ($env:BEEOS_NO_DESKTOP -eq "1") {
|
|
702
|
+
Write-BeeInfo "BEEOS_NO_DESKTOP=1 — skipping TightVNC detection."
|
|
703
|
+
return
|
|
704
|
+
}
|
|
705
|
+
if ($Device) {
|
|
706
|
+
# device-attach handles its own VNC story; the OpenClaw
|
|
707
|
+
# auto-desktop path is only taken by `beeos init`.
|
|
708
|
+
return
|
|
709
|
+
}
|
|
710
|
+
$svc = Get-Service tvnserver -ErrorAction SilentlyContinue
|
|
711
|
+
$reg = Test-Path "HKLM:\SOFTWARE\TightVNC\Server"
|
|
712
|
+
if ($svc -or $reg) {
|
|
713
|
+
Write-BeeOk "TightVNC detected — `beeos init` will configure it for desktop streaming."
|
|
714
|
+
return
|
|
715
|
+
}
|
|
716
|
+
Write-Host ""
|
|
717
|
+
Write-BeeInfo "Optional: BeeOS desktop streaming on Windows uses TightVNC."
|
|
718
|
+
Write-Host " Install with:" -ForegroundColor White
|
|
719
|
+
Write-Host " winget install GlavSoft.TightVNC --accept-package-agreements --accept-source-agreements --silent"
|
|
720
|
+
Write-Host ""
|
|
721
|
+
Write-Host " Then re-run `beeos init`. Set $env:BEEOS_NO_DESKTOP = '1' to suppress this hint." -ForegroundColor DarkGray
|
|
722
|
+
Write-Host ""
|
|
723
|
+
}
|
|
724
|
+
Test-VncServer
|
|
725
|
+
|
|
565
726
|
# Bootstrap is finished. Hand off to `Invoke-BeeosCli` which performs
|
|
566
727
|
# `npm install -g @beeos-ai/cli` (idempotent — npm short-circuits when
|
|
567
728
|
# the requested version is already on disk) and then runs the freshly
|
package/scripts/install.sh
CHANGED
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
# 3 `npm install -g @beeos-ai/cli` failed (CLI didn't reach PATH)
|
|
30
30
|
#
|
|
31
31
|
# Automation can branch on these — `1` is "fix your Node install",
|
|
32
|
-
# `2` is "wrong machine", `3` is "your npm prefix / proxy / disk
|
|
32
|
+
# `2` is "wrong machine", `3` is "your npm prefix / proxy / disk
|
|
33
|
+
# (after EACCES auto-recovery already attempted, see
|
|
34
|
+
# `BEEOS_NO_NPM_PREFIX_FIX` below)".
|
|
33
35
|
#
|
|
34
36
|
# ── Optional env vars ─────────────────────────────────────────────
|
|
35
37
|
# BEEOS_API_URL Public API base (this script uses it for
|
|
@@ -43,8 +45,30 @@
|
|
|
43
45
|
# BEEOS_INSTALL_DRY_RUN=1 CI smoke-test escape hatch — return 0
|
|
44
46
|
# from main() before any side effect.
|
|
45
47
|
# BEEOS_NO_TELEMETRY=1 Disable the script-level telemetry POSTs.
|
|
48
|
+
# BEEOS_NO_DESKTOP=1 Skip the TigerVNC pre-check (Linux) and
|
|
49
|
+
# forwarded to `beeos init` so the CLI's
|
|
50
|
+
# `getDesktopPipeline()` chokepoint also
|
|
51
|
+
# short-circuits, suppressing every macOS /
|
|
52
|
+
# Linux cold-start side effect. Mirrors
|
|
53
|
+
# install.ps1's same-named env var.
|
|
46
54
|
# BEEOS_USE_NPX=1 Power-user throwaway install (beeos won't
|
|
47
55
|
# persist on PATH).
|
|
56
|
+
# BEEOS_NO_NPM_PREFIX_FIX=1 Disable Phase 3 EACCES auto-recovery.
|
|
57
|
+
# Recovery (default ON) detects "EACCES on
|
|
58
|
+
# lib/node_modules" in the npm log, switches
|
|
59
|
+
# the npm global prefix to ~/.npm-global,
|
|
60
|
+
# persists $HOME/.npm-global/bin on PATH via
|
|
61
|
+
# the user's shell rc (zsh -> ~/.zshrc, bash
|
|
62
|
+
# -> ~/.bash_profile on macOS or ~/.bashrc
|
|
63
|
+
# on Linux), and retries `npm install -g`
|
|
64
|
+
# exactly once. The shell rc edit is wrapped
|
|
65
|
+
# in a sentinel block (`# >>> beeos
|
|
66
|
+
# npm-prefix >>>` ... `# <<< beeos
|
|
67
|
+
# npm-prefix <<<`) so it can be reverted by
|
|
68
|
+
# removing the block AND running
|
|
69
|
+
# `npm config delete prefix`. Set this var
|
|
70
|
+
# to 1 to fall back to the legacy
|
|
71
|
+
# "hint + exit 3" behaviour.
|
|
48
72
|
#
|
|
49
73
|
# IMPORTANT (env inheritance):
|
|
50
74
|
# BEEOS_API_URL / BEEOS_AGENT_GATEWAY_URL / BEEOS_DASHBOARD_URL must
|
|
@@ -451,6 +475,188 @@ print_install_hints() {
|
|
|
451
475
|
echo ""
|
|
452
476
|
}
|
|
453
477
|
|
|
478
|
+
# ── TigerVNC pre-check (Linux desktop streaming) ─────────────
|
|
479
|
+
#
|
|
480
|
+
# Mirrors install.ps1's `Test-VncServer`. BeeOS desktop streaming on
|
|
481
|
+
# Linux uses TigerVNC + the `vnc-bridge` sidecar (same RFB pipeline
|
|
482
|
+
# as macOS / Windows). The CLI's `LinuxDesktopPlatform` adapter takes
|
|
483
|
+
# over once `beeos init` runs: it generates a viewer password,
|
|
484
|
+
# writes `~/.vnc/passwd` via `tigervncpasswd -f`, mirrors plaintext
|
|
485
|
+
# into `~/.beeos/vnc.password`, and starts `vncserver :1 -localhost
|
|
486
|
+
# yes` if not already listening. This script's only job at install
|
|
487
|
+
# time is the user-facing hint — pointing the user at the
|
|
488
|
+
# distro-appropriate package so the cold-start has something to
|
|
489
|
+
# configure on the next `beeos init`.
|
|
490
|
+
#
|
|
491
|
+
# Skipped entirely when:
|
|
492
|
+
# - $BEEOS_NO_DESKTOP = "1" (hint AND CLI desktop pipeline off)
|
|
493
|
+
# - the user invoked `--device` mode (device-attach handles its own
|
|
494
|
+
# VNC story via `--vnc-host`).
|
|
495
|
+
# - host is darwin (macOS Screen Sharing is built-in; the CLI's
|
|
496
|
+
# `MacosDesktopPlatform` cold-start handles enable + password
|
|
497
|
+
# generation, no install-time hint needed).
|
|
498
|
+
#
|
|
499
|
+
# Detection: command -v tigervncpasswd or vncpasswd. Both are part
|
|
500
|
+
# of standard distro packages (tigervnc-standalone-server on
|
|
501
|
+
# Debian/Ubuntu, tigervnc-server on Fedora/RHEL, tigervnc on Arch).
|
|
502
|
+
test_vnc_server() {
|
|
503
|
+
if [[ "${BEEOS_NO_DESKTOP:-}" == "1" ]]; then
|
|
504
|
+
info "BEEOS_NO_DESKTOP=1 — skipping TigerVNC pre-check."
|
|
505
|
+
return 0
|
|
506
|
+
fi
|
|
507
|
+
if [[ "$MODE" == "device" ]]; then
|
|
508
|
+
return 0
|
|
509
|
+
fi
|
|
510
|
+
if [[ "$OS_KIND" != "linux" ]]; then
|
|
511
|
+
return 0
|
|
512
|
+
fi
|
|
513
|
+
if command -v tigervncpasswd &>/dev/null || command -v vncpasswd &>/dev/null; then
|
|
514
|
+
success "TigerVNC detected — \`beeos init\` will configure it for desktop streaming."
|
|
515
|
+
return 0
|
|
516
|
+
fi
|
|
517
|
+
echo ""
|
|
518
|
+
info "Optional: BeeOS desktop streaming on Linux uses TigerVNC."
|
|
519
|
+
echo " Install with one of:"
|
|
520
|
+
echo " Debian/Ubuntu: sudo apt install tigervnc-standalone-server"
|
|
521
|
+
echo " RHEL/Fedora: sudo dnf install tigervnc-server"
|
|
522
|
+
echo " Arch: sudo pacman -S tigervnc"
|
|
523
|
+
echo ""
|
|
524
|
+
echo " Then re-run \`beeos init\`. Set BEEOS_NO_DESKTOP=1 to suppress this hint."
|
|
525
|
+
echo ""
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
# ── EACCES auto-recovery (Phase 3) ────────────────────────────
|
|
529
|
+
#
|
|
530
|
+
# Phase 2 of the bootstrap pipeline (Node install) already has a
|
|
531
|
+
# multi-strategy auto-recovery loop in `try_install_node` (nvm → fnm
|
|
532
|
+
# → brew). Phase 3 (`npm install -g @beeos-ai/cli`) historically had
|
|
533
|
+
# none — it just printed a hint and exited 3. The single most common
|
|
534
|
+
# Phase 3 failure is EACCES on the system-owned global node_modules
|
|
535
|
+
# (typically `/usr/local/lib/node_modules` after a nodejs.org .pkg
|
|
536
|
+
# install or a sudo brew install). The two helpers below close that
|
|
537
|
+
# gap with the same shape Phase 2 uses: a small detect function +
|
|
538
|
+
# an idempotent recovery function. `run_cli` calls them only when
|
|
539
|
+
# the npm log carries the EACCES fingerprint; every other npm
|
|
540
|
+
# failure mode is rarer and needs user judgement we can't safely
|
|
541
|
+
# automate from a curl|bash one-liner.
|
|
542
|
+
|
|
543
|
+
# Detect the user's preferred shell init file so that an `export
|
|
544
|
+
# PATH=...` write survives a new terminal. We support zsh + bash
|
|
545
|
+
# (~95% of macOS / Linux users); fish / tcsh / nushell users get a
|
|
546
|
+
# printed hint instead of a silent edit to a file we don't fully
|
|
547
|
+
# understand. `$SHELL` is the login shell as recorded in /etc/passwd,
|
|
548
|
+
# NOT the currently-running interpreter — that's exactly what we want
|
|
549
|
+
# for "what does the user's NEXT terminal source?".
|
|
550
|
+
detect_shell_rc() {
|
|
551
|
+
local shell_name
|
|
552
|
+
shell_name="$(basename "${SHELL:-}")"
|
|
553
|
+
case "$shell_name" in
|
|
554
|
+
zsh)
|
|
555
|
+
# zsh's per-user interactive rc. macOS Terminal.app sources it
|
|
556
|
+
# for both login and non-login zsh sessions. We deliberately do
|
|
557
|
+
# NOT touch ~/.zprofile (login-only) — keeping all our writes
|
|
558
|
+
# in a single file makes "how do I revert?" a one-line answer.
|
|
559
|
+
printf '%s' "$HOME/.zshrc"
|
|
560
|
+
;;
|
|
561
|
+
bash)
|
|
562
|
+
# macOS Terminal.app launches each window as a login bash, so
|
|
563
|
+
# the canonical sourced file is ~/.bash_profile. Linux GUI
|
|
564
|
+
# terminals run interactive non-login bash and source ~/.bashrc.
|
|
565
|
+
if [[ "$OS_KIND" == "darwin" ]]; then
|
|
566
|
+
printf '%s' "$HOME/.bash_profile"
|
|
567
|
+
else
|
|
568
|
+
printf '%s' "$HOME/.bashrc"
|
|
569
|
+
fi
|
|
570
|
+
;;
|
|
571
|
+
*)
|
|
572
|
+
# Empty string ⇒ caller falls back to a manual-paste hint.
|
|
573
|
+
printf '%s' ""
|
|
574
|
+
;;
|
|
575
|
+
esac
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
# Switch the npm global prefix to a user-owned directory and persist
|
|
579
|
+
# the resulting PATH change to the user's shell rc. Used as the EACCES
|
|
580
|
+
# auto-recovery in `run_cli`. Idempotent — running on an already-
|
|
581
|
+
# fixed host is a no-op (the sentinel block check below prevents
|
|
582
|
+
# duplicate appends).
|
|
583
|
+
#
|
|
584
|
+
# Why this approach (and not the alternatives):
|
|
585
|
+
#
|
|
586
|
+
# - sudo retry: would leave /usr/local/lib/node_modules/@beeos-ai/cli
|
|
587
|
+
# owned by root, breaking the next `npm update -g` and creating
|
|
588
|
+
# ownership inconsistencies between the CLI binary and ~/.beeos
|
|
589
|
+
# (which the user owns). It's the kind of "fix" that buries the
|
|
590
|
+
# real problem deeper.
|
|
591
|
+
#
|
|
592
|
+
# - force-install nvm: intrusive for a user who already has a
|
|
593
|
+
# working Node toolchain, and risks breaking other tools that
|
|
594
|
+
# depend on the system Node path.
|
|
595
|
+
#
|
|
596
|
+
# - just print a hint: the original behaviour. Pushes the fix onto
|
|
597
|
+
# the user, who has to switch contexts mid-install. Most users
|
|
598
|
+
# give up here.
|
|
599
|
+
#
|
|
600
|
+
# The chosen path mirrors npm's own documentation:
|
|
601
|
+
# https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
|
|
602
|
+
#
|
|
603
|
+
# Escape hatch: `BEEOS_NO_NPM_PREFIX_FIX=1` short-circuits this
|
|
604
|
+
# function so power users / strict-dotfiles operators can opt out.
|
|
605
|
+
recover_eacces_prefix() {
|
|
606
|
+
if [[ "${BEEOS_NO_NPM_PREFIX_FIX:-}" == "1" ]]; then
|
|
607
|
+
info "BEEOS_NO_NPM_PREFIX_FIX=1 — skipping auto npm prefix switch."
|
|
608
|
+
return 1
|
|
609
|
+
fi
|
|
610
|
+
|
|
611
|
+
local prefix="$HOME/.npm-global"
|
|
612
|
+
info "Switching npm global prefix to ${prefix} (user-owned)."
|
|
613
|
+
|
|
614
|
+
if ! mkdir -p "$prefix" >> "$BEEOS_INSTALL_LOG" 2>&1; then
|
|
615
|
+
error "Could not create ${prefix} — falling back to hint."
|
|
616
|
+
return 1
|
|
617
|
+
fi
|
|
618
|
+
if ! npm config set prefix "$prefix" >> "$BEEOS_INSTALL_LOG" 2>&1; then
|
|
619
|
+
error "npm config set prefix failed — falling back to hint."
|
|
620
|
+
return 1
|
|
621
|
+
fi
|
|
622
|
+
|
|
623
|
+
# Make the new prefix usable for the upcoming retry IN this
|
|
624
|
+
# session. Persistence (next terminal) happens via shell rc below.
|
|
625
|
+
export PATH="$prefix/bin:$PATH"
|
|
626
|
+
|
|
627
|
+
local rc
|
|
628
|
+
rc="$(detect_shell_rc)"
|
|
629
|
+
if [[ -z "$rc" ]]; then
|
|
630
|
+
warn "Unsupported login shell ($(basename "${SHELL:-unknown}")) — could not"
|
|
631
|
+
warn " persist PATH automatically. Add this line to your shell init:"
|
|
632
|
+
warn " export PATH=\"$prefix/bin:\$PATH\""
|
|
633
|
+
return 0
|
|
634
|
+
fi
|
|
635
|
+
|
|
636
|
+
# Sentinel block — grep + sed can remove it cleanly. We check for
|
|
637
|
+
# the BEGIN marker so re-runs of the installer don't append the
|
|
638
|
+
# block twice (the file may have been edited by hand between runs).
|
|
639
|
+
local marker_begin="# >>> beeos npm-prefix >>>"
|
|
640
|
+
local marker_end="# <<< beeos npm-prefix <<<"
|
|
641
|
+
if [[ -f "$rc" ]] && grep -qF "$marker_begin" "$rc"; then
|
|
642
|
+
info "Sentinel block already present in ${rc} — leaving as-is."
|
|
643
|
+
return 0
|
|
644
|
+
fi
|
|
645
|
+
|
|
646
|
+
# `>>` never clobbers existing content. If the rc doesn't exist yet
|
|
647
|
+
# (fresh user account), the redirect creates it with 0644 perms.
|
|
648
|
+
{
|
|
649
|
+
printf '\n%s\n' "$marker_begin"
|
|
650
|
+
printf '# Added by https://beeos.ai/install on %s\n' "$(date -u +%FT%TZ)"
|
|
651
|
+
printf '# Reason: system npm prefix was not writable (EACCES).\n'
|
|
652
|
+
printf '# To revert: delete this block AND run `npm config delete prefix`.\n'
|
|
653
|
+
printf 'export PATH="%s/bin:$PATH"\n' "$prefix"
|
|
654
|
+
printf '%s\n' "$marker_end"
|
|
655
|
+
} >> "$rc"
|
|
656
|
+
info "Persisted PATH to ${rc}. Set BEEOS_NO_NPM_PREFIX_FIX=1 to skip on re-runs."
|
|
657
|
+
return 0
|
|
658
|
+
}
|
|
659
|
+
|
|
454
660
|
# ── Main ─────────────────────────────────────────────────────
|
|
455
661
|
|
|
456
662
|
run_cli() {
|
|
@@ -497,6 +703,28 @@ run_cli() {
|
|
|
497
703
|
# the time they go to copy-paste. `set -o pipefail` (file header)
|
|
498
704
|
# ensures the pipe's exit status is `npm`'s, not `tee`'s.
|
|
499
705
|
if ! npm install -g "$CLI_PACKAGE" 2>&1 | tee -a "$BEEOS_INSTALL_LOG"; then
|
|
706
|
+
# ── EACCES auto-recovery ──────────────────────────────────────
|
|
707
|
+
# The single most common Phase 3 failure: the system npm prefix
|
|
708
|
+
# is owned by root, EACCES on rename. Detect the fingerprint in
|
|
709
|
+
# the npm log we just teed; if it matches, swap the prefix to a
|
|
710
|
+
# user-owned dir (see `recover_eacces_prefix` for the rationale)
|
|
711
|
+
# and retry exactly once. Every other npm error class
|
|
712
|
+
# (ENOSPC / ETIMEDOUT / EBADENGINE / ...) falls through to the
|
|
713
|
+
# hint+exit path below — those are rarer in practice and need
|
|
714
|
+
# human judgement we can't safely automate.
|
|
715
|
+
if grep -qE 'EACCES.*permission denied.*node_modules' "$BEEOS_INSTALL_LOG"; then
|
|
716
|
+
warn "Detected EACCES on global node_modules — attempting auto-recovery."
|
|
717
|
+
if recover_eacces_prefix; then
|
|
718
|
+
info "Retrying npm install with user-owned prefix..."
|
|
719
|
+
if npm install -g "$CLI_PACKAGE" 2>&1 | tee -a "$BEEOS_INSTALL_LOG"; then
|
|
720
|
+
send_telemetry "install.bootstrap.npm_recovered" "eacces_prefix"
|
|
721
|
+
send_telemetry "install.bootstrap.cli_installed"
|
|
722
|
+
exec beeos "$subcmd" "$@" <"$stdin_src"
|
|
723
|
+
fi
|
|
724
|
+
fi
|
|
725
|
+
fi
|
|
726
|
+
# ── End recovery ──────────────────────────────────────────────
|
|
727
|
+
|
|
500
728
|
# P0-A of the install-link review: separate "Node ready" from
|
|
501
729
|
# "CLI is actually on PATH" so the dashboard never reports a
|
|
502
730
|
# success that the user can't reproduce. `install.bootstrap.npm_fail`
|
|
@@ -509,7 +737,10 @@ run_cli() {
|
|
|
509
737
|
error " - EEXIST on /bin/beeos from another package:"
|
|
510
738
|
error " npm uninstall -g @beeos-ai/cli # then re-run installer"
|
|
511
739
|
error " - EACCES permission error:"
|
|
512
|
-
error "
|
|
740
|
+
error " auto-recovery already attempted; if it failed, manually"
|
|
741
|
+
error " run \`npm config set prefix \"\$HOME/.npm-global\"\` and"
|
|
742
|
+
error " add \$HOME/.npm-global/bin to PATH, then re-run installer."
|
|
743
|
+
error " (Set BEEOS_NO_NPM_PREFIX_FIX=1 to disable auto-recovery.)"
|
|
513
744
|
exit 3
|
|
514
745
|
fi
|
|
515
746
|
# NPM succeeded — CLI is now on PATH. The device-agent suite is
|
|
@@ -559,6 +790,13 @@ main() {
|
|
|
559
790
|
|
|
560
791
|
success "Node.js $(node -v) detected"
|
|
561
792
|
|
|
793
|
+
# Phase 3 of the multi-OS install-link refactor: TigerVNC pre-check
|
|
794
|
+
# for Linux. Parallels install.ps1's `Test-VncServer`. Silent
|
|
795
|
+
# success when the tool is on PATH; printable hint when missing.
|
|
796
|
+
# Skipped on darwin (macOS Screen Sharing is configured by the
|
|
797
|
+
# CLI's `MacosDesktopPlatform` cold-start) and in `--device` mode.
|
|
798
|
+
test_vnc_server
|
|
799
|
+
|
|
562
800
|
# Bootstrap is finished. Hand off to `run_cli` which performs
|
|
563
801
|
# `npm install -g @beeos-ai/cli` (idempotent — npm short-circuits
|
|
564
802
|
# when the requested version is already on disk) and then `exec`s
|