@hybridlabor-api/aos 4.4.2-beta.1 → 4.4.2-beta.3
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/bin/aos-uninstall.mjs +25 -3
- package/installer.js +30 -4
- package/lib/startup-ui.js +7 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -616,6 +616,58 @@ must not do.
|
|
|
616
616
|
|
|
617
617
|
## Headless timeouts
|
|
618
618
|
|
|
619
|
+
A trivial headless `agy` prompt was measured at **605s** in 2026-09.
|
|
620
|
+
`agy-delegate` defaults to `--print-timeout 5m`, so it aborts at 300s and
|
|
621
|
+
reports an empty body while the answer is still arriving. Pass `--timeout 15m`
|
|
622
|
+
for anything non-trivial. A short timeout does not read as "slow", it reads as
|
|
623
|
+
"broken".
|
|
624
|
+
|
|
625
|
+
# AOS — Antigravity / Gemini
|
|
626
|
+
|
|
627
|
+
**Read [AGENTS.md](AGENTS.md) first.** It holds every rule that applies to all
|
|
628
|
+
harnesses: the non-negotiables, the release gate, Conventional Commits, the
|
|
629
|
+
skill contract and category routing, the pipeline variants, and the delegation
|
|
630
|
+
policy. Nothing from it is repeated here — a rule that lives in two files is a
|
|
631
|
+
rule that will eventually disagree with itself.
|
|
632
|
+
|
|
633
|
+
This file covers only what is specific to running AOS under Antigravity.
|
|
634
|
+
|
|
635
|
+
## Nothing enforces the gate here — you are the enforcement
|
|
636
|
+
|
|
637
|
+
`.claude/hooks/go-gate.mjs` is a Claude Code hook and does not run on this
|
|
638
|
+
harness. Not one of the four release commands is mechanically blocked for you,
|
|
639
|
+
and neither is anything else.
|
|
640
|
+
|
|
641
|
+
So the full rule in AGENTS.md applies here in its entirety, not just its
|
|
642
|
+
hook-enforced subset: when the user asks for a plan, review, audit or
|
|
643
|
+
multi-step action, you are read-only until they answer with the literal **GO**
|
|
644
|
+
— including file writes and `git commit`. On Claude Code a hook would catch the
|
|
645
|
+
four worst cases if discipline failed. Here there is no backstop, which makes
|
|
646
|
+
this the harness where the rule matters most, not least.
|
|
647
|
+
|
|
648
|
+
## Model routing
|
|
649
|
+
|
|
650
|
+
The tier names in `agy-delegate` map to models that go stale — the built-in
|
|
651
|
+
`flash` still points at Gemini 3.7 while 3.8 ships. Re-check against
|
|
652
|
+
`agy models` after every upgrade; the id carries both the version and the
|
|
653
|
+
effort suffix.
|
|
654
|
+
|
|
655
|
+
| Work | Model |
|
|
656
|
+
|---|---|
|
|
657
|
+
| Media, fast or mechanical coding, boilerplate | `Gemini 3.8 Flash (Medium)` |
|
|
658
|
+
| Trivial one-liners | `Gemini 3.8 Flash (Low)` |
|
|
659
|
+
| Review, architecture, hard reasoning | `Claude Sonnet 4.6 (Thinking)` |
|
|
660
|
+
|
|
661
|
+
Set these once via `CLAUDE_PLUGIN_OPTION_TIER_{FLASH,FLASH_LO,PRO}` in
|
|
662
|
+
`~/.zshenv` — **not** `~/.zshrc`, which non-interactive tool shells never
|
|
663
|
+
source.
|
|
664
|
+
|
|
665
|
+
Adversarial review is the case that most repays the stronger model: a Flash
|
|
666
|
+
tier tends to agree with what it is shown, which is the one thing a reviewer
|
|
667
|
+
must not do.
|
|
668
|
+
|
|
669
|
+
## Headless timeouts
|
|
670
|
+
|
|
619
671
|
A trivial headless `agy` prompt was measured at **605s** in 2026-09.
|
|
620
672
|
`agy-delegate` defaults to `--print-timeout 5m`, so it aborts at 300s and
|
|
621
673
|
reports an empty body while the answer is still arriving. Pass `--timeout 15m`
|
package/bin/aos-uninstall.mjs
CHANGED
|
@@ -50,8 +50,21 @@ const MODULE_DIRS = ['memB', 'bdb-synapse', 'bdb-os-remote', 'bdb-dev-creator-ex
|
|
|
50
50
|
'bdb-dev-tool-installer',
|
|
51
51
|
'bdb-agent-orchestrator', // AO
|
|
52
52
|
'bdb-os-agent-workspace', // AO's archived predecessor, if still lying around
|
|
53
|
+
'bdb-dev-optimized-agent-skills', // AOS's own core payload cache, when a "from source" or non-npx run left one behind
|
|
53
54
|
].map((m) => h('.agents', m));
|
|
54
55
|
|
|
56
|
+
// installer.js's detectInstallState() treats any of these as proof AOS is
|
|
57
|
+
// still installed, independently of the manifest -- a leftover copy after
|
|
58
|
+
// this uninstall runs was reported as "Current & Up-to-date" on the very
|
|
59
|
+
// next launch, with the manifest already gone. Keep this list in exact sync
|
|
60
|
+
// with the `legacyMarkers` array in installer.js's detectInstallState().
|
|
61
|
+
const LEGACY_MARKERS = [
|
|
62
|
+
h('.agents', 'AGENTS.md'),
|
|
63
|
+
h('.gemini', 'config', 'skills', 'startcycle', 'SKILL.md'),
|
|
64
|
+
h('.agents', 'skills', 'startcycle', 'SKILL.md'),
|
|
65
|
+
h('.claude', 'skills', 'startcycle', 'SKILL.md'),
|
|
66
|
+
];
|
|
67
|
+
|
|
55
68
|
const sha256 = (file) => {
|
|
56
69
|
try { return createHash('sha256').update(readFileSync(file)).digest('hex'); }
|
|
57
70
|
catch { return null; }
|
|
@@ -77,13 +90,14 @@ function plan() {
|
|
|
77
90
|
.filter((a) => existsSync(a.plist));
|
|
78
91
|
|
|
79
92
|
const modules = MODULE_DIRS.filter(existsSync);
|
|
93
|
+
const legacy = LEGACY_MARKERS.filter(existsSync);
|
|
80
94
|
const data = PURGE ? DATA_PATHS.filter((d) => existsSync(d.path)) : [];
|
|
81
95
|
|
|
82
|
-
return { manifest, ours, edited, gone, agents, modules, data };
|
|
96
|
+
return { manifest, ours, edited, gone, agents, modules, legacy, data };
|
|
83
97
|
}
|
|
84
98
|
|
|
85
99
|
function describe(p) {
|
|
86
|
-
const { manifest, ours, edited, gone, agents, modules, data } = p;
|
|
100
|
+
const { manifest, ours, edited, gone, agents, modules, legacy, data } = p;
|
|
87
101
|
|
|
88
102
|
if (!manifest) {
|
|
89
103
|
console.log('Kein Installations-Manifest unter ' + tilde(MANIFEST) + '.');
|
|
@@ -110,6 +124,11 @@ function describe(p) {
|
|
|
110
124
|
console.log('\nModule:');
|
|
111
125
|
for (const m of modules) console.log(` ${tilde(m)}`);
|
|
112
126
|
}
|
|
127
|
+
if (legacy.length) {
|
|
128
|
+
console.log(`\nInstallations-Marker (${legacy.length}) -- ohne diese hält die nächste`);
|
|
129
|
+
console.log(' Installation AOS für bereits aktuell installiert:');
|
|
130
|
+
for (const l of legacy) console.log(` ${tilde(l)}`);
|
|
131
|
+
}
|
|
113
132
|
|
|
114
133
|
console.log('\nBleibt erhalten:');
|
|
115
134
|
if (!PURGE) for (const d of DATA_PATHS.filter((d) => existsSync(d.path))) console.log(` ${tilde(d.path).padEnd(18)} ${d.what}`);
|
|
@@ -140,7 +159,7 @@ function dirSize(p) {
|
|
|
140
159
|
|
|
141
160
|
// ------------------------------------------------------------------ execute
|
|
142
161
|
function execute(p) {
|
|
143
|
-
const { ours, edited, agents, modules, data } = p;
|
|
162
|
+
const { ours, edited, agents, modules, legacy, data } = p;
|
|
144
163
|
const stamp = new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
|
|
145
164
|
let removed = 0, backed = 0;
|
|
146
165
|
|
|
@@ -161,6 +180,9 @@ function execute(p) {
|
|
|
161
180
|
for (const m of modules) { try { rmSync(m, { recursive: true, force: true }); } catch { /* in use */ } }
|
|
162
181
|
if (modules.length) console.log(` ${modules.length} Module entfernt`);
|
|
163
182
|
|
|
183
|
+
for (const l of legacy) { try { rmSync(l); } catch { /* already gone */ } }
|
|
184
|
+
if (legacy.length) console.log(` ${legacy.length} Installations-Marker entfernt`);
|
|
185
|
+
|
|
164
186
|
// Only the BDB hook entries leave settings.json; everything else in it is
|
|
165
187
|
// the user's and must survive an uninstall exactly as it survives an install.
|
|
166
188
|
const settings = h('.claude', 'settings.json');
|
package/installer.js
CHANGED
|
@@ -3405,15 +3405,26 @@ function generateAndOpenLaunchpad() {
|
|
|
3405
3405
|
|
|
3406
3406
|
const filePath = path.join(os.homedir(), '.agents', 'bdb-launchpad.html');
|
|
3407
3407
|
fs.writeFileSync(filePath, html, 'utf-8');
|
|
3408
|
+
const warnOpenFailed = (e) => log.warn(`Could not open the dashboard automatically (${e.message}). Open it yourself: ${filePath}`);
|
|
3408
3409
|
try {
|
|
3410
|
+
let child;
|
|
3409
3411
|
if (process.platform === 'darwin') {
|
|
3410
|
-
spawn('open', [filePath], { detached: true, stdio: 'ignore' })
|
|
3412
|
+
child = spawn('open', [filePath], { detached: true, stdio: 'ignore' });
|
|
3411
3413
|
} else if (process.platform === 'win32') {
|
|
3412
|
-
|
|
3414
|
+
// cmd.exe /c start has a title-vs-path quoting quirk when the
|
|
3415
|
+
// arguments come from spawn's argv array rather than a real shell --
|
|
3416
|
+
// on a real Windows test run it silently opened nothing, and the
|
|
3417
|
+
// failure was invisible: spawn() reports a bad launch asynchronously
|
|
3418
|
+
// via 'error', not by throwing, so the try/catch around this call
|
|
3419
|
+
// could never have caught it regardless of --verbose. explorer.exe
|
|
3420
|
+
// on a plain file path has no title argument to misparse.
|
|
3421
|
+
child = spawn('explorer', [filePath], { detached: true, stdio: 'ignore' });
|
|
3413
3422
|
} else {
|
|
3414
|
-
spawn('xdg-open', [filePath], { detached: true, stdio: 'ignore' })
|
|
3423
|
+
child = spawn('xdg-open', [filePath], { detached: true, stdio: 'ignore' });
|
|
3415
3424
|
}
|
|
3416
|
-
|
|
3425
|
+
child.on('error', warnOpenFailed);
|
|
3426
|
+
child.unref();
|
|
3427
|
+
} catch (e) { warnOpenFailed(e); }
|
|
3417
3428
|
}
|
|
3418
3429
|
|
|
3419
3430
|
async function universalHarnessSync(primaryMcpConfigPath) {
|
|
@@ -3662,12 +3673,14 @@ async function main() {
|
|
|
3662
3673
|
{ value: 'quick', label: `⚡ Quick Update (v${installState.localVersion} ➔ v${installState.currentVersion})`, hint: 'refresh skills, templates & daemons' },
|
|
3663
3674
|
{ value: 'project', label: '📁 Drop Local Project Harness', hint: 'copy dispatcher contract to cwd' },
|
|
3664
3675
|
{ value: 'reconfigure', label: '🛠️ Reconfigure System', hint: 'change targets, tier or options' },
|
|
3676
|
+
{ value: 'uninstall', label: '🗑️ Uninstall AOS', hint: 'remove what this installer placed; your data stays' },
|
|
3665
3677
|
{ value: 'cancel', label: '❌ Exit' }
|
|
3666
3678
|
]
|
|
3667
3679
|
: [
|
|
3668
3680
|
{ value: 'project', label: '📁 Drop Local Project Harness', hint: 'copy dispatcher contract to cwd' },
|
|
3669
3681
|
{ value: 'quick', label: '🔄 Verify & Refresh All Skills', hint: 're-sync and health check' },
|
|
3670
3682
|
{ value: 'reconfigure', label: '🛠️ Reconfigure System', hint: 'switch tier or targets' },
|
|
3683
|
+
{ value: 'uninstall', label: '🗑️ Uninstall AOS', hint: 'remove what this installer placed; your data stays' },
|
|
3671
3684
|
{ value: 'cancel', label: '❌ Exit' }
|
|
3672
3685
|
];
|
|
3673
3686
|
|
|
@@ -3691,6 +3704,19 @@ async function main() {
|
|
|
3691
3704
|
outro('Quick Update complete.');
|
|
3692
3705
|
return;
|
|
3693
3706
|
}
|
|
3707
|
+
if (action === 'uninstall') {
|
|
3708
|
+
// aos-uninstall.mjs is its own script, not a function of this file --
|
|
3709
|
+
// it is ESM (installer.js is CommonJS) and drives its own readline
|
|
3710
|
+
// confirmation prompt, so it runs as a real child process with
|
|
3711
|
+
// inherited stdio rather than being imported in-process.
|
|
3712
|
+
const uninstallScript = path.join(srcDir, 'bin', 'aos-uninstall.mjs');
|
|
3713
|
+
if (!fs.existsSync(uninstallScript)) {
|
|
3714
|
+
log.error(`Uninstaller not found at ${uninstallScript} -- run it directly: npx @hybridlabor-api/aos-uninstall`);
|
|
3715
|
+
return;
|
|
3716
|
+
}
|
|
3717
|
+
spawnSync('node', [uninstallScript], { stdio: 'inherit' });
|
|
3718
|
+
return;
|
|
3719
|
+
}
|
|
3694
3720
|
}
|
|
3695
3721
|
|
|
3696
3722
|
const detectedNames = detections.map(d => d.name).join(', ');
|
package/lib/startup-ui.js
CHANGED
|
@@ -83,7 +83,13 @@ function buildTelemetryCard({ installState, detections, daemonStatus = [] }) {
|
|
|
83
83
|
'Google Antigravity': 'Antigravity',
|
|
84
84
|
'ChatGPT Codex CLI': 'Codex CLI',
|
|
85
85
|
'Claude Code CLI': 'Claude Code',
|
|
86
|
-
|
|
86
|
+
// The underlying detection (installer.js's 'vscode' evidence) fires on
|
|
87
|
+
// any of: the VS Code app/CLI being present, OR a Roo/Cline extension
|
|
88
|
+
// glob match. Those are not the same claim -- plain VS Code with no
|
|
89
|
+
// Roo/Cline extension installed used to display as "Roo / Cline" here,
|
|
90
|
+
// asserting something that was not there. "VS Code" is the one label
|
|
91
|
+
// that is true in all three trigger cases.
|
|
92
|
+
'Roo Code / Cline / VS Code': 'VS Code',
|
|
87
93
|
'Aider CLI': 'Aider',
|
|
88
94
|
'OpenCode CLI': 'OpenCode',
|
|
89
95
|
'Cursor / Generic IDE': 'Cursor',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/aos",
|
|
3
|
-
"version": "4.4.2-beta.
|
|
3
|
+
"version": "4.4.2-beta.3",
|
|
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
|
"bin": {
|