@beeos-ai/cli 1.0.17 → 1.0.19
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/dist/index.js +613 -541
- package/package.json +1 -1
- package/scripts/_existing_install_actions.json +30 -34
- package/scripts/install.Tests.ps1 +3 -1
- package/scripts/install.ps1 +58 -130
- package/scripts/install.sh +106 -157
package/scripts/install.sh
CHANGED
|
@@ -1,58 +1,68 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
3
|
# BeeOS CLI Installer (macOS / Linux)
|
|
4
|
+
#
|
|
4
5
|
# Usage:
|
|
5
6
|
# curl -fsSL https://beeos.ai/install | bash
|
|
6
7
|
# curl -fsSL https://beeos.ai/install | bash -s -- [beeos init args]
|
|
7
|
-
# curl -fsSL https://beeos.ai/install | bash -s -- --device
|
|
8
|
+
# curl -fsSL https://beeos.ai/install | bash -s -- --device # → beeos device attach
|
|
8
9
|
#
|
|
9
|
-
#
|
|
10
|
+
# Responsibilities (deliberately minimal — framework-agnostic):
|
|
10
11
|
# 1. Detect OS + CPU architecture, refuse unsupported targets early.
|
|
11
|
-
# 2. Make sure Node.js >= MIN_NODE_VERSION is available (install via
|
|
12
|
-
# fnm / brew when possible).
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# 4.
|
|
17
|
-
#
|
|
12
|
+
# 2. Make sure Node.js >= MIN_NODE_VERSION is available (install via
|
|
13
|
+
# nvm / fnm / brew when possible). All heavier dependencies (adb,
|
|
14
|
+
# scrcpy-bridge, the device-agent suite) are installed lazily by
|
|
15
|
+
# the CLI itself when the user actually needs them.
|
|
16
|
+
# 3. `npm install -g @beeos-ai/cli`.
|
|
17
|
+
# 4. `exec beeos init` (or `beeos device attach` with `--device`).
|
|
18
|
+
#
|
|
19
|
+
# Anything else — "you already have BeeOS installed, what now?",
|
|
20
|
+
# framework selection, rebind variants — lives inside the CLI's own
|
|
21
|
+
# `beeos init` menu, not here. The bootstrap script stays small so it's
|
|
22
|
+
# easy to maintain and easy to diagnose on a customer machine.
|
|
23
|
+
#
|
|
24
|
+
# ── Exit codes ────────────────────────────────────────────────────
|
|
25
|
+
# 0 Success (or `exec` handed off — the CLI's own exit code wins)
|
|
26
|
+
# 1 Node bootstrap failure (Node missing / version too old / npm
|
|
27
|
+
# not on PATH after Node install)
|
|
28
|
+
# 2 Unsupported OS / CPU architecture (and user declined override)
|
|
29
|
+
# 3 `npm install -g @beeos-ai/cli` failed (CLI didn't reach PATH)
|
|
30
|
+
#
|
|
31
|
+
# Automation can branch on these — `1` is "fix your Node install",
|
|
32
|
+
# `2` is "wrong machine", `3` is "your npm prefix / proxy / disk".
|
|
33
|
+
#
|
|
34
|
+
# ── Optional env vars ─────────────────────────────────────────────
|
|
35
|
+
# BEEOS_API_URL Public API base (this script uses it for
|
|
36
|
+
# telemetry; the CLI uses it for runtime).
|
|
37
|
+
# Defaults to production.
|
|
38
|
+
# BEEOS_AGENT_GATEWAY_URL Agent Gateway base (forwarded as-is to the
|
|
39
|
+
# spawned CLI).
|
|
40
|
+
# BEEOS_DASHBOARD_URL Dashboard base (OAuth / bind redirect).
|
|
41
|
+
# BEEOS_INSTALL_LOG Path to a forensic log of Node-bootstrap
|
|
42
|
+
# stderr; defaults to /tmp/beeos-install-$$.log.
|
|
43
|
+
# BEEOS_INSTALL_DRY_RUN=1 CI smoke-test escape hatch — return 0
|
|
44
|
+
# from main() before any side effect.
|
|
45
|
+
# BEEOS_NO_TELEMETRY=1 Disable the script-level telemetry POSTs.
|
|
46
|
+
# BEEOS_USE_NPX=1 Power-user throwaway install (beeos won't
|
|
47
|
+
# persist on PATH).
|
|
18
48
|
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
# (telemetry) + BEEOS_AGENT_GATEWAY_URL (runtime).
|
|
49
|
+
# IMPORTANT (env inheritance):
|
|
50
|
+
# BEEOS_API_URL / BEEOS_AGENT_GATEWAY_URL / BEEOS_DASHBOARD_URL must
|
|
51
|
+
# be set in THE SHELL THAT RUNS THIS SCRIPT before the curl pipe.
|
|
52
|
+
# They reach `beeos init` only via the normal exec env passthrough
|
|
53
|
+
# — there is NO auto-injection from the curl arguments.
|
|
25
54
|
#
|
|
26
|
-
# BEEOS_API_URL
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
# BEEOS_DASHBOARD_URL Dashboard base (OAuth + bind redirect).
|
|
31
|
-
# BEEOS_DEVICE_AGENT_VERSION Pin @beeos-ai/device-agent semver.
|
|
32
|
-
# NOT consumed by this script (CLI ≥ 1.0.16
|
|
33
|
-
# installs the device suite lazily on the
|
|
34
|
-
# first `beeos device attach`); export it
|
|
35
|
-
# in the shell that runs `beeos device
|
|
36
|
-
# attach` instead.
|
|
37
|
-
# BEEOS_MCP_SERVER_VERSION Same as above, for @beeos-ai/device-mcp-server.
|
|
38
|
-
# BEEOS_USE_NPX=1 (Power-user escape hatch) Use `npx` for a
|
|
39
|
-
# throwaway install. `beeos` will NOT
|
|
40
|
-
# persist on PATH after the script exits.
|
|
41
|
-
# Default behaviour (since CLI 1.0.11) is
|
|
42
|
-
# always `npm install -g` so the CLI is
|
|
43
|
-
# globally available for follow-up commands.
|
|
44
|
-
# The device-agent suite is no longer
|
|
45
|
-
# eagerly installed (CLI ≥ 1.0.16); see
|
|
46
|
-
# `web/packages/core/src/device-setup.ts`.
|
|
55
|
+
# Working: `BEEOS_API_URL=... bash -c 'curl ...| bash'`
|
|
56
|
+
# Working: Set the var in your shell profile, then run normally.
|
|
57
|
+
# Broken: `bash -c "BEEOS_API_URL=... curl ... | bash"`
|
|
58
|
+
# (the var is local to the inner bash, not exported).
|
|
47
59
|
#
|
|
48
|
-
#
|
|
49
|
-
# add `BEEOS_DEVICE_AGENT_VERSION=...` to the shell when you later run
|
|
50
|
-
# `beeos device attach` if you need to pin a specific build):
|
|
60
|
+
# Bare-metal staging one-liner:
|
|
51
61
|
#
|
|
52
62
|
# BEEOS_API_URL=https://public-api-staging.beeos.ai \
|
|
53
63
|
# BEEOS_AGENT_GATEWAY_URL=https://agent-gw-staging.beeos.ai \
|
|
54
64
|
# BEEOS_DASHBOARD_URL=https://beeos-staging-web.vercel.app \
|
|
55
|
-
# curl -fsSL https://beeos.ai/install | bash -s -- --version 1.0.
|
|
65
|
+
# curl -fsSL https://beeos.ai/install | bash -s -- --version 1.0.18
|
|
56
66
|
|
|
57
67
|
set -euo pipefail
|
|
58
68
|
|
|
@@ -65,11 +75,6 @@ RED="\033[31m"
|
|
|
65
75
|
CYAN="\033[36m"
|
|
66
76
|
|
|
67
77
|
CLI_PACKAGE="@beeos-ai/cli@latest"
|
|
68
|
-
# `@beeos-ai/device-agent` + `@beeos-ai/device-mcp-server` are NOT
|
|
69
|
-
# installed here. CLI ≥ 1.0.16 installs them lazily on the first
|
|
70
|
-
# `beeos device attach` via `ensureDeviceAgent` in
|
|
71
|
-
# `web/packages/core/src/device-setup.ts`. OpenClaw-only users never
|
|
72
|
-
# download the device suite at all.
|
|
73
78
|
MIN_NODE_VERSION=18
|
|
74
79
|
NVM_VERSION="v0.40.1"
|
|
75
80
|
FNM_INSTALL_URL="https://fnm.vercel.app/install"
|
|
@@ -116,6 +121,25 @@ success() { printf "${BOLD}${GREEN}[beeos]${RESET} %s\n" "$*"; }
|
|
|
116
121
|
# `BEEOS_NO_TELEMETRY=1` short-circuits everything. This matches the
|
|
117
122
|
# Node CLI's opt-out env var verbatim so a user who disabled telemetry
|
|
118
123
|
# for the CLI doesn't unexpectedly get events from the bootstrap.
|
|
124
|
+
# Minimal JSON string-value escaper. Maps the four characters that
|
|
125
|
+
# can break a `"..."` JSON literal to their backslash escapes:
|
|
126
|
+
#
|
|
127
|
+
# \ -> \\
|
|
128
|
+
# " -> \"
|
|
129
|
+
# <CR> -> \r
|
|
130
|
+
# <LF> -> \n
|
|
131
|
+
#
|
|
132
|
+
# We deliberately don't pull in jq (not always available) or full
|
|
133
|
+
# JSON encoding — telemetry payload values are short slugs and human
|
|
134
|
+
# strings, not arbitrary binary. Tab + control-char escaping is
|
|
135
|
+
# nice-to-have but the four cases above are the ones that actually
|
|
136
|
+
# show up (e.g. `error_code` strings carrying quoted reasons, or
|
|
137
|
+
# error messages with embedded newlines).
|
|
138
|
+
json_escape() {
|
|
139
|
+
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' \
|
|
140
|
+
| tr '\r' ' ' | tr '\n' ' '
|
|
141
|
+
}
|
|
142
|
+
|
|
119
143
|
send_telemetry() {
|
|
120
144
|
local event="$1"
|
|
121
145
|
local error_code="${2:-}"
|
|
@@ -137,13 +161,25 @@ send_telemetry() {
|
|
|
137
161
|
local host_hint
|
|
138
162
|
host_hint="$(hostname 2>/dev/null || echo unknown)-${os_arch}"
|
|
139
163
|
|
|
164
|
+
# 1.0.19: every value below goes through `json_escape` so a stray
|
|
165
|
+
# `"` or newline in any of these fields can't break the POST body.
|
|
166
|
+
# `success_flag` is a bare boolean literal — never user-controlled —
|
|
167
|
+
# so it stays unquoted/unescaped.
|
|
168
|
+
local ev_e os_e arch_e node_e ec_e host_e
|
|
169
|
+
ev_e=$(json_escape "$event")
|
|
170
|
+
os_e=$(json_escape "$os_kind")
|
|
171
|
+
arch_e=$(json_escape "$os_arch")
|
|
172
|
+
node_e=$(json_escape "$node_ver")
|
|
173
|
+
ec_e=$(json_escape "$error_code")
|
|
174
|
+
host_e=$(json_escape "$host_hint")
|
|
175
|
+
|
|
140
176
|
# POST body kept deliberately small — matches Node CLI payload.
|
|
141
177
|
# Note: `cli_version` is empty until after npx install; we fill it
|
|
142
178
|
# only when the bootstrap telemetry is fired post-install, from the
|
|
143
179
|
# Node side. For pre-install events it stays "" and that's fine.
|
|
144
180
|
local body
|
|
145
181
|
body=$(cat <<JSON
|
|
146
|
-
{"event":"${
|
|
182
|
+
{"event":"${ev_e}","cli_version":"","dist_tag":"","os":"${os_e}","arch":"${arch_e}","node_version":"${node_e}","success":${success_flag},"error_code":"${ec_e}","host_hint":"${host_e}"}
|
|
147
183
|
JSON
|
|
148
184
|
)
|
|
149
185
|
|
|
@@ -340,8 +376,12 @@ try_install_node() {
|
|
|
340
376
|
fi
|
|
341
377
|
fi
|
|
342
378
|
|
|
343
|
-
# 3. fnm — works on locked-down Linux without git/curl quirks
|
|
344
|
-
|
|
379
|
+
# 3. fnm — works on locked-down Linux without git/curl quirks AND
|
|
380
|
+
# on macOS where users have neither Homebrew nor an existing nvm
|
|
381
|
+
# (the historical 1.0.18 path required brew on darwin, which is not
|
|
382
|
+
# always available — corporate-managed Macs, fresh users).
|
|
383
|
+
if [[ "$OS_KIND" == "linux" || "$OS_KIND" == "darwin" ]] \
|
|
384
|
+
&& ! command -v fnm &>/dev/null; then
|
|
345
385
|
info "Trying fnm (single-user, no sudo)..."
|
|
346
386
|
if curl -fsSL "$FNM_INSTALL_URL" 2>>"$BEEOS_INSTALL_LOG" \
|
|
347
387
|
| bash -s -- --skip-shell >> "$BEEOS_INSTALL_LOG" 2>&1; then
|
|
@@ -355,7 +395,8 @@ try_install_node() {
|
|
|
355
395
|
fi
|
|
356
396
|
fi
|
|
357
397
|
|
|
358
|
-
# 4. macOS Homebrew
|
|
398
|
+
# 4. macOS Homebrew (last resort — already-installed brew only,
|
|
399
|
+
# we don't try to install brew itself).
|
|
359
400
|
if [[ "$OS_KIND" == "darwin" ]] && command -v brew &>/dev/null; then
|
|
360
401
|
info "Trying Homebrew..."
|
|
361
402
|
if brew install node >> "$BEEOS_INSTALL_LOG" 2>&1; then
|
|
@@ -410,76 +451,6 @@ print_install_hints() {
|
|
|
410
451
|
echo ""
|
|
411
452
|
}
|
|
412
453
|
|
|
413
|
-
# ── Existing install detection ───────────────────────────────
|
|
414
|
-
|
|
415
|
-
beeos_already_installed() {
|
|
416
|
-
if command -v beeos &>/dev/null; then
|
|
417
|
-
return 0
|
|
418
|
-
fi
|
|
419
|
-
return 1
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
beeos_current_version() {
|
|
423
|
-
# `beeos --version` currently prints just the semver string. Tolerate
|
|
424
|
-
# other formats by extracting the first dotted number we can find.
|
|
425
|
-
local out
|
|
426
|
-
out=$(beeos --version 2>/dev/null | head -n1 | tr -d '[:space:]' || true)
|
|
427
|
-
if [[ "$out" =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
|
428
|
-
echo "${BASH_REMATCH[0]}"
|
|
429
|
-
else
|
|
430
|
-
echo "$out"
|
|
431
|
-
fi
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
prompt_existing_install_action() {
|
|
435
|
-
# The labels here are anchored against the equivalents in
|
|
436
|
-
# install.ps1 (Read-ExistingInstallAction) and `init.ts`'s
|
|
437
|
-
# `decideAction` menu by
|
|
438
|
-
# `web/packages/cli/scripts/_existing_install_actions.json` and the
|
|
439
|
-
# vitest grep lint at
|
|
440
|
-
# `web/packages/cli/src/__tests__/existing-install-actions.test.ts`
|
|
441
|
-
# (P1-E of the install-link review). Keep at least one keyword from
|
|
442
|
-
# the manifest's `keywords[action]` array per option so the lint
|
|
443
|
-
# doesn't break.
|
|
444
|
-
#
|
|
445
|
-
# Only prompt on an interactive TTY. When the script is piped without a
|
|
446
|
-
# TTY attached (e.g. one-liner with no tty allocated), default to
|
|
447
|
-
# "reinstall + re-run init" which is the safest non-destructive choice.
|
|
448
|
-
if [[ ! -t 0 ]] && [[ ! -t 1 ]]; then
|
|
449
|
-
info "Non-interactive shell detected — defaulting to reinstall."
|
|
450
|
-
echo "upgrade"
|
|
451
|
-
return 0
|
|
452
|
-
fi
|
|
453
|
-
|
|
454
|
-
# Note on naming: the option below is labelled "Reinstall + upgrade
|
|
455
|
-
# CLI" deliberately. `beeos init`'s own menu has an item called
|
|
456
|
-
# "Upgrade CLI & agents" — it does (now) call `npm i -g` for the
|
|
457
|
-
# three-piece suite and re-runs `beeos start openclaw`. The script
|
|
458
|
-
# action here is broader: it also re-bootstraps Node / pnpm if
|
|
459
|
-
# missing, re-applies env vars from this shell, and *exec*s the
|
|
460
|
-
# newly-installed binary. Different verb avoids the user thinking
|
|
461
|
-
# they're picking the same code path twice. (See `init.ts`'s own
|
|
462
|
-
# upgrade branch for the in-CLI behavior.)
|
|
463
|
-
local ver
|
|
464
|
-
ver=$(beeos_current_version || true)
|
|
465
|
-
ver="${ver:-unknown}"
|
|
466
|
-
warn "BeeOS CLI is already installed (v${ver})."
|
|
467
|
-
echo ""
|
|
468
|
-
echo " [1] Reinstall + upgrade CLI to the latest version, then run ${BOLD}beeos init${RESET}"
|
|
469
|
-
echo " [2] Re-run ${BOLD}beeos init${RESET} without reinstalling"
|
|
470
|
-
echo " [3] Skip (do nothing)"
|
|
471
|
-
echo ""
|
|
472
|
-
|
|
473
|
-
local choice
|
|
474
|
-
read -rp "Choose [1-3]: " choice </dev/tty || choice=""
|
|
475
|
-
case "$choice" in
|
|
476
|
-
""|1) echo "upgrade" ;;
|
|
477
|
-
2) echo "rerun" ;;
|
|
478
|
-
3) echo "skip" ;;
|
|
479
|
-
*) echo "upgrade" ;;
|
|
480
|
-
esac
|
|
481
|
-
}
|
|
482
|
-
|
|
483
454
|
# ── Main ─────────────────────────────────────────────────────
|
|
484
455
|
|
|
485
456
|
run_cli() {
|
|
@@ -519,20 +490,27 @@ run_cli() {
|
|
|
519
490
|
fi
|
|
520
491
|
|
|
521
492
|
info "Installing ${CLI_PACKAGE} globally..."
|
|
522
|
-
|
|
493
|
+
# 1.0.19: tee npm output into BEEOS_INSTALL_LOG. Without this, when
|
|
494
|
+
# `npm install -g` fails the user (and support engineers) only see
|
|
495
|
+
# whatever scrolled past in the terminal — important details like
|
|
496
|
+
# the npm error code, registry URL, or proxy hint may be gone by
|
|
497
|
+
# the time they go to copy-paste. `set -o pipefail` (file header)
|
|
498
|
+
# ensures the pipe's exit status is `npm`'s, not `tee`'s.
|
|
499
|
+
if ! npm install -g "$CLI_PACKAGE" 2>&1 | tee -a "$BEEOS_INSTALL_LOG"; then
|
|
523
500
|
# P0-A of the install-link review: separate "Node ready" from
|
|
524
501
|
# "CLI is actually on PATH" so the dashboard never reports a
|
|
525
502
|
# success that the user can't reproduce. `install.bootstrap.npm_fail`
|
|
526
503
|
# is the canonical fail-after-bootstrap marker.
|
|
527
504
|
send_telemetry "install.bootstrap.npm_fail" "npm_install_cli_failed" false
|
|
528
505
|
error "npm install -g ${CLI_PACKAGE} failed."
|
|
506
|
+
error " Full log: ${BEEOS_INSTALL_LOG}"
|
|
529
507
|
error ""
|
|
530
508
|
error "Common fixes:"
|
|
531
509
|
error " - EEXIST on /bin/beeos from another package:"
|
|
532
|
-
error " npm uninstall -g beeos # then re-run installer"
|
|
510
|
+
error " npm uninstall -g @beeos-ai/cli # then re-run installer"
|
|
533
511
|
error " - EACCES permission error:"
|
|
534
512
|
error " use a node version manager (nvm / fnm) or sudo"
|
|
535
|
-
exit
|
|
513
|
+
exit 3
|
|
536
514
|
fi
|
|
537
515
|
# NPM succeeded — CLI is now on PATH. The device-agent suite is
|
|
538
516
|
# deliberately NOT installed here; `beeos device attach` will
|
|
@@ -581,41 +559,12 @@ main() {
|
|
|
581
559
|
|
|
582
560
|
success "Node.js $(node -v) detected"
|
|
583
561
|
|
|
584
|
-
#
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
info "Skipping. Run \`beeos init\` or \`beeos device attach\` manually later."
|
|
591
|
-
exit 0
|
|
592
|
-
;;
|
|
593
|
-
upgrade)
|
|
594
|
-
info "Reinstalling ${CLI_PACKAGE}..."
|
|
595
|
-
if command -v npm &>/dev/null; then
|
|
596
|
-
if ! npm install -g "$CLI_PACKAGE"; then
|
|
597
|
-
send_telemetry "install.bootstrap.npm_fail" "npm_install_cli_failed_upgrade" false
|
|
598
|
-
error "npm install -g ${CLI_PACKAGE} failed."
|
|
599
|
-
error ""
|
|
600
|
-
error "Common fixes:"
|
|
601
|
-
error " - EEXIST on /bin/beeos from another package:"
|
|
602
|
-
error " npm uninstall -g beeos # then re-run installer"
|
|
603
|
-
error " - EACCES permission error:"
|
|
604
|
-
error " use a node version manager (nvm / fnm) or sudo"
|
|
605
|
-
exit 1
|
|
606
|
-
fi
|
|
607
|
-
# Device-agent suite is intentionally NOT upgraded here.
|
|
608
|
-
# `beeos device upgrade` is the canonical refresh path (it
|
|
609
|
-
# also restarts the running fleet); the install-script
|
|
610
|
-
# upgrade prompt only refreshes the CLI itself.
|
|
611
|
-
fi
|
|
612
|
-
;;
|
|
613
|
-
rerun)
|
|
614
|
-
info "Reusing existing install."
|
|
615
|
-
;;
|
|
616
|
-
esac
|
|
617
|
-
fi
|
|
618
|
-
|
|
562
|
+
# Bootstrap is finished. Hand off to `run_cli` which performs
|
|
563
|
+
# `npm install -g @beeos-ai/cli` (idempotent — npm short-circuits
|
|
564
|
+
# when the requested version is already on disk) and then `exec`s
|
|
565
|
+
# the freshly-installed binary. "What does the CLI do when it's
|
|
566
|
+
# already installed?" is now `beeos init`'s problem; we don't
|
|
567
|
+
# second-guess it from out here.
|
|
619
568
|
info "Running BeeOS CLI..."
|
|
620
569
|
echo ""
|
|
621
570
|
|