























@@ -1056,8 +1056,8 @@ function commandNeedsAwsMacosPackageManager(commandArgs, options = {}) {
10561056return true;
10571057}
10581058if (commandArgs.length === 1) {
1059-return shellCommandWordCandidates(commandArgs[0]).some(
1060-(words) => commandWordsNeedAwsMacosPackageManager(words, options),
1059+return shellCommandWordCandidates(commandArgs[0]).some((words) =>
1060+commandWordsNeedAwsMacosPackageManager(words, options),
10611061);
10621062}
10631063return commandWordsNeedAwsMacosPackageManager(normalizedCommandWords(commandArgs), options);
@@ -1964,7 +1964,7 @@ function remoteGitBootstrapForChangedGate(changedGateBase) {
19641964}
1965196519661966function injectRemoteChangedGateEnvironment(commandArgs) {
1967-if (commandArgs[0] !== "run" || isWindowsRemoteTarget(commandArgs)) {
1967+if (commandArgs[0] !== "run" || isNativeWindowsRemoteTarget(commandArgs)) {
19681968return commandArgs;
19691969}
19701970@@ -2055,6 +2055,16 @@ function isAwsMacosRemoteTarget(commandArgs, providerName) {
20552055);
20562056}
205720572058+function isBrokeredWsl2RemoteTarget(commandArgs, providerName) {
2059+const canonicalProvider = providerAliases.get(providerName) ?? providerName;
2060+return (
2061+commandArgs[0] === "run" &&
2062+(canonicalProvider === "aws" || canonicalProvider === "azure") &&
2063+isWindowsRemoteTarget(commandArgs) &&
2064+optionValue(commandArgs, "--windows-mode") === "wsl2"
2065+);
2066+}
2067+20582068function isHydratedNativeWindowsProvider(providerName) {
20592069return providerName === "aws" || providerName === "azure";
20602070}
@@ -2141,6 +2151,31 @@ function injectRemoteChangedGateGitBootstrap(commandArgs, changedGateBase) {
21412151return normalizedArgs;
21422152}
214321532154+function remotePosixJsEnvBootstrap() {
2155+return [
2156+"openclaw_crabbox_env() {",
2157+"openclaw_env_args=();",
2158+"openclaw_env_ignore=0;",
2159+"openclaw_env_path_seen=0;",
2160+'while [ "$#" -gt 0 ]; do',
2161+'case "$1" in',
2162+'-i|--ignore-environment) openclaw_env_ignore=1; openclaw_env_args+=("$1"); shift ;;',
2163+'-S|--split-string|-S*|--split-string=*) command env "${openclaw_env_args[@]}" "$@"; return ;;',
2164+'-[!-]*i*) openclaw_env_ignore=1; openclaw_env_args+=("$1"); shift ;;',
2165+'-u|--unset|-C|--chdir) openclaw_env_args+=("$1"); shift; if [ "$#" -gt 0 ]; then openclaw_env_args+=("$1"); shift; fi ;;',
2166+'--unset=*|--chdir=*) openclaw_env_args+=("$1"); shift ;;',
2167+'PATH=*) if [ "$openclaw_env_ignore" = "1" ]; then openclaw_env_args+=("PATH=${OPENCLAW_CRABBOX_BOOTSTRAP_PATH:-$PATH}:${1#PATH=}"); else openclaw_env_args+=("$1"); fi; openclaw_env_path_seen=1; shift ;;',
2168+'[A-Za-z_]*=*) openclaw_env_args+=("$1"); shift ;;',
2169+'--) openclaw_env_args+=("--"); shift; break ;;',
2170+"*) break ;;",
2171+"esac;",
2172+"done;",
2173+'if [ "$openclaw_env_ignore" = "1" ] && [ "$openclaw_env_path_seen" = "0" ]; then openclaw_env_args+=("PATH=${OPENCLAW_CRABBOX_BOOTSTRAP_PATH:-$PATH}"); fi;',
2174+'command env "${openclaw_env_args[@]}" "$@";',
2175+"};",
2176+];
2177+}
2178+21442179function remoteAwsMacosJsBootstrap({ packageManager = false, bun = false } = {}) {
21452180const nodeVersion = process.env.OPENCLAW_CRABBOX_MACOS_NODE_VERSION?.trim() || "24.15.0";
21462181const bootstrap = [
@@ -2192,26 +2227,7 @@ function remoteAwsMacosJsBootstrap({ packageManager = false, bun = false } = {})
21922227"release_install_lock;",
21932228"fi;",
21942229"node --version >&2 || return 1;",
2195-"openclaw_crabbox_env() {",
2196-"openclaw_env_args=();",
2197-"openclaw_env_ignore=0;",
2198-"openclaw_env_path_seen=0;",
2199-'while [ "$#" -gt 0 ]; do',
2200-'case "$1" in',
2201-'-i|--ignore-environment) openclaw_env_ignore=1; openclaw_env_args+=("$1"); shift ;;',
2202-'-S|--split-string|-S*|--split-string=*) command env "${openclaw_env_args[@]}" "$@"; return ;;',
2203-'-[!-]*i*) openclaw_env_ignore=1; openclaw_env_args+=("$1"); shift ;;',
2204-'-u|--unset|-C|--chdir) openclaw_env_args+=("$1"); shift; if [ "$#" -gt 0 ]; then openclaw_env_args+=("$1"); shift; fi ;;',
2205-'--unset=*|--chdir=*) openclaw_env_args+=("$1"); shift ;;',
2206-'PATH=*) if [ "$openclaw_env_ignore" = "1" ]; then openclaw_env_args+=("PATH=${OPENCLAW_CRABBOX_BOOTSTRAP_PATH:-$PATH}:${1#PATH=}"); else openclaw_env_args+=("$1"); fi; openclaw_env_path_seen=1; shift ;;',
2207-'[A-Za-z_]*=*) openclaw_env_args+=("$1"); shift ;;',
2208-'--) openclaw_env_args+=("--"); shift; break ;;',
2209-"*) break ;;",
2210-"esac;",
2211-"done;",
2212-'if [ "$openclaw_env_ignore" = "1" ] && [ "$openclaw_env_path_seen" = "0" ]; then openclaw_env_args+=("PATH=${OPENCLAW_CRABBOX_BOOTSTRAP_PATH:-$PATH}"); fi;',
2213-'command env "${openclaw_env_args[@]}" "$@";',
2214-"};",
2230+ ...remotePosixJsEnvBootstrap(),
22152231];
22162232if (packageManager) {
22172233bootstrap.push(
@@ -2264,6 +2280,71 @@ function remoteAwsMacosJsBootstrap({ packageManager = false, bun = false } = {})
22642280return bootstrap.join(" ");
22652281}
226622822283+function remoteWsl2JsBootstrap({ packageManager = false } = {}) {
2284+const nodeVersion = process.env.OPENCLAW_CRABBOX_WSL2_NODE_VERSION?.trim() || "24.15.0";
2285+const bootstrap = [
2286+"openclaw_crabbox_bootstrap_wsl2_js() {",
2287+'tool_root="${OPENCLAW_CRABBOX_WSL2_TOOLCHAIN_DIR:-$HOME/.openclaw-crabbox-toolchain}";',
2288+`node_version=${shellQuote(nodeVersion)};`,
2289+'arch="$(uname -m)";',
2290+'case "$arch" in arm64|aarch64) node_arch=arm64 ;; x86_64|amd64) node_arch=x64 ;; *) echo "unsupported WSL2 arch: $arch" >&2; return 2 ;; esac;',
2291+'if [ -z "${TMPDIR:-}" ]; then export TMPDIR="/tmp"; fi;',
2292+'if [ ! -d "$TMPDIR" ]; then mkdir -p "$TMPDIR" 2>/dev/null || export TMPDIR="/tmp"; fi;',
2293+'if [ ! -d "$TMPDIR" ]; then echo "usable TMPDIR not found: $TMPDIR" >&2; return 1; fi;',
2294+'node_dir="$tool_root/node-v${node_version}-linux-${node_arch}";',
2295+'ready_marker="$node_dir/.openclaw-crabbox-node-ready";',
2296+'export PATH="$node_dir/bin:$PATH";',
2297+'if [ ! -x "$node_dir/bin/node" ] || [ ! -f "$ready_marker" ]; then',
2298+'mkdir -p "$tool_root" || { status=$?; return "$status"; };',
2299+'install_lock="$tool_root/.node-${node_version}-${node_arch}.lock";',
2300+"lock_acquired=0;",
2301+"lock_deadline=$((SECONDS + 300));",
2302+"while true; do",
2303+'if mkdir "$install_lock" 2>/dev/null; then lock_acquired=1; printf "%s\\n" "$$" >"$install_lock/pid" || { status=$?; rm -rf "$install_lock"; return "$status"; }; break; fi;',
2304+'if [ -x "$node_dir/bin/node" ] && [ -f "$ready_marker" ]; then break; fi;',
2305+'if [ "$SECONDS" -ge "$lock_deadline" ]; then',
2306+'lock_pid="$(cat "$install_lock/pid" 2>/dev/null || true)";',
2307+'if [ -n "$lock_pid" ] && kill -0 "$lock_pid" 2>/dev/null; then echo "timed out waiting for active WSL2 Node toolchain install lock: $install_lock pid=$lock_pid" >&2; return 1; fi;',
2308+'echo "reclaiming stale WSL2 Node toolchain install lock: $install_lock" >&2;',
2309+'rm -rf "$install_lock" || return 1;',
2310+"lock_deadline=$((SECONDS + 300));",
2311+"fi;",
2312+"sleep 1;",
2313+"done;",
2314+'release_install_lock() { if [ "$lock_acquired" = "1" ]; then rm -rf "$install_lock" 2>/dev/null || true; fi; };',
2315+'if [ ! -x "$node_dir/bin/node" ] || [ ! -f "$ready_marker" ]; then',
2316+'tmp_dir="$(mktemp -d)" || { release_install_lock; return 1; };',
2317+'pkg="node-v${node_version}-linux-${node_arch}.tar.gz";',
2318+'base_url="https://nodejs.org/dist/v${node_version}";',
2319+'curl -fsSL --connect-timeout 10 --max-time 300 --retry 2 --retry-delay 2 -o "$tmp_dir/$pkg" "$base_url/$pkg" || { status=$?; release_install_lock; rm -rf "$tmp_dir"; return "$status"; };',
2320+'curl -fsSL --connect-timeout 10 --max-time 60 --retry 2 --retry-delay 2 -o "$tmp_dir/SHASUMS256.txt" "$base_url/SHASUMS256.txt" || { status=$?; release_install_lock; rm -rf "$tmp_dir"; return "$status"; };',
2321+'(cd "$tmp_dir" && grep " $pkg$" SHASUMS256.txt | sha256sum -c -) || { status=$?; release_install_lock; rm -rf "$tmp_dir"; return "$status"; };',
2322+'rm -rf "$node_dir" || { status=$?; release_install_lock; rm -rf "$tmp_dir"; return "$status"; };',
2323+'tar -xzf "$tmp_dir/$pkg" -C "$tool_root" || { status=$?; release_install_lock; rm -rf "$tmp_dir"; return "$status"; };',
2324+'touch "$ready_marker" || { status=$?; release_install_lock; rm -rf "$tmp_dir"; return "$status"; };',
2325+'rm -rf "$tmp_dir";',
2326+"fi;",
2327+"release_install_lock;",
2328+"fi;",
2329+"node --version >&2 || return 1;",
2330+ ...remotePosixJsEnvBootstrap(),
2331+];
2332+if (packageManager) {
2333+bootstrap.push(
2334+'export COREPACK_HOME="${COREPACK_HOME:-$tool_root/corepack}";',
2335+'export PNPM_HOME="${PNPM_HOME:-$tool_root/pnpm-home}";',
2336+'mkdir -p "$COREPACK_HOME" "$PNPM_HOME" || return 1;',
2337+'export PATH="$PNPM_HOME:$PATH";',
2338+'corepack enable --install-directory "$PNPM_HOME" || return 1;',
2339+"pnpm --version >&2;",
2340+"if [ -f pnpm-lock.yaml ] && [ ! -f node_modules/.modules.yaml ]; then pnpm install --frozen-lockfile || return 1; fi;",
2341+);
2342+}
2343+bootstrap.push('export OPENCLAW_CRABBOX_BOOTSTRAP_PATH="$PATH";');
2344+bootstrap.push("};", "openclaw_crabbox_bootstrap_wsl2_js");
2345+return bootstrap.join(" ");
2346+}
2347+22672348function scopedAwsMacosEnvCommand(commandArgs) {
22682349if (commandArgs.length <= 1 || !isSupportedSystemEnvCommand(commandArgs[0])) {
22692350return null;
@@ -2280,11 +2361,7 @@ function scopedAwsMacosEnvCommand(commandArgs) {
22802361commandWordsNeedAwsMacosPackageManager(targetWords);
22812362const needsRuntime = jsRuntimeEntrypoints.has(targetEntrypoint);
22822363const needsBun = awsMacosBunEntrypoints.has(targetEntrypoint);
2283-if (
2284-!needsRuntime &&
2285-!needsPackageManager &&
2286-!needsBun
2287-) {
2364+if (!needsRuntime && !needsPackageManager && !needsBun) {
22882365return null;
22892366}
22902367@@ -2521,6 +2598,73 @@ function readLeadingShellWord(command, start) {
25212598return word ? { word, end: command.length } : null;
25222599}
252326002601+function remoteWsl2JsBootstrapRequirements(commandArgs) {
2602+const runArgs = runCommandArgs(commandArgs);
2603+const directScopedEnvCommand = hasOption(commandArgs, "--shell")
2604+ ? null
2605+ : scopedAwsMacosEnvCommand(runArgs);
2606+const shellScopedEnvCommand =
2607+hasOption(commandArgs, "--shell") && runArgs.length === 1
2608+ ? scopedAwsMacosShellEnvCommand(runArgs[0])
2609+ : null;
2610+const scopedEnvCommand = directScopedEnvCommand ?? shellScopedEnvCommand;
2611+const packageManagerFallbackNeeded = scopedEnvCommand
2612+ ? commandNeedsAwsMacosPackageManager(runArgs)
2613+ : commandNeedsAwsMacosPackageManager(runArgs, { canShimIgnoreEnvironment: false });
2614+const packageManagerNeeded = scopedEnvCommand?.packageManager || packageManagerFallbackNeeded;
2615+const runtimeEntrypoint =
2616+scopedEnvCommand?.runtimeEntrypoint || commandRuntimeEntrypoint(runArgs);
2617+const runtimeNeeded =
2618+runtimeEntrypoint && !awsMacosBunEntrypoints.has(runtimeEntrypoint) ? runtimeEntrypoint : "";
2619+2620+return {
2621+ scopedEnvCommand,
2622+packageManager: packageManagerNeeded,
2623+runtimeEntrypoint: runtimeNeeded,
2624+};
2625+}
2626+2627+function prepareRemoteWsl2JsBootstrapScript(commandArgs, providerName) {
2628+const requirements = remoteWsl2JsBootstrapRequirements(commandArgs);
2629+if (
2630+!isBrokeredWsl2RemoteTarget(commandArgs, providerName) ||
2631+(!requirements.runtimeEntrypoint && !requirements.packageManager)
2632+) {
2633+return { args: commandArgs, cleanup: () => {}, prepared: false };
2634+}
2635+2636+const { start, optionEnd } = runCommandBounds(commandArgs);
2637+if (start < 0) {
2638+return { args: commandArgs, cleanup: () => {}, prepared: false };
2639+}
2640+2641+const scriptRoot = mkdtempSync(resolve(tmpdir(), "openclaw-crabbox-wsl2-script-"));
2642+const scriptPath = resolve(scriptRoot, "script.sh");
2643+const remoteCommand = commandArgs.slice(start);
2644+const originalShellCommand =
2645+requirements.scopedEnvCommand?.shellCommand ??
2646+(hasOption(commandArgs, "--shell") && remoteCommand.length === 1
2647+ ? remoteCommand[0]
2648+ : shellJoin(remoteCommand));
2649+const script = `${remoteWsl2JsBootstrap({
2650+ packageManager: requirements.packageManager,
2651+ })} || exit $?\n{ ${originalShellCommand}\n}\n`;
2652+writeFileSync(scriptPath, script, "utf8");
2653+chmodSync(scriptPath, 0o700);
2654+2655+const normalizedArgs = commandArgs.slice(0, optionEnd);
2656+if (!hasOption(normalizedArgs, "--no-hydrate")) {
2657+normalizedArgs.push("--no-hydrate");
2658+}
2659+normalizedArgs.push("--script", scriptPath);
2660+2661+return {
2662+args: normalizedArgs,
2663+cleanup: () => rmSync(scriptRoot, { recursive: true, force: true }),
2664+prepared: true,
2665+};
2666+}
2667+25242668function injectRemoteAwsMacosJsBootstrap(commandArgs, providerName) {
25252669const runArgs = runCommandArgs(commandArgs);
25262670const directScopedEnvCommand = hasOption(commandArgs, "--shell")
@@ -2531,12 +2675,10 @@ function injectRemoteAwsMacosJsBootstrap(commandArgs, providerName) {
25312675 ? scopedAwsMacosShellEnvCommand(runArgs[0])
25322676 : null;
25332677const scopedEnvCommand = directScopedEnvCommand ?? shellScopedEnvCommand;
2534-const packageManagerFallbackNeeded =
2535-scopedEnvCommand
2536- ? commandNeedsAwsMacosPackageManager(runArgs)
2537- : commandNeedsAwsMacosPackageManager(runArgs, { canShimIgnoreEnvironment: false });
2538-const packageManagerNeeded =
2539-scopedEnvCommand?.packageManager || packageManagerFallbackNeeded;
2678+const packageManagerFallbackNeeded = scopedEnvCommand
2679+ ? commandNeedsAwsMacosPackageManager(runArgs)
2680+ : commandNeedsAwsMacosPackageManager(runArgs, { canShimIgnoreEnvironment: false });
2681+const packageManagerNeeded = scopedEnvCommand?.packageManager || packageManagerFallbackNeeded;
25402682const bunNeeded = scopedEnvCommand?.bun || commandNeedsAwsMacosBun(runArgs);
25412683const runtimeEntrypoint =
25422684scopedEnvCommand?.runtimeEntrypoint || commandRuntimeEntrypoint(runArgs);
@@ -3182,6 +3324,7 @@ let remoteChangedGateBase = "";
31823324const scriptBootstrap = prepareAwsMacosScriptStdinBootstrap(normalizedArgs, provider);
31833325normalizedArgs = scriptBootstrap.args;
31843326const scriptStdinPrepared = scriptBootstrap.prepared;
3327+let wsl2ScriptBootstrap = { args: normalizedArgs, cleanup: () => {}, prepared: false };
31853328try {
31863329if (shouldUseFullCheckoutForCleanRemoteSync(normalizedArgs, provider)) {
31873330const runWords = runCommandArgs(normalizedArgs);
@@ -3212,6 +3355,7 @@ function cleanupOnce() {
32123355}
32133356cleanupDone = true;
32143357stopFullCheckoutKeepalive();
3358+wsl2ScriptBootstrap.cleanup();
32153359scriptBootstrap.cleanup();
32163360preserveTemporaryCrabboxRuns();
32173361cleanupChildCwd();
@@ -3237,6 +3381,14 @@ if (
32373381);
32383382}
32393383}
3384+if (normalizedArgs[0] === "run" && isBrokeredWsl2RemoteTarget(normalizedArgs, provider)) {
3385+const wsl2Requirements = remoteWsl2JsBootstrapRequirements(normalizedArgs);
3386+if (wsl2Requirements.runtimeEntrypoint || wsl2Requirements.packageManager) {
3387+console.error(
3388+`[crabbox] provider=${provider} WSL2 raw boxes may lack Node/Corepack/pnpm for ${wsl2Requirements.runtimeEntrypoint || "package-manager"}; using no-hydrate pinned user-local JavaScript tooling before the command`,
3389+);
3390+}
3391+}
3240339232413393const childEnv = { ...process.env };
32423394if (
@@ -3265,11 +3417,20 @@ const remoteMarkedArgs = injectRemoteChangedGateEnvironment(normalizedArgs);
32653417const remoteMarkedNeedsAwsMacosSwift =
32663418isAwsMacosRemoteTarget(remoteMarkedArgs, provider) &&
32673419commandNeedsAwsMacosSwiftToolchain(runCommandArgs(remoteMarkedArgs));
3420+try {
3421+wsl2ScriptBootstrap = prepareRemoteWsl2JsBootstrapScript(
3422+childCwd === repoRoot ? remoteMarkedArgs : absolutizeLocalRunPaths(remoteMarkedArgs),
3423+provider,
3424+);
3425+} catch (error) {
3426+cleanupOnce();
3427+throw error;
3428+}
32683429const childArgs =
32693430childCwd === repoRoot
32703431 ? injectRemoteWindowsHydratedNodeModulesBootstrap(
32713432injectRemoteAwsMacosSwiftBootstrap(
3272-injectRemoteAwsMacosJsBootstrap(remoteMarkedArgs, provider),
3433+injectRemoteAwsMacosJsBootstrap(wsl2ScriptBootstrap.args, provider),
32733434provider,
32743435remoteMarkedNeedsAwsMacosSwift,
32753436),
@@ -3278,7 +3439,7 @@ const childArgs =
32783439 : injectRemoteChangedGateGitBootstrap(
32793440injectRemoteWindowsHydratedNodeModulesBootstrap(
32803441injectRemoteAwsMacosSwiftBootstrap(
3281-injectRemoteAwsMacosJsBootstrap(absolutizeLocalRunPaths(remoteMarkedArgs), provider),
3442+injectRemoteAwsMacosJsBootstrap(wsl2ScriptBootstrap.args, provider),
32823443provider,
32833444remoteMarkedNeedsAwsMacosSwift,
32843445),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。