@hybridlabor-api/aos 4.4.2-beta.5 → 4.4.2-beta.7
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/CLAUDE.md +52 -0
- package/README.de.md +22 -16
- package/README.md +84 -18
- package/README.pt.md +22 -17
- package/docs/backups/hub-overview-20260915.html +200 -0
- package/docs/backups/hub-overview-rewrite-plan.md +98 -0
- package/docs/backups/readme-update-plan.md +393 -0
- package/installer.js +100 -11
- package/lib/startup-ui.js +3 -3
- package/package.json +4 -1
package/installer.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Node compatibility guard -- must run before any require() that could pull
|
|
4
|
+
// in a dependency using the `node:` built-in scheme (@clack/prompts ->
|
|
5
|
+
// @clack/core does `require('node:process')` internally), which only
|
|
6
|
+
// resolves on Node >=14.18/>=16. On an older Node this crashed deep inside
|
|
7
|
+
// that dependency with a bare "Cannot find module 'node:process'" -- no
|
|
8
|
+
// mention of Node version anywhere -- reported from a real Windows machine
|
|
9
|
+
// where the installer couldn't even start. Uses only process.version, a
|
|
10
|
+
// built-in global with no require() of its own, so this check itself runs
|
|
11
|
+
// on any Node version ever shipped.
|
|
12
|
+
const NODE_MAJOR = parseInt(process.version.slice(1).split('.')[0], 10);
|
|
13
|
+
if (Number.isFinite(NODE_MAJOR) && NODE_MAJOR < 20) {
|
|
14
|
+
console.error(`\nAOS requires Node.js 20 or newer -- this machine has ${process.version}.\nInstall a current Node.js from https://nodejs.org and re-run.\n`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
3
18
|
const fs = require('fs');
|
|
4
19
|
const path = require('path');
|
|
5
20
|
const os = require('os');
|
|
@@ -2237,7 +2252,17 @@ function verifyEcosystemInstallation() {
|
|
|
2237
2252
|
function resolveTargetPaths(platformValue, customPaths) {
|
|
2238
2253
|
let targetSkillDir = globalConfigDir;
|
|
2239
2254
|
let targetLegacyDir = globalLegacyDir;
|
|
2240
|
-
|
|
2255
|
+
// NOT the module-level `workspaceDir` (process.cwd()-based) -- that default
|
|
2256
|
+
// is only correct for the Cursor branch below and the explicit Local
|
|
2257
|
+
// Project Harness selection (platformValue '4' with customPaths), both of
|
|
2258
|
+
// which are genuinely project-scoped by design. For every other platform,
|
|
2259
|
+
// including this function's own top-level default used by the universal
|
|
2260
|
+
// tier ('1'), a global Quick Update inherited a directory relative to
|
|
2261
|
+
// whatever the current working directory happened to be -- silently
|
|
2262
|
+
// harmless when cwd sat under the user's own home dir, but a hard EPERM
|
|
2263
|
+
// crash the one time a Windows user ran npx from C:\Windows\System32
|
|
2264
|
+
// (PowerShell's default start directory, unwritable for a normal user).
|
|
2265
|
+
let targetWorkspaceDir = path.join(homeDir, '.agents', 'workspace_skills');
|
|
2241
2266
|
let targetMcpDir = path.join(geminiDir, 'config');
|
|
2242
2267
|
let mcpConfigPath = path.join(targetMcpDir, 'mcp_config.json');
|
|
2243
2268
|
// Secondary MCP stores that must receive the same servers as mcpConfigPath
|
|
@@ -3303,8 +3328,13 @@ function generateAndOpenLaunchpad() {
|
|
|
3303
3328
|
if (process.env.SSH_CLIENT || process.env.SSH_TTY) return;
|
|
3304
3329
|
|
|
3305
3330
|
// Local Developer Workflow Guard:
|
|
3306
|
-
// Only generate and open the launchpad if running in a local developer repo environment or explicitly requested
|
|
3307
|
-
|
|
3331
|
+
// Only generate and open the launchpad if running in a local developer repo environment or explicitly requested.
|
|
3332
|
+
// ~/bdb-dev was the pre-reorg workspace root; the State-0 reorg moved it to
|
|
3333
|
+
// ~/dev/bdb-dev, but this check was never updated -- it has been silently
|
|
3334
|
+
// false on every real dev machine since that reorg. Checking both keeps
|
|
3335
|
+
// this working regardless of which layout a given machine still has.
|
|
3336
|
+
const isDevWorkflow = fs.existsSync(path.join(homeDir, 'dev', 'bdb-dev')) ||
|
|
3337
|
+
fs.existsSync(path.join(homeDir, 'bdb-dev')) ||
|
|
3308
3338
|
process.env.BDB_DEV === '1' ||
|
|
3309
3339
|
process.argv.includes('--launchpad') ||
|
|
3310
3340
|
process.argv.includes('--dev');
|
|
@@ -3464,8 +3494,8 @@ function generateAndOpenLaunchpad() {
|
|
|
3464
3494
|
<div class="card-content">
|
|
3465
3495
|
<div class="card-icon">⚡</div>
|
|
3466
3496
|
<div class="card-info">
|
|
3467
|
-
<h2>Agent
|
|
3468
|
-
<p>Multi-Agent Cockpit &
|
|
3497
|
+
<h2>AO — Agent Orchestrator</h2>
|
|
3498
|
+
<p>Multi-Agent Cockpit & Git-Worktree Orchestration</p>
|
|
3469
3499
|
</div>
|
|
3470
3500
|
</div>
|
|
3471
3501
|
<div class="card-meta">
|
|
@@ -3473,6 +3503,19 @@ function generateAndOpenLaunchpad() {
|
|
|
3473
3503
|
<span class="status-dot" id="dot-ao" title="Checking..."></span>
|
|
3474
3504
|
</div>
|
|
3475
3505
|
</a>
|
|
3506
|
+
<a class="card" href="http://127.0.0.1:9080" target="_blank">
|
|
3507
|
+
<div class="card-content">
|
|
3508
|
+
<div class="card-icon">🌐</div>
|
|
3509
|
+
<div class="card-info">
|
|
3510
|
+
<h2>RemoteOS Gateway</h2>
|
|
3511
|
+
<p>Multi-Cloud Execution & 4-Eyes Approval Gateway</p>
|
|
3512
|
+
</div>
|
|
3513
|
+
</div>
|
|
3514
|
+
<div class="card-meta">
|
|
3515
|
+
<span class="port-pill">:9080</span>
|
|
3516
|
+
<span class="status-dot" id="dot-remote" title="Checking..."></span>
|
|
3517
|
+
</div>
|
|
3518
|
+
</a>
|
|
3476
3519
|
</div>
|
|
3477
3520
|
<div class="footer">
|
|
3478
3521
|
<span>Autostart Daemons • 127.0.0.1</span>
|
|
@@ -3486,14 +3529,14 @@ function generateAndOpenLaunchpad() {
|
|
|
3486
3529
|
.then(() => dot.classList.add('online'))
|
|
3487
3530
|
.catch(() => dot.classList.remove('online'));
|
|
3488
3531
|
}
|
|
3489
|
-
|
|
3490
|
-
checkHealth('http://127.0.0.1:7781', 'dot-synapse');
|
|
3491
|
-
checkHealth('http://127.0.0.1:3101', 'dot-ao');
|
|
3492
|
-
setInterval(() => {
|
|
3532
|
+
function checkAllHealth() {
|
|
3493
3533
|
checkHealth('http://127.0.0.1:8088', 'dot-memb');
|
|
3494
3534
|
checkHealth('http://127.0.0.1:7781', 'dot-synapse');
|
|
3495
3535
|
checkHealth('http://127.0.0.1:3101', 'dot-ao');
|
|
3496
|
-
|
|
3536
|
+
checkHealth('http://127.0.0.1:9080', 'dot-remote');
|
|
3537
|
+
}
|
|
3538
|
+
checkAllHealth();
|
|
3539
|
+
setInterval(checkAllHealth, 5000);
|
|
3497
3540
|
</script>
|
|
3498
3541
|
</body>
|
|
3499
3542
|
</html>`;
|
|
@@ -3520,6 +3563,47 @@ function generateAndOpenLaunchpad() {
|
|
|
3520
3563
|
child.on('error', warnOpenFailed);
|
|
3521
3564
|
child.unref();
|
|
3522
3565
|
} catch (e) { warnOpenFailed(e); }
|
|
3566
|
+
|
|
3567
|
+
// Opening it once per install/update isn't the same as being available at
|
|
3568
|
+
// every login -- memB/Synapse/AO all get a real autostart entry for their
|
|
3569
|
+
// own background services, but the dashboard itself (a static file, not
|
|
3570
|
+
// a process) never got the equivalent: something to open it automatically
|
|
3571
|
+
// on login too, not just right after an installer run.
|
|
3572
|
+
if (process.platform === 'darwin') {
|
|
3573
|
+
const plistPath = path.join(homeDir, 'Library', 'LaunchAgents', 'com.bdb.launchpad.plist');
|
|
3574
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
3575
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3576
|
+
<plist version="1.0">
|
|
3577
|
+
<dict>
|
|
3578
|
+
<key>Label</key>
|
|
3579
|
+
<string>com.bdb.launchpad</string>
|
|
3580
|
+
<key>ProgramArguments</key>
|
|
3581
|
+
<array>
|
|
3582
|
+
<string>open</string>
|
|
3583
|
+
<string>${filePath}</string>
|
|
3584
|
+
</array>
|
|
3585
|
+
<key>RunAtLoad</key>
|
|
3586
|
+
<true/>
|
|
3587
|
+
</dict>
|
|
3588
|
+
</plist>`;
|
|
3589
|
+
// Deliberately no KeepAlive: this launches a browser tab, not a
|
|
3590
|
+
// long-running service -- `open` exits the moment it's handed the
|
|
3591
|
+
// file to the browser, and KeepAlive would make launchd treat that
|
|
3592
|
+
// normal exit as a crash to restart, reopening the tab in a loop.
|
|
3593
|
+
try {
|
|
3594
|
+
fs.writeFileSync(plistPath, plistContent);
|
|
3595
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
|
|
3596
|
+
execSync(`launchctl load -w "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
|
|
3597
|
+
} catch (e) { logDebug(e, 'launchpad autostart plist'); }
|
|
3598
|
+
} else if (process.platform === 'win32') {
|
|
3599
|
+
const startupDir = path.join(process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming'), 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
|
|
3600
|
+
const vbsPath = path.join(startupDir, 'com.bdb.launchpad.vbs');
|
|
3601
|
+
const vbsContent = `Set WshShell = CreateObject("WScript.Shell")\r\nWshShell.Run """${filePath}""", 1, False\r\n`;
|
|
3602
|
+
try {
|
|
3603
|
+
fs.mkdirSync(startupDir, { recursive: true });
|
|
3604
|
+
fs.writeFileSync(vbsPath, vbsContent, 'utf-8');
|
|
3605
|
+
} catch (e) { logDebug(e, 'launchpad autostart vbs'); }
|
|
3606
|
+
}
|
|
3523
3607
|
}
|
|
3524
3608
|
|
|
3525
3609
|
async function universalHarnessSync(primaryMcpConfigPath) {
|
|
@@ -3704,12 +3788,17 @@ async function runQuickUpdate(installState) {
|
|
|
3704
3788
|
|
|
3705
3789
|
console.log('');
|
|
3706
3790
|
verifyEcosystemInstallation();
|
|
3791
|
+
// Fresh installs open this via universalHarnessSync(); Quick Update never
|
|
3792
|
+
// did, so a dev-workflow machine only ever saw it once, on day one --
|
|
3793
|
+
// every subsequent run is a Quick Update, which is what almost every
|
|
3794
|
+
// real run after the first actually is.
|
|
3795
|
+
generateAndOpenLaunchpad();
|
|
3707
3796
|
}
|
|
3708
3797
|
|
|
3709
3798
|
|
|
3710
3799
|
async function main() {
|
|
3711
3800
|
const skipIntro = isAutoYes || process.argv.includes('--no-intro') || process.argv.includes('--no-animation');
|
|
3712
|
-
await renderKineticIntro({ rotations: 1, fps: 12.5, skip: skipIntro });
|
|
3801
|
+
await renderKineticIntro({ rotations: 1, fps: 12.5, skip: skipIntro, pkgVersion: pkg.version });
|
|
3713
3802
|
console.log(buildWordmarkBanner());
|
|
3714
3803
|
|
|
3715
3804
|
const installState = detectInstallState();
|
package/lib/startup-ui.js
CHANGED
|
@@ -19,7 +19,7 @@ const BRAND = {
|
|
|
19
19
|
* Plays the 3D rotating BDB medallion kinetic intro in terminal.
|
|
20
20
|
* Automatically clears frame buffer upon completion for smooth handoff to Clack.
|
|
21
21
|
*/
|
|
22
|
-
async function renderKineticIntro({ rotations = 1, fps = 12.5, skip = false } = {}) {
|
|
22
|
+
async function renderKineticIntro({ rotations = 1, fps = 12.5, skip = false, pkgVersion = '4.0.0' } = {}) {
|
|
23
23
|
if (skip || !process.stdout.isTTY) return;
|
|
24
24
|
|
|
25
25
|
const frames = framesData.ansi;
|
|
@@ -27,7 +27,7 @@ async function renderKineticIntro({ rotations = 1, fps = 12.5, skip = false } =
|
|
|
27
27
|
const totalFrames = Math.round(rotations * frames.length);
|
|
28
28
|
|
|
29
29
|
// Clear terminal screen and hide cursor for a clean viewport
|
|
30
|
-
process.stdout.write(
|
|
30
|
+
process.stdout.write(`\x1b]0;BDB Agent OS · AOS Installer v${pkgVersion}\x07`);
|
|
31
31
|
process.stdout.write('\x1b[2J\x1b[H\x1b[?25l');
|
|
32
32
|
|
|
33
33
|
return new Promise((resolve) => {
|
|
@@ -41,7 +41,7 @@ async function renderKineticIntro({ rotations = 1, fps = 12.5, skip = false } =
|
|
|
41
41
|
'\x1b[H',
|
|
42
42
|
...lines.map(line => '\x1b[2K' + line),
|
|
43
43
|
'\x1b[2K',
|
|
44
|
-
`\x1b[2K ${BRAND.lila}${BRAND.bold}━━━ BDB AGENT OS ━━━${BRAND.reset} ${BRAND.white}${BRAND.bold}AOS Kernel
|
|
44
|
+
`\x1b[2K ${BRAND.lila}${BRAND.bold}━━━ BDB AGENT OS ━━━${BRAND.reset} ${BRAND.white}${BRAND.bold}AOS Kernel v${pkgVersion}${BRAND.reset} ${BRAND.dim}· Initializing runtime...${BRAND.reset}`
|
|
45
45
|
].join('\n');
|
|
46
46
|
|
|
47
47
|
process.stdout.write(buffer);
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/aos",
|
|
3
|
-
"version": "4.4.2-beta.
|
|
3
|
+
"version": "4.4.2-beta.7",
|
|
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
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
6
9
|
"bin": {
|
|
7
10
|
"aos": "installer.js",
|
|
8
11
|
"bdb-dev-optimized-agent-skills": "installer.js",
|