@hybridlabor-api/aos 4.6.3 → 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 +55 -7
- package/package.json +1 -1
package/installer.js
CHANGED
|
@@ -1072,6 +1072,15 @@ function moveIfExists(src, dest, label) {
|
|
|
1072
1072
|
}
|
|
1073
1073
|
}
|
|
1074
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
|
+
|
|
1075
1084
|
function copyDirRecursiveSync(source, target, excludeList = [], manifest = null, knownSourceHashes = null) {
|
|
1076
1085
|
// Fall back to session-level state when no explicit manifest is passed.
|
|
1077
1086
|
const mfst = manifest !== null ? manifest : _sessionManifest;
|
|
@@ -1722,7 +1731,21 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
|
|
|
1722
1731
|
// kept until the swap succeeds, and restored if it does not.
|
|
1723
1732
|
const stagingDir = `${targetDir}.incoming-${timestamp}`;
|
|
1724
1733
|
const retiredDir = `${targetDir}.previous-${timestamp}`;
|
|
1725
|
-
|
|
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);
|
|
1726
1749
|
fs.mkdirSync(stagingDir, { recursive: true });
|
|
1727
1750
|
execSync(`tar -xzf "${path.join(targetDir, tarball)}" --strip-components=1 -C "${stagingDir}"`, { stdio: 'ignore' });
|
|
1728
1751
|
fs.unlinkSync(path.join(targetDir, tarball));
|
|
@@ -1733,7 +1756,11 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
|
|
|
1733
1756
|
for (const keep of PRESERVE) {
|
|
1734
1757
|
const from = path.join(targetDir, keep);
|
|
1735
1758
|
if (fs.existsSync(from) && !fs.existsSync(path.join(stagingDir, keep))) {
|
|
1736
|
-
|
|
1759
|
+
try {
|
|
1760
|
+
fs.renameSync(from, path.join(stagingDir, keep));
|
|
1761
|
+
} catch (preserveErr) {
|
|
1762
|
+
logDebug(preserveErr, `preserve ${keep}`);
|
|
1763
|
+
}
|
|
1737
1764
|
}
|
|
1738
1765
|
}
|
|
1739
1766
|
|
|
@@ -1741,11 +1768,17 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
|
|
|
1741
1768
|
fs.renameSync(targetDir, retiredDir);
|
|
1742
1769
|
fs.renameSync(stagingDir, targetDir);
|
|
1743
1770
|
} catch (swapError) {
|
|
1744
|
-
if (fs.existsSync(retiredDir) && !fs.existsSync(targetDir))
|
|
1745
|
-
|
|
1771
|
+
if (fs.existsSync(retiredDir) && !fs.existsSync(targetDir)) {
|
|
1772
|
+
try { fs.renameSync(retiredDir, targetDir); } catch (_) {}
|
|
1773
|
+
}
|
|
1774
|
+
safeRmDirSync(stagingDir);
|
|
1746
1775
|
throw swapError;
|
|
1747
1776
|
}
|
|
1748
|
-
|
|
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);
|
|
1749
1782
|
|
|
1750
1783
|
s.stop(`${displayName} ready (v${status.remoteVer || 'latest'})`);
|
|
1751
1784
|
return true;
|
|
@@ -1810,6 +1843,17 @@ async function installMemB(interactive) {
|
|
|
1810
1843
|
if (!hasUv) {
|
|
1811
1844
|
try { execSync('uv --version', { stdio: 'ignore' }); hasUv = true; } catch (e) { hasUv = false; }
|
|
1812
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
|
+
}
|
|
1813
1857
|
const uvInstall = (pkgsArg) => `uv pip install --python "${venvPython}" ${pkgsArg}`;
|
|
1814
1858
|
const pipInstall = (pkgsArg) => `"${venvPython}" -m pip install ${pkgsArg} --timeout 30 --no-input`;
|
|
1815
1859
|
const installCmd = (pkgsArg) => hasUv ? uvInstall(pkgsArg) : pipInstall(pkgsArg);
|
|
@@ -2076,11 +2120,12 @@ async function installOpenWikiVisualizer() {
|
|
|
2076
2120
|
const ecosystemWiki = path.join(homeDir, '.openwiki', 'ecosystem-wiki');
|
|
2077
2121
|
const syncScript = path.join(srcDir, 'skills', 'global_config', 'openwiki-skill', 'scripts', 'sync_ecosystem_wiki.py');
|
|
2078
2122
|
if (!wikiPath) {
|
|
2123
|
+
const pyBin = hasExecutable('python3') ? 'python3' : hasExecutable('python') ? 'python' : null;
|
|
2079
2124
|
if (looksLikeWiki(ecosystemWiki)) {
|
|
2080
2125
|
wikiPath = ecosystemWiki;
|
|
2081
|
-
} else if (fs.existsSync(syncScript) &&
|
|
2126
|
+
} else if (fs.existsSync(syncScript) && pyBin) {
|
|
2082
2127
|
try {
|
|
2083
|
-
execSync(`
|
|
2128
|
+
execSync(`"${pyBin}" "${syncScript}"`, { stdio: 'ignore' });
|
|
2084
2129
|
if (looksLikeWiki(ecosystemWiki)) wikiPath = ecosystemWiki;
|
|
2085
2130
|
} catch (e) { logDebug(e, 'ecosystem wiki sync'); }
|
|
2086
2131
|
}
|
|
@@ -2091,6 +2136,9 @@ async function installOpenWikiVisualizer() {
|
|
|
2091
2136
|
});
|
|
2092
2137
|
if (!isCancel(answer) && answer && answer.trim()) {
|
|
2093
2138
|
const candidate = answer.trim().replace(/^~(?=$|\/|\\)/, homeDir);
|
|
2139
|
+
if (!fs.existsSync(candidate)) {
|
|
2140
|
+
try { fs.mkdirSync(candidate, { recursive: true }); } catch (_) {}
|
|
2141
|
+
}
|
|
2094
2142
|
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
2095
2143
|
wikiPath = candidate;
|
|
2096
2144
|
if (!looksLikeWiki(candidate)) {
|
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": {
|