@hybridlabor-api/aos 4.6.2 → 4.6.4
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/installer.js +64 -9
- package/package.json +1 -1
package/installer.js
CHANGED
|
@@ -59,6 +59,12 @@ const {
|
|
|
59
59
|
log
|
|
60
60
|
} = clack;
|
|
61
61
|
|
|
62
|
+
// Defensive alias: @clack/prompts provides log.success, not log.ok.
|
|
63
|
+
// Ensure any legacy or third-party call to log.ok safely routes to log.success.
|
|
64
|
+
if (log && typeof log === 'object' && !log.ok) {
|
|
65
|
+
log.ok = log.success;
|
|
66
|
+
}
|
|
67
|
+
|
|
62
68
|
const {
|
|
63
69
|
renderKineticIntro,
|
|
64
70
|
buildHeroHeader,
|
|
@@ -1066,6 +1072,15 @@ function moveIfExists(src, dest, label) {
|
|
|
1066
1072
|
}
|
|
1067
1073
|
}
|
|
1068
1074
|
|
|
1075
|
+
function safeRmDirSync(dirPath, maxRetries = 5, retryDelay = 200) {
|
|
1076
|
+
if (!dirPath || !fs.existsSync(dirPath)) return;
|
|
1077
|
+
try {
|
|
1078
|
+
fs.rmSync(dirPath, { recursive: true, force: true, maxRetries, retryDelay });
|
|
1079
|
+
} catch (err) {
|
|
1080
|
+
logDebug(err, `safeRmDirSync: ${dirPath}`);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1069
1084
|
function copyDirRecursiveSync(source, target, excludeList = [], manifest = null, knownSourceHashes = null) {
|
|
1070
1085
|
// Fall back to session-level state when no explicit manifest is passed.
|
|
1071
1086
|
const mfst = manifest !== null ? manifest : _sessionManifest;
|
|
@@ -1716,7 +1731,21 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
|
|
|
1716
1731
|
// kept until the swap succeeds, and restored if it does not.
|
|
1717
1732
|
const stagingDir = `${targetDir}.incoming-${timestamp}`;
|
|
1718
1733
|
const retiredDir = `${targetDir}.previous-${timestamp}`;
|
|
1719
|
-
|
|
1734
|
+
|
|
1735
|
+
// Clean up any stale staging or retired directories left behind by earlier interrupted runs
|
|
1736
|
+
try {
|
|
1737
|
+
const parentDir = path.dirname(targetDir);
|
|
1738
|
+
const baseName = path.basename(targetDir);
|
|
1739
|
+
if (fs.existsSync(parentDir)) {
|
|
1740
|
+
for (const item of fs.readdirSync(parentDir)) {
|
|
1741
|
+
if (item.startsWith(`${baseName}.incoming-`) || item.startsWith(`${baseName}.previous-`)) {
|
|
1742
|
+
safeRmDirSync(path.join(parentDir, item));
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
} catch (_) {}
|
|
1747
|
+
|
|
1748
|
+
safeRmDirSync(stagingDir);
|
|
1720
1749
|
fs.mkdirSync(stagingDir, { recursive: true });
|
|
1721
1750
|
execSync(`tar -xzf "${path.join(targetDir, tarball)}" --strip-components=1 -C "${stagingDir}"`, { stdio: 'ignore' });
|
|
1722
1751
|
fs.unlinkSync(path.join(targetDir, tarball));
|
|
@@ -1727,7 +1756,11 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
|
|
|
1727
1756
|
for (const keep of PRESERVE) {
|
|
1728
1757
|
const from = path.join(targetDir, keep);
|
|
1729
1758
|
if (fs.existsSync(from) && !fs.existsSync(path.join(stagingDir, keep))) {
|
|
1730
|
-
|
|
1759
|
+
try {
|
|
1760
|
+
fs.renameSync(from, path.join(stagingDir, keep));
|
|
1761
|
+
} catch (preserveErr) {
|
|
1762
|
+
logDebug(preserveErr, `preserve ${keep}`);
|
|
1763
|
+
}
|
|
1731
1764
|
}
|
|
1732
1765
|
}
|
|
1733
1766
|
|
|
@@ -1735,11 +1768,17 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
|
|
|
1735
1768
|
fs.renameSync(targetDir, retiredDir);
|
|
1736
1769
|
fs.renameSync(stagingDir, targetDir);
|
|
1737
1770
|
} catch (swapError) {
|
|
1738
|
-
if (fs.existsSync(retiredDir) && !fs.existsSync(targetDir))
|
|
1739
|
-
|
|
1771
|
+
if (fs.existsSync(retiredDir) && !fs.existsSync(targetDir)) {
|
|
1772
|
+
try { fs.renameSync(retiredDir, targetDir); } catch (_) {}
|
|
1773
|
+
}
|
|
1774
|
+
safeRmDirSync(stagingDir);
|
|
1740
1775
|
throw swapError;
|
|
1741
1776
|
}
|
|
1742
|
-
|
|
1777
|
+
|
|
1778
|
+
// On Windows especially, deleting a directory that was just renamed or contains
|
|
1779
|
+
// locked file handles can throw EPERM / EBUSY. Since targetDir already has the
|
|
1780
|
+
// new version in place, failure to clean up retiredDir must be non-fatal.
|
|
1781
|
+
safeRmDirSync(retiredDir);
|
|
1743
1782
|
|
|
1744
1783
|
s.stop(`${displayName} ready (v${status.remoteVer || 'latest'})`);
|
|
1745
1784
|
return true;
|
|
@@ -1804,6 +1843,17 @@ async function installMemB(interactive) {
|
|
|
1804
1843
|
if (!hasUv) {
|
|
1805
1844
|
try { execSync('uv --version', { stdio: 'ignore' }); hasUv = true; } catch (e) { hasUv = false; }
|
|
1806
1845
|
}
|
|
1846
|
+
if (!hasUv && fs.existsSync(venvPython)) {
|
|
1847
|
+
try {
|
|
1848
|
+
execSync(`"${venvPython}" -m pip --version`, { stdio: 'ignore' });
|
|
1849
|
+
} catch (_) {
|
|
1850
|
+
try {
|
|
1851
|
+
execSync(`"${venvPython}" -m ensurepip --default-pip`, { cwd: membDir, stdio: 'ignore' });
|
|
1852
|
+
} catch (ePip) {
|
|
1853
|
+
logDebug(ePip, 'ensurepip bootstrap for memB');
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1807
1857
|
const uvInstall = (pkgsArg) => `uv pip install --python "${venvPython}" ${pkgsArg}`;
|
|
1808
1858
|
const pipInstall = (pkgsArg) => `"${venvPython}" -m pip install ${pkgsArg} --timeout 30 --no-input`;
|
|
1809
1859
|
const installCmd = (pkgsArg) => hasUv ? uvInstall(pkgsArg) : pipInstall(pkgsArg);
|
|
@@ -2022,7 +2072,7 @@ async function installOpenWikiVisualizer() {
|
|
|
2022
2072
|
log.warn('Skipping OpenWiki Visualizer setup: the openwiki CLI is not on PATH. Install it with: npm install -g openwiki@latest');
|
|
2023
2073
|
return;
|
|
2024
2074
|
}
|
|
2025
|
-
log.
|
|
2075
|
+
log.success('OpenWiki CLI installed.');
|
|
2026
2076
|
}
|
|
2027
2077
|
// launchd starts agents with a minimal PATH that never includes npm's global
|
|
2028
2078
|
// bin dir, so resolve the absolute binary path now instead of relying on PATH at boot.
|
|
@@ -2070,11 +2120,12 @@ async function installOpenWikiVisualizer() {
|
|
|
2070
2120
|
const ecosystemWiki = path.join(homeDir, '.openwiki', 'ecosystem-wiki');
|
|
2071
2121
|
const syncScript = path.join(srcDir, 'skills', 'global_config', 'openwiki-skill', 'scripts', 'sync_ecosystem_wiki.py');
|
|
2072
2122
|
if (!wikiPath) {
|
|
2123
|
+
const pyBin = hasExecutable('python3') ? 'python3' : hasExecutable('python') ? 'python' : null;
|
|
2073
2124
|
if (looksLikeWiki(ecosystemWiki)) {
|
|
2074
2125
|
wikiPath = ecosystemWiki;
|
|
2075
|
-
} else if (fs.existsSync(syncScript) &&
|
|
2126
|
+
} else if (fs.existsSync(syncScript) && pyBin) {
|
|
2076
2127
|
try {
|
|
2077
|
-
execSync(`
|
|
2128
|
+
execSync(`"${pyBin}" "${syncScript}"`, { stdio: 'ignore' });
|
|
2078
2129
|
if (looksLikeWiki(ecosystemWiki)) wikiPath = ecosystemWiki;
|
|
2079
2130
|
} catch (e) { logDebug(e, 'ecosystem wiki sync'); }
|
|
2080
2131
|
}
|
|
@@ -2085,6 +2136,9 @@ async function installOpenWikiVisualizer() {
|
|
|
2085
2136
|
});
|
|
2086
2137
|
if (!isCancel(answer) && answer && answer.trim()) {
|
|
2087
2138
|
const candidate = answer.trim().replace(/^~(?=$|\/|\\)/, homeDir);
|
|
2139
|
+
if (!fs.existsSync(candidate)) {
|
|
2140
|
+
try { fs.mkdirSync(candidate, { recursive: true }); } catch (_) {}
|
|
2141
|
+
}
|
|
2088
2142
|
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
2089
2143
|
wikiPath = candidate;
|
|
2090
2144
|
if (!looksLikeWiki(candidate)) {
|
|
@@ -2151,7 +2205,8 @@ async function installOpenWikiVisualizer() {
|
|
|
2151
2205
|
const stdoutLog = path.join(visualizerLogDir, 'visualize.stdout.log');
|
|
2152
2206
|
const stderrLog = path.join(visualizerLogDir, 'visualize.stderr.log');
|
|
2153
2207
|
const batPath = path.join(visualizerLogDir, 'run-openwiki-visualize.bat');
|
|
2154
|
-
const
|
|
2208
|
+
const targetWikiArg = wikiPath ? `"${wikiPath}" ` : '';
|
|
2209
|
+
const runCmd = `"${openwikiBin}" visualize ${targetWikiArg}--port 4321 --no-open`;
|
|
2155
2210
|
const batContent = `@echo off\r\ncd /d "${homeDir}"\r\n${runCmd} >> "${stdoutLog}" 2>> "${stderrLog}"\r\n`;
|
|
2156
2211
|
const vbsPath = path.join(startupDir, 'com.bdb.openwiki-visualize.vbs');
|
|
2157
2212
|
const vbsContent = `Set WshShell = CreateObject("WScript.Shell")\r\nWshShell.CurrentDirectory = "${homeDir}"\r\nWshShell.Run """${batPath}""", 0, False\r\n`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/aos",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.4",
|
|
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": {
|