

























@@ -128,8 +128,19 @@ function spawnInvocation(command, commandArgs, env, platform) {
128128}
129129130130const cmdMetaCharactersRe = /([()\][%!^"`<>&|;, *?])/g;
131-const jsRuntimeEntrypoints = new Set(["pnpm", "npm", "npx", "corepack", "node", "yarn", "bun"]);
131+const jsRuntimeEntrypoints = new Set([
132+"pnpm",
133+"npm",
134+"npx",
135+"corepack",
136+"node",
137+"yarn",
138+"bun",
139+"bunx",
140+]);
132141const awsMacosCorepackEntrypoints = new Set(["pnpm", "yarn", "corepack"]);
142+const awsMacosBunEntrypoints = new Set(["bun", "bunx"]);
143+const awsMacosBunVersion = "1.3.14";
133144const minimumBlacksmithCrabboxVersion = [0, 22, 0];
134145const shellControlCommandPrefixes = new Set([
135146"if",
@@ -785,25 +796,37 @@ function commandNeedsAwsMacosPackageManager(commandArgs) {
785796if (isChangedGateCommand(commandArgs)) {
786797return true;
787798}
799+return commandNeedsEntrypoint(commandArgs, awsMacosCorepackEntrypoints);
800+}
801+802+function commandNeedsAwsMacosBun(commandArgs) {
803+return commandNeedsEntrypoint(commandArgs, awsMacosBunEntrypoints);
804+}
805+806+function commandNeedsEntrypoint(commandArgs, entrypoints) {
788807if (commandArgs.length === 1) {
789-return shellCommandWordCandidates(commandArgs[0]).some(commandWordsNeedAwsMacosPackageManager);
808+return shellCommandWordCandidates(commandArgs[0]).some((words) =>
809+commandWordsNeedEntrypoint(words, entrypoints),
810+);
790811}
791-return commandWordsNeedAwsMacosPackageManager(normalizedCommandWords(commandArgs));
812+return commandWordsNeedEntrypoint(normalizedCommandWords(commandArgs), entrypoints);
792813}
793814794-function commandWordsNeedAwsMacosPackageManager(wordsInput) {
815+function commandWordsNeedEntrypoint(wordsInput, entrypoints) {
795816let words = wordsInput;
796817words = normalizeExecutableWords(words);
797818const first = (words[0] ?? "").split("/").pop();
798-if (awsMacosCorepackEntrypoints.has(first)) {
819+if (entrypoints.has(first)) {
799820return true;
800821}
801822802823const inlineCommand = shellInlineCommand(words);
803824if (!inlineCommand) {
804825return false;
805826}
806-return shellCommandWordCandidates(inlineCommand).some(commandWordsNeedAwsMacosPackageManager);
827+return shellCommandWordCandidates(inlineCommand).some((candidateWords) =>
828+commandWordsNeedEntrypoint(candidateWords, entrypoints),
829+);
807830}
808831809832function isChangedGateCommand(commandArgs) {
@@ -1668,7 +1691,7 @@ function injectRemoteChangedGateGitBootstrap(commandArgs, changedGateBase) {
16681691return normalizedArgs;
16691692}
167016931671-function remoteAwsMacosJsBootstrap({ packageManager = false } = {}) {
1694+function remoteAwsMacosJsBootstrap({ packageManager = false, bun = false } = {}) {
16721695const nodeVersion = process.env.OPENCLAW_CRABBOX_MACOS_NODE_VERSION?.trim() || "24.15.0";
16731696const bootstrap = [
16741697"openclaw_crabbox_bootstrap_macos_js() {",
@@ -1750,6 +1773,42 @@ function remoteAwsMacosJsBootstrap({ packageManager = false } = {}) {
17501773"pnpm --version >&2;",
17511774);
17521775}
1776+// Raw AWS macOS boxes skip setup-node-env, so Bun needs its own user-local pin.
1777+if (bun) {
1778+bootstrap.push(
1779+`bun_version=${shellQuote(awsMacosBunVersion)};`,
1780+'bun_root="$tool_root/bun-v${bun_version}";',
1781+'bun_ready_marker="$bun_root/.openclaw-crabbox-bun-ready";',
1782+'export PATH="$bun_root/bin:$PATH";',
1783+'if [ ! -x "$bun_root/bin/bun" ] || [ ! -f "$bun_ready_marker" ]; then',
1784+'mkdir -p "$tool_root" || { status=$?; return "$status"; };',
1785+'bun_install_lock="$tool_root/.bun-${bun_version}.lock";',
1786+"bun_lock_acquired=0;",
1787+"bun_lock_deadline=$((SECONDS + 300));",
1788+"while true; do",
1789+'if mkdir "$bun_install_lock" 2>/dev/null; then bun_lock_acquired=1; printf "%s\\n" "$$" >"$bun_install_lock/pid" || { status=$?; rm -rf "$bun_install_lock"; return "$status"; }; break; fi;',
1790+'if [ -x "$bun_root/bin/bun" ] && [ -f "$bun_ready_marker" ]; then break; fi;',
1791+'if [ "$SECONDS" -ge "$bun_lock_deadline" ]; then',
1792+'bun_lock_pid="$(cat "$bun_install_lock/pid" 2>/dev/null || true)";',
1793+'if [ -n "$bun_lock_pid" ] && kill -0 "$bun_lock_pid" 2>/dev/null; then echo "timed out waiting for active macOS Bun install lock: $bun_install_lock pid=$bun_lock_pid" >&2; return 1; fi;',
1794+'echo "reclaiming stale macOS Bun install lock: $bun_install_lock" >&2;',
1795+'rm -rf "$bun_install_lock" || return 1;',
1796+"bun_lock_deadline=$((SECONDS + 300));",
1797+"fi;",
1798+"sleep 1;",
1799+"done;",
1800+'release_bun_install_lock() { if [ "$bun_lock_acquired" = "1" ]; then rm -rf "$bun_install_lock" 2>/dev/null || true; fi; };',
1801+'if [ ! -x "$bun_root/bin/bun" ] || [ ! -f "$bun_ready_marker" ]; then',
1802+'rm -rf "$bun_root" || { status=$?; release_bun_install_lock; return "$status"; };',
1803+'mkdir -p "$bun_root" || { status=$?; release_bun_install_lock; return "$status"; };',
1804+'npm install --global --prefix "$bun_root" "bun@${bun_version}" || { status=$?; release_bun_install_lock; return "$status"; };',
1805+'touch "$bun_ready_marker" || { status=$?; release_bun_install_lock; return "$status"; };',
1806+"fi;",
1807+"release_bun_install_lock;",
1808+"fi;",
1809+"bun --version >&2 || return 1;",
1810+);
1811+}
17531812bootstrap.push("};", "openclaw_crabbox_bootstrap_macos_js");
17541813return bootstrap.join(" ");
17551814}
@@ -1775,6 +1834,7 @@ function scopedAwsMacosEnvCommand(commandArgs) {
17751834return {
17761835runtimeEntrypoint: targetEntrypoint,
17771836packageManager: awsMacosCorepackEntrypoints.has(targetEntrypoint),
1837+bun: awsMacosBunEntrypoints.has(targetEntrypoint),
17781838shellCommand: `openclaw_crabbox_env ${shellJoin(commandArgs.slice(1))}`,
17791839};
17801840}
@@ -1805,6 +1865,7 @@ function injectRemoteAwsMacosJsBootstrap(commandArgs, providerName) {
18051865const shellCommand = `${remoteAwsMacosJsBootstrap({
18061866 packageManager:
18071867 directScopedEnvCommand?.packageManager || commandNeedsAwsMacosPackageManager(runArgs),
1868+ bun: directScopedEnvCommand?.bun || commandNeedsAwsMacosBun(runArgs),
18081869 })} && { ${originalShellCommand}\n}`;
1809187018101871if (!hasOption(normalizedArgs, "--shell")) {
@@ -1876,13 +1937,13 @@ function prepareAwsMacosScriptStdinBootstrap(commandArgs, providerName) {
18761937}
1877193818781939function createAwsMacosScriptStdinWrapper(script) {
1879-const packageManager = scriptNeedsAwsMacosPackageManager(script);
1940+const requirements = awsMacosScriptBootstrapRequirements(script);
18801941if (!script.startsWith("#!")) {
1881-return `${remoteAwsMacosJsBootstrap({ packageManager })} || exit $?\n${script}`;
1942+return `${remoteAwsMacosJsBootstrap(requirements)} || exit $?\n${script}`;
18821943}
18831944const delimiterValue = uniqueHereDocDelimiter(script);
18841945return [
1885-`${remoteAwsMacosJsBootstrap({ packageManager })} || exit $?`,
1946+`${remoteAwsMacosJsBootstrap(requirements)} || exit $?`,
18861947'tmp_script="$(mktemp "${TMPDIR:-/tmp}/openclaw-crabbox-script.XXXXXX")" || exit $?',
18871948'cleanup_openclaw_crabbox_script() { rm -f "$tmp_script"; }',
18881949"trap cleanup_openclaw_crabbox_script EXIT",
@@ -1895,7 +1956,8 @@ function createAwsMacosScriptStdinWrapper(script) {
18951956].join("\n");
18961957}
189719581898-function scriptNeedsAwsMacosPackageManager(script) {
1959+function awsMacosScriptBootstrapRequirements(script) {
1960+const requirements = { packageManager: false, bun: false };
18991961const firstLine = script.match(/^[^\r\n]*/u)?.[0] ?? "";
19001962if (firstLine.startsWith("#!")) {
19011963let words = firstLine.slice(2).trim().split(/\s+/u).filter(Boolean);
@@ -1905,11 +1967,13 @@ function scriptNeedsAwsMacosPackageManager(script) {
19051967words = words.slice(1);
19061968}
19071969}
1908-if (commandWordsNeedAwsMacosPackageManager(words)) {
1909- return true;
1910-}
1970+requirements.packageManager = commandWordsNeedEntrypoint(words, awsMacosCorepackEntrypoints);
1971+requirements.bun = commandWordsNeedEntrypoint(words, awsMacosBunEntrypoints);
1972+return requirements;
19111973}
1912-return commandNeedsAwsMacosPackageManager([script]);
1974+requirements.packageManager = commandNeedsAwsMacosPackageManager([script]);
1975+requirements.bun = commandNeedsAwsMacosBun([script]);
1976+return requirements;
19131977}
1914197819151979function uniqueHereDocDelimiter(script) {
@@ -2369,15 +2433,15 @@ if (
23692433) {
23702434if (isAwsMacosRemoteTarget(normalizedArgs, provider)) {
23712435console.error(
2372-`[crabbox] provider=aws macOS raw boxes may lack Node/Corepack/pnpm for ${runtimeEntrypoint || "--script-stdin"}; bootstrapping a pinned user-local Node toolchain before the command`,
2436+`[crabbox] provider=aws macOS raw boxes may lack Node/Corepack/pnpm/Bun for ${runtimeEntrypoint || "--script-stdin"}; bootstrapping pinned user-local JavaScript tooling before the command`,
23732437);
23742438} else {
23752439const id = optionValue(normalizedArgs, "--id");
23762440const hydrate = id
23772441 ? `pnpm crabbox:hydrate -- --id ${id}`
23782442 : "pnpm crabbox:warmup, then pnpm crabbox:hydrate -- --id <id>";
23792443console.error(
2380-`[crabbox] warning: provider=aws raw boxes may lack Node/Corepack/pnpm for ${runtimeEntrypoint}; hydrate first (${hydrate}) or pass --provider blacksmith-testbox for OpenClaw CI-like proof; not switching providers automatically`,
2444+`[crabbox] warning: provider=aws raw boxes may lack Node/Corepack/pnpm/Bun for ${runtimeEntrypoint}; hydrate first (${hydrate}) or pass --provider blacksmith-testbox for OpenClaw CI-like proof; not switching providers automatically`,
23812445);
23822446}
23832447}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。