@hybridlabor-api/aos 4.6.5 → 4.6.6

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.
@@ -64,8 +64,10 @@ export function propose() {
64
64
  };
65
65
  }
66
66
 
67
+ import { pathToFileURL } from 'node:url';
68
+
67
69
  // ------------------------------------------------------------------- CLI
68
- if (import.meta.url === `file://${process.argv[1]}`) {
70
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
69
71
  const [cmd, key, ...rest] = process.argv.slice(2);
70
72
  const value = rest.join(' ');
71
73
 
package/installer.js CHANGED
@@ -2546,6 +2546,11 @@ function verifyEcosystemInstallation() {
2546
2546
  console.log(` • ${colors.bold}${mod.name.padEnd(35)}${colors.reset} ➔ ${colors.dim}⚪ Optional / Not downloaded${colors.reset}`);
2547
2547
  }
2548
2548
  }
2549
+
2550
+ console.log('');
2551
+ console.log(` ${colors.bold}━━━ BDB Agent OS Dashboard ━━━${colors.reset}`);
2552
+ console.log(` Interactive Control Center: npx aos-dashboard`);
2553
+ console.log(` ${colors.dim}(Live status & service control at http://127.0.0.1:7900)${colors.reset}`);
2549
2554
  }
2550
2555
 
2551
2556
  function resolveTargetPaths(platformValue, customPaths) {
@@ -3559,6 +3564,51 @@ function installGlobalHooks() {
3559
3564
  log.warn(`Could not install OpenCode plugin: ${e.message}`);
3560
3565
  }
3561
3566
  }
3567
+
3568
+ // 5. Global CLI launcher binaries (aos-config, aos-dashboard, aos-uninstall)
3569
+ installGlobalBinaries();
3570
+ }
3571
+
3572
+ function installGlobalBinaries() {
3573
+ const binSrc = path.join(srcDir, 'bin');
3574
+ const globalAgentsBin = path.join(homeDir, '.agents', 'bin');
3575
+ if (fs.existsSync(binSrc)) {
3576
+ copyDirRecursiveSync(binSrc, globalAgentsBin);
3577
+ log.step(`Installed CLI binaries to ${globalAgentsBin}`);
3578
+ }
3579
+
3580
+ const localBinDir = path.join(homeDir, '.local', 'bin');
3581
+ if (!fs.existsSync(localBinDir)) {
3582
+ try { fs.mkdirSync(localBinDir, { recursive: true }); } catch (e) { logDebug(e, 'mkdir localBin'); }
3583
+ }
3584
+
3585
+ const isWin = process.platform === 'win32';
3586
+ const cliBins = ['aos-config', 'aos-dashboard', 'aos-uninstall'];
3587
+
3588
+ for (const name of cliBins) {
3589
+ const targetMjs = path.join(globalAgentsBin, `${name}.mjs`);
3590
+ if (!fs.existsSync(targetMjs)) continue;
3591
+
3592
+ // Shell wrapper for Unix / Git Bash
3593
+ const shPath = path.join(localBinDir, name);
3594
+ const shContent = `#!/bin/sh\nexec node "${targetMjs}" "$@"\n`;
3595
+ try {
3596
+ fs.writeFileSync(shPath, shContent, { mode: 0o755 });
3597
+ try { fs.chmodSync(shPath, 0o755); } catch (e) { logDebug(e, `chmod ${shPath}`); }
3598
+ } catch (e) { logDebug(e, `write ${shPath}`); }
3599
+
3600
+ // Windows CMD and PowerShell launchers
3601
+ if (isWin) {
3602
+ const cmdPath = path.join(localBinDir, `${name}.cmd`);
3603
+ const cmdContent = `@echo off\r\nnode "${targetMjs}" %*\r\n`;
3604
+ try { fs.writeFileSync(cmdPath, cmdContent); } catch (e) { logDebug(e, `write ${cmdPath}`); }
3605
+
3606
+ const ps1Path = path.join(localBinDir, `${name}.ps1`);
3607
+ const ps1Content = `node "${targetMjs}" $args\r\n`;
3608
+ try { fs.writeFileSync(ps1Path, ps1Content); } catch (e) { logDebug(e, `write ${ps1Path}`); }
3609
+ }
3610
+ }
3611
+ log.step(`Wired CLI launcher binaries (aos-config, aos-dashboard, aos-uninstall) in ${localBinDir}`);
3562
3612
  }
3563
3613
 
3564
3614
  // Merge the BDB hooks -- the two gates plus the memB ambient-memory hook --
@@ -3954,26 +4004,59 @@ async function promptOptionalModules(installedModules) {
3954
4004
  return chosen;
3955
4005
  }
3956
4006
 
3957
- function generateAndOpenLaunchpad() {
4007
+ // Module ids whose daemons ship a web interface or background service worth
4008
+ // surfacing in the launchpad (each has a card in the generated HTML below).
4009
+ const LAUNCHPAD_WEB_MODULES = ['memb', 'synapse', 'openwiki', 'ao', 'remote'];
4010
+
4011
+ // Explicit opt-in flags that open the launchpad even outside a dev checkout.
4012
+ const LAUNCHPAD_OPEN_FLAGS = ['--launchpad', '--dashboard', '--open', '--dev'];
4013
+
4014
+ // True on a local BDB dev checkout (or BDB_DEV=1). This is intentionally
4015
+ // narrower than the old isDevWorkflow check: CLI flags live in
4016
+ // shouldOpenLaunchpad(), not here, so callers can tell "dev machine" apart
4017
+ // from "user asked for it". Overrides exist for tests.
4018
+ function isDevEnvironment(overrides = {}) {
4019
+ const home = overrides.homeDir || homeDir;
4020
+ const env = overrides.env || process.env;
4021
+ return fs.existsSync(path.join(home, 'dev', 'bdb-dev')) ||
4022
+ fs.existsSync(path.join(home, 'bdb-dev')) ||
4023
+ env.BDB_DEV === '1';
4024
+ }
4025
+
4026
+ // True when the launchpad should be generated and opened: a dev checkout, an
4027
+ // explicit flag, or installed daemon/WebUI modules. Overrides exist for tests.
4028
+ function shouldOpenLaunchpad(installedModules = [], overrides = {}) {
4029
+ const argv = overrides.argv || process.argv;
4030
+ if (isDevEnvironment(overrides)) return true;
4031
+ if (LAUNCHPAD_OPEN_FLAGS.some(f => argv.includes(f))) return true;
4032
+ const installed = Array.isArray(installedModules) ? installedModules : [];
4033
+ return installed.some(m => LAUNCHPAD_WEB_MODULES.includes(m));
4034
+ }
4035
+
4036
+ // Boot autostart (login item) is opt-in only: an explicit flag or a dev
4037
+ // checkout. Regular end-user installs must not get an autostart entry that
4038
+ // opens a browser on every login. Overrides exist for tests.
4039
+ function shouldAutostartLaunchpad(overrides = {}) {
4040
+ const argv = overrides.argv || process.argv;
4041
+ if (argv.includes('--autostart-launchpad')) return true;
4042
+ return isDevEnvironment(overrides);
4043
+ }
4044
+
4045
+ function generateAndOpenLaunchpad(installedModules = []) {
3958
4046
  if (DRY_RUN) {
3959
4047
  log.step('[dry-run] would generate & open BDB Launchpad HTML');
3960
- return;
4048
+ return false;
3961
4049
  }
3962
- if (process.env.SSH_CLIENT || process.env.SSH_TTY) return;
4050
+ if (process.env.SSH_CLIENT || process.env.SSH_TTY) return false;
3963
4051
 
3964
- // Local Developer Workflow Guard:
3965
- // Only generate and open the launchpad if running in a local developer repo environment or explicitly requested.
4052
+ // Decoupled from the dev-checkout layout: on a regular end-user machine
4053
+ // (no ~/dev/bdb-dev, no ~/bdb-dev) the launchpad still opens when daemon
4054
+ // modules are installed or an explicit flag was passed.
3966
4055
  // ~/bdb-dev was the pre-reorg workspace root; the State-0 reorg moved it to
3967
- // ~/dev/bdb-dev, but this check was never updated -- it has been silently
3968
- // false on every real dev machine since that reorg. Checking both keeps
3969
- // this working regardless of which layout a given machine still has.
3970
- const isDevWorkflow = fs.existsSync(path.join(homeDir, 'dev', 'bdb-dev')) ||
3971
- fs.existsSync(path.join(homeDir, 'bdb-dev')) ||
3972
- process.env.BDB_DEV === '1' ||
3973
- process.argv.includes('--launchpad') ||
3974
- process.argv.includes('--dev');
3975
- if (!isDevWorkflow) {
3976
- return;
4056
+ // ~/dev/bdb-dev. Both are checked so this works regardless of which layout
4057
+ // a given machine still has.
4058
+ if (!shouldOpenLaunchpad(installedModules)) {
4059
+ return false;
3977
4060
  }
3978
4061
 
3979
4062
  const html = `<!DOCTYPE html>
@@ -4309,6 +4392,12 @@ function generateAndOpenLaunchpad() {
4309
4392
  // own background services, but the dashboard itself (a static file, not
4310
4393
  // a process) never got the equivalent: something to open it automatically
4311
4394
  // on login too, not just right after an installer run.
4395
+ // Opt-in only: without --autostart-launchpad (or a dev checkout) a regular
4396
+ // end-user install must not drop a login item that opens a browser on
4397
+ // every boot.
4398
+ if (!shouldAutostartLaunchpad()) {
4399
+ return true;
4400
+ }
4312
4401
  if (process.platform === 'darwin') {
4313
4402
  const plistPath = path.join(homeDir, 'Library', 'LaunchAgents', 'com.bdb.launchpad.plist');
4314
4403
  const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
@@ -4344,9 +4433,10 @@ function generateAndOpenLaunchpad() {
4344
4433
  fs.writeFileSync(vbsPath, vbsContent, 'utf-8');
4345
4434
  } catch (e) { logDebug(e, 'launchpad autostart vbs'); }
4346
4435
  }
4436
+ return true;
4347
4437
  }
4348
4438
 
4349
- async function universalHarnessSync(primaryMcpConfigPath) {
4439
+ async function universalHarnessSync(primaryMcpConfigPath, installedModules = []) {
4350
4440
  log.info('Universal Agent Harness Sync...');
4351
4441
  const detections = detectPlatforms();
4352
4442
  let masterMcpData = {};
@@ -4508,7 +4598,7 @@ async function universalHarnessSync(primaryMcpConfigPath) {
4508
4598
  }
4509
4599
  }
4510
4600
  log.success('Universal Sync Complete!');
4511
- generateAndOpenLaunchpad();
4601
+ generateAndOpenLaunchpad(installedModules);
4512
4602
  }
4513
4603
 
4514
4604
  async function runQuickUpdate(installState) {
@@ -4614,7 +4704,7 @@ async function runQuickUpdate(installState) {
4614
4704
  // did, so a dev-workflow machine only ever saw it once, on day one --
4615
4705
  // every subsequent run is a Quick Update, which is what almost every
4616
4706
  // real run after the first actually is.
4617
- generateAndOpenLaunchpad();
4707
+ generateAndOpenLaunchpad(modulesToUpdate);
4618
4708
  }
4619
4709
 
4620
4710
 
@@ -5013,7 +5103,7 @@ async function main() {
5013
5103
  saveManifest({ tier, isUniversal: wantsUniversal, installedModules: installedModulesForPrompt });
5014
5104
 
5015
5105
  if (wantsUniversal) {
5016
- await universalHarnessSync(primaryTarget.mcpConfigPath);
5106
+ await universalHarnessSync(primaryTarget.mcpConfigPath, installedModulesForPrompt);
5017
5107
  }
5018
5108
 
5019
5109
  // Flush file-level install manifest after all writes are done.
@@ -5061,4 +5151,11 @@ module.exports = {
5061
5151
  loadPipelineConfig,
5062
5152
  resolveAgentConfig,
5063
5153
  CANONICAL_TIERS,
5154
+ // Launchpad lifecycle (exported for regression tests)
5155
+ generateAndOpenLaunchpad,
5156
+ shouldOpenLaunchpad,
5157
+ shouldAutostartLaunchpad,
5158
+ isDevEnvironment,
5159
+ LAUNCHPAD_WEB_MODULES,
5160
+ LAUNCHPAD_OPEN_FLAGS,
5064
5161
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hybridlabor-api/aos",
3
- "version": "4.6.5",
3
+ "version": "4.6.6",
4
4
  "description": "AOS — A Curated AI AGENT OS. Optimized agent skills and add-ons like memB, OpenWiki, Heimdall Token Saver, and Godmode architectures.",
5
5
  "main": "installer.js",
6
6
  "engines": {
@@ -55,6 +55,17 @@ function checkGit() {
55
55
 
56
56
  // ---------------------------------------------------------------- aos config
57
57
  function checkAosConfig() {
58
+ const machineConfig = (() => {
59
+ try { return JSON.parse(readFileSync(path.join(HOME, '.agents', 'aos-config.json'), 'utf8')); }
60
+ catch { return null; }
61
+ })();
62
+ const machineOk = !!(machineConfig?.workspaceRoot && machineConfig?.domains?.length && machineConfig?.userId);
63
+ add('aos', 'machine vocabulary', machineOk,
64
+ machineOk
65
+ ? `workspaceRoot "${machineConfig.workspaceRoot}" · ${machineConfig.domains.length} domains · userId "${machineConfig.userId}"`
66
+ : 'missing or incomplete in ~/.agents/aos-config.json — /aos-project-init requires machine vocabulary',
67
+ 'Run /aos-setup (or `aos-config propose` / `aos-config set`) to configure machine vocabulary.');
68
+
58
69
  add('aos', '.aos/project.json', !!aosConfig,
59
70
  aosConfig
60
71
  ? `slug "${aosConfig.slug}"${aosConfig.domain ? ` · domain ${aosConfig.domain}` : ''}${aosConfig.watch ? ' · überwacht' : ''}`