@beeos-ai/cli 1.0.9 → 1.0.11

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 CHANGED
@@ -119,11 +119,26 @@ async function loadOrCreateConfig() {
119
119
  const raw = await p.readFile(path10);
120
120
  const parsed = TOML.parse(raw);
121
121
  const cfg2 = mergeWithDefaults(parsed);
122
- return cfg2;
122
+ return applyEnvOverrides(cfg2);
123
123
  }
124
124
  const cfg = defaultConfig();
125
125
  await saveConfig(cfg);
126
- return cfg;
126
+ return applyEnvOverrides(cfg);
127
+ }
128
+ function applyEnvOverrides(cfg) {
129
+ const env = globalThis.process?.env ?? {};
130
+ const apiUrl = env.BEEOS_API_URL?.trim();
131
+ const agwUrl = env.BEEOS_AGENT_GATEWAY_URL?.trim();
132
+ const dashUrl = env.BEEOS_DASHBOARD_URL?.trim();
133
+ return {
134
+ ...cfg,
135
+ platform: {
136
+ ...cfg.platform,
137
+ ...apiUrl ? { api_url: apiUrl } : {},
138
+ ...agwUrl ? { agent_gateway_url: agwUrl } : {},
139
+ ...dashUrl ? { dashboard_base_url: dashUrl } : {}
140
+ }
141
+ };
127
142
  }
128
143
  async function saveConfig(cfg) {
129
144
  const p = getPlatformAdapter();
@@ -4320,6 +4335,8 @@ var init_state = __esm({
4320
4335
  });
4321
4336
 
4322
4337
  // src/commands/device/attach.ts
4338
+ import { spawn as spawn2 } from "child_process";
4339
+ import readline from "readline";
4323
4340
  async function attach(options) {
4324
4341
  const cfg = await loadOrCreateConfig();
4325
4342
  const reporter = new CliReporter();
@@ -4403,7 +4420,7 @@ async function attach(options) {
4403
4420
  throw e;
4404
4421
  }
4405
4422
  });
4406
- await maybeNotifyFleetWithHint();
4423
+ await maybeNotifyFleetWithHint(cfg);
4407
4424
  }
4408
4425
  async function attachAll(cfg, reporter, withVideo, options) {
4409
4426
  const devices = await deviceRuntime.listAdbDevices();
@@ -4478,7 +4495,7 @@ async function attachAll(cfg, reporter, withVideo, options) {
4478
4495
  await saveDeviceState(state);
4479
4496
  console.log(`Attached ${committed.length} device(s); supervision via device-agent fleet.`);
4480
4497
  });
4481
- await maybeNotifyFleetWithHint();
4498
+ await maybeNotifyFleetWithHint(cfg);
4482
4499
  }
4483
4500
  function commitAttachResults(state, commits) {
4484
4501
  const committed = [];
@@ -4572,9 +4589,70 @@ async function installService(mgr, spec) {
4572
4589
  maybePrintFallbackBanner(mgr.kind);
4573
4590
  await mgr.install(spec);
4574
4591
  }
4575
- async function maybeNotifyFleetWithHint() {
4592
+ async function maybeNotifyFleetWithHint(cfg) {
4576
4593
  const outcome = await notifyFleetReloadBestEffort();
4577
- if (outcome === "not_running") printFleetNotRunningHint();
4594
+ if (outcome !== "not_running") return;
4595
+ if (!shouldOfferFleetEnable()) {
4596
+ printFleetNotRunningHint();
4597
+ return;
4598
+ }
4599
+ console.log("");
4600
+ console.log("device-agent fleet is not running yet. Until you start");
4601
+ console.log("it, the device is recorded in ~/.beeos/devices.json but");
4602
+ console.log("no process is supervising the per-device agent.");
4603
+ console.log("");
4604
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
4605
+ const answer = await new Promise((resolve) => {
4606
+ rl.question("Enable fleet now (registers a launchd service)? [Y/n]: ", (a) => {
4607
+ rl.close();
4608
+ resolve(a);
4609
+ });
4610
+ });
4611
+ const yes = answer.trim() === "" || /^y(es)?$/i.test(answer.trim());
4612
+ if (!yes) {
4613
+ printFleetNotRunningHint();
4614
+ return;
4615
+ }
4616
+ const ok = await runDeviceAgentFleetEnable(cfg);
4617
+ if (!ok) {
4618
+ console.error("");
4619
+ console.error("fleet enable did not complete cleanly. Re-run manually:");
4620
+ console.error(" device-agent fleet enable --agent-gateway-url <URL>");
4621
+ console.error("");
4622
+ printFleetNotRunningHint();
4623
+ return;
4624
+ }
4625
+ console.log("");
4626
+ console.log("fleet enabled \u2014 supervised processes should come up within a few seconds.");
4627
+ console.log("Check status with: device-agent fleet devices");
4628
+ }
4629
+ function shouldOfferFleetEnable(inputs = {
4630
+ platform: process.platform,
4631
+ stdinIsTTY: process.stdin.isTTY,
4632
+ stdoutIsTTY: process.stdout.isTTY,
4633
+ env: process.env
4634
+ }) {
4635
+ if (inputs.platform !== "darwin") return false;
4636
+ if (inputs.env.BEEOS_NO_FLEET_AUTOSTART === "1") return false;
4637
+ if (!inputs.stdinIsTTY) return false;
4638
+ if (!inputs.stdoutIsTTY) return false;
4639
+ return true;
4640
+ }
4641
+ async function runDeviceAgentFleetEnable(cfg) {
4642
+ const agentGatewayUrl = resolveAgentGatewayUrl(cfg);
4643
+ return new Promise((resolve) => {
4644
+ try {
4645
+ const child = spawn2(
4646
+ "device-agent",
4647
+ ["fleet", "enable", "--agent-gateway-url", agentGatewayUrl],
4648
+ { stdio: "inherit" }
4649
+ );
4650
+ child.once("close", (code) => resolve(code === 0));
4651
+ child.once("error", () => resolve(false));
4652
+ } catch {
4653
+ resolve(false);
4654
+ }
4655
+ });
4578
4656
  }
4579
4657
  async function registerVideoBridge(_mgr, reporter, params) {
4580
4658
  if (!params.withVideo) return { mode: "none" };
@@ -5373,7 +5451,7 @@ init_device2();
5373
5451
 
5374
5452
  // src/commands/init.ts
5375
5453
  init_dist();
5376
- import readline from "readline";
5454
+ import readline2 from "readline";
5377
5455
 
5378
5456
  // src/commands/doctor.ts
5379
5457
  init_dist();
@@ -5818,7 +5896,7 @@ function printNextSteps() {
5818
5896
  console.log("");
5819
5897
  }
5820
5898
  function prompt(question) {
5821
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5899
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
5822
5900
  return new Promise((resolve) => {
5823
5901
  rl.question(question, (answer) => {
5824
5902
  rl.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beeos-ai/cli",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "description": "BeeOS CLI — run AI agents from your desktop",
6
6
  "bin": {
@@ -9,6 +9,31 @@
9
9
  `-Device` is passed. Heavier deps (Python, uv, adb, scrcpy/vnc bridges)
10
10
  are installed lazily by the CLI itself.
11
11
 
12
+ Staging / dev-loop env vars (CLI >= 1.0.10). All four are inherited by
13
+ the spawned `beeos init` / `beeos device attach` child via the normal
14
+ process env passthrough — no extra Set-Item / -PassThru is needed. CLI
15
+ >= 1.0.10 reads them via the loadOrCreateConfig env-overrides layer;
16
+ older CLIs only honor BEEOS_API_URL (telemetry) +
17
+ BEEOS_AGENT_GATEWAY_URL (runtime).
18
+
19
+ $env:BEEOS_API_URL Public API base; both this script
20
+ (telemetry) and the CLI runtime use
21
+ this.
22
+ $env:BEEOS_AGENT_GATEWAY_URL Agent Gateway base (Ed25519-signed
23
+ bootstrap requests).
24
+ $env:BEEOS_DASHBOARD_URL Dashboard base (OAuth + bind redirect).
25
+ $env:BEEOS_DEVICE_AGENT_VERSION Pin @beeos-ai/device-agent semver.
26
+ $env:BEEOS_MCP_SERVER_VERSION Pin @beeos-ai/device-mcp-server semver.
27
+ $env:BEEOS_USE_NPX = "1" Power-user escape hatch: use `npx`
28
+ for a throwaway install. `beeos`
29
+ will NOT persist on PATH after
30
+ the script exits. Default
31
+ behaviour (since CLI 1.0.11) is
32
+ always `npm install -g` so the
33
+ CLI plus the device-agent suite
34
+ are both globally available for
35
+ follow-up commands.
36
+
12
37
  .EXAMPLE
13
38
  # One-liner (PowerShell 5+):
14
39
  irm https://beeos.ai/install.ps1 | iex
@@ -20,6 +45,15 @@
20
45
  .EXAMPLE
21
46
  # Jump straight into device attach instead of init:
22
47
  .\install.ps1 -Device
48
+
49
+ .EXAMPLE
50
+ # Bare-metal one-shot staging install (CLI >= 1.0.11):
51
+ $env:BEEOS_API_URL = "https://public-api-staging.beeos.ai"
52
+ $env:BEEOS_AGENT_GATEWAY_URL = "https://agent-gw-staging.beeos.ai"
53
+ $env:BEEOS_DASHBOARD_URL = "https://beeos-staging-web.vercel.app"
54
+ $env:BEEOS_DEVICE_AGENT_VERSION = "0.4.2"
55
+ $env:BEEOS_MCP_SERVER_VERSION = "0.2.3"
56
+ irm https://beeos.ai/install.ps1 | iex
23
57
  #>
24
58
  param(
25
59
  [string]$Version = "latest",
@@ -308,32 +342,41 @@ function Invoke-BeeosCli {
308
342
  [string[]]$ExtraArgs
309
343
  )
310
344
 
311
- $npxPath = Get-Command npx -ErrorAction SilentlyContinue
312
345
  $args = @($Subcommand)
313
346
  if ($ExtraArgs) { $args += $ExtraArgs }
314
347
 
315
- if ($npxPath) {
316
- # Temporary / npx path: deliberately do NOT install the device-agent
317
- # suite globally. The user opted into the throwaway-install flow, so
318
- # we honor that if they later run `beeos device attach`,
319
- # ensureDeviceAgent will guide them through a global install at that
320
- # point.
348
+ # ALWAYS install globally. Pre-1.0.11 we branched into `npx --yes`
349
+ # when available, which gave irm|iex users a throwaway install but
350
+ # silently broke their next step (`beeos device attach`) because
351
+ # `beeos` was not on PATH after the script exited. Power users who
352
+ # explicitly want the old throwaway behaviour can set
353
+ # `$env:BEEOS_USE_NPX = "1"`.
354
+ $npxPath = Get-Command npx -ErrorAction SilentlyContinue
355
+ if ($env:BEEOS_USE_NPX -eq "1" -and $npxPath) {
356
+ Write-BeeWarn "BEEOS_USE_NPX=1 — using throwaway npx install (beeos won't persist on PATH)."
321
357
  & npx --yes $CliPackage @args
322
- } else {
323
- Write-BeeWarn "npx not found, installing globally..."
324
- & npm install -g $CliPackage
325
- if ($LASTEXITCODE -ne 0) {
326
- Write-BeeError "npm install -g $CliPackage failed."
327
- Write-BeeError ""
328
- Write-BeeError "Common fixes:"
329
- Write-BeeError " - EEXIST on beeos from another package:"
330
- Write-BeeError " npm uninstall -g beeos # then re-run installer"
331
- Write-BeeError " - EACCES / permission error: run PowerShell as Administrator"
332
- exit 1
333
- }
334
- Install-DeviceAgentSuite
335
- & beeos @args
358
+ return
359
+ }
360
+
361
+ $npmPath = Get-Command npm -ErrorAction SilentlyContinue
362
+ if (-not $npmPath) {
363
+ Write-BeeError "npm not found — install Node.js first (this script tries that for you)."
364
+ exit 1
365
+ }
366
+
367
+ Write-BeeInfo "Installing $CliPackage globally..."
368
+ & npm install -g $CliPackage
369
+ if ($LASTEXITCODE -ne 0) {
370
+ Write-BeeError "npm install -g $CliPackage failed."
371
+ Write-BeeError ""
372
+ Write-BeeError "Common fixes:"
373
+ Write-BeeError " - EEXIST on beeos from another package:"
374
+ Write-BeeError " npm uninstall -g beeos # then re-run installer"
375
+ Write-BeeError " - EACCES / permission error: run PowerShell as Administrator"
376
+ exit 1
336
377
  }
378
+ Install-DeviceAgentSuite
379
+ & beeos @args
337
380
  }
338
381
 
339
382
  # ── Main ─────────────────────────────────────────────────────
@@ -15,6 +15,38 @@
15
15
  # upgrade / rebind / skip before re-running the bind flow.
16
16
  # 4. Dispatch into `beeos init` (default) or `beeos device attach` when
17
17
  # `--device` is passed.
18
+ #
19
+ # ── Staging / dev-loop env vars (CLI ≥ 1.0.10) ──────────────────────
20
+ # All four are inherited by the spawned `beeos init` / `beeos device
21
+ # attach` child via the normal `exec` env passthrough — there is no
22
+ # extra `export` needed. CLI ≥ 1.0.10 reads them via the `loadOrCreate
23
+ # Config` env-overrides layer; older CLIs only honor BEEOS_API_URL
24
+ # (telemetry) + BEEOS_AGENT_GATEWAY_URL (runtime).
25
+ #
26
+ # BEEOS_API_URL Public API base; both the script (telemetry)
27
+ # and the CLI runtime use this.
28
+ # BEEOS_AGENT_GATEWAY_URL Agent Gateway base (Ed25519-signed
29
+ # bootstrap requests).
30
+ # BEEOS_DASHBOARD_URL Dashboard base (OAuth + bind redirect).
31
+ # BEEOS_DEVICE_AGENT_VERSION Pin @beeos-ai/device-agent semver.
32
+ # BEEOS_MCP_SERVER_VERSION Pin @beeos-ai/device-mcp-server semver.
33
+ # BEEOS_USE_NPX=1 (Power-user escape hatch) Use `npx` for a
34
+ # throwaway install. `beeos` will NOT
35
+ # persist on PATH after the script exits.
36
+ # Default behaviour (since CLI 1.0.11) is
37
+ # always `npm install -g` so the CLI plus
38
+ # the device-agent suite are both globally
39
+ # available for follow-up commands.
40
+ #
41
+ # Example: bare-metal one-shot staging install, including device-agent
42
+ # version pin and OAuth landing on the staging dashboard:
43
+ #
44
+ # BEEOS_API_URL=https://public-api-staging.beeos.ai \
45
+ # BEEOS_AGENT_GATEWAY_URL=https://agent-gw-staging.beeos.ai \
46
+ # BEEOS_DASHBOARD_URL=https://beeos-staging-web.vercel.app \
47
+ # BEEOS_DEVICE_AGENT_VERSION=0.4.2 \
48
+ # BEEOS_MCP_SERVER_VERSION=0.2.3 \
49
+ # curl -fsSL https://beeos.ai/install | bash -s -- --version 1.0.11
18
50
 
19
51
  set -euo pipefail
20
52
 
@@ -470,28 +502,44 @@ run_cli() {
470
502
  stdin_src="/dev/tty"
471
503
  fi
472
504
 
473
- if command -v npx &>/dev/null; then
474
- # Temporary / npx path: deliberately do NOT install the device-agent
475
- # suite globally. The user opted into the throwaway-install flow, so
476
- # we honor that if they later run `beeos device attach`,
477
- # ensureDeviceAgent will guide them through a global install at that
478
- # point.
505
+ # ALWAYS install globally. We previously branched to `npx --yes` when
506
+ # available so curl|bash users got a throwaway install, but that
507
+ # silently broke the post-install UX:
508
+ # - `beeos` was not on PATH after the script exited, so the user's
509
+ # next step (`beeos device attach`) failed with `command not found`
510
+ # and the obvious recovery (re-run the one-liner) hit the
511
+ # "existing install" prompt because some state in ~/.beeos
512
+ # persisted, leaving the user stuck.
513
+ # - The device-agent suite was deliberately skipped on the npx
514
+ # branch, so even if the user re-ran via `npm i -g`, the very
515
+ # next `beeos device attach` had to bootstrap device-agent
516
+ # itself.
517
+ # Power users who explicitly want the old throwaway behaviour can set
518
+ # `BEEOS_USE_NPX=1`. Default is global install.
519
+ if [[ "${BEEOS_USE_NPX:-}" == "1" ]] && command -v npx &>/dev/null; then
520
+ warn "BEEOS_USE_NPX=1 — using throwaway npx install (beeos won't persist on PATH)."
479
521
  exec npx --yes "$CLI_PACKAGE" "$subcmd" "$@" <"$stdin_src"
480
- else
481
- warn "npx not found, installing globally..."
482
- if ! npm install -g "$CLI_PACKAGE"; then
483
- error "npm install -g ${CLI_PACKAGE} failed."
484
- error ""
485
- error "Common fixes:"
486
- error " - EEXIST on /bin/beeos from another package:"
487
- error " npm uninstall -g beeos # then re-run installer"
488
- error " - EACCES permission error:"
489
- error " use a node version manager (nvm / fnm) or sudo"
490
- exit 1
491
- fi
492
- install_device_agent_suite
493
- exec beeos "$subcmd" "$@" <"$stdin_src"
494
522
  fi
523
+
524
+ if ! command -v npm &>/dev/null; then
525
+ error "npm not found — install Node.js first (this script tries that for you;"
526
+ error "see ${BEEOS_INSTALL_LOG} for why auto-install bailed out)."
527
+ exit 1
528
+ fi
529
+
530
+ info "Installing ${CLI_PACKAGE} globally..."
531
+ if ! npm install -g "$CLI_PACKAGE"; then
532
+ error "npm install -g ${CLI_PACKAGE} failed."
533
+ error ""
534
+ error "Common fixes:"
535
+ error " - EEXIST on /bin/beeos from another package:"
536
+ error " npm uninstall -g beeos # then re-run installer"
537
+ error " - EACCES permission error:"
538
+ error " use a node version manager (nvm / fnm) or sudo"
539
+ exit 1
540
+ fi
541
+ install_device_agent_suite
542
+ exec beeos "$subcmd" "$@" <"$stdin_src"
495
543
  }
496
544
 
497
545
  main() {