

















@@ -1,6 +1,15 @@
11#!/usr/bin/env node
22import { spawn, spawnSync } from "node:child_process";
3-import { accessSync, constants, mkdtempSync, readFileSync, rmSync, statSync } from "node:fs";
3+import {
4+accessSync,
5+chmodSync,
6+constants,
7+mkdtempSync,
8+readFileSync,
9+rmSync,
10+statSync,
11+writeFileSync,
12+} from "node:fs";
413import { tmpdir } from "node:os";
514import { delimiter, dirname, extname, isAbsolute, relative, resolve } from "node:path";
615import { fileURLToPath } from "node:url";
@@ -1156,6 +1165,91 @@ function injectRemoteAwsMacosJsBootstrap(commandArgs, providerName) {
11561165return normalizedArgs;
11571166}
115811671168+function hasRunOption(commandArgs, name) {
1169+if (commandArgs[0] !== "run") {
1170+return false;
1171+}
1172+const { optionEnd } = runCommandBounds(commandArgs);
1173+const normalizedName = name.replace(/^-+/u, "");
1174+for (let index = 1; index < optionEnd; index += 1) {
1175+const arg = commandArgs[index];
1176+if (arg.startsWith("-") && runOptionName(arg) === normalizedName) {
1177+return true;
1178+}
1179+if (!arg.includes("=") && currentRunValueOptions().has(runOptionName(arg))) {
1180+index += 1;
1181+}
1182+}
1183+return false;
1184+}
1185+1186+function replaceRunFlagWithScript(commandArgs, flagName, scriptPath) {
1187+const { optionEnd } = runCommandBounds(commandArgs);
1188+const normalizedName = flagName.replace(/^-+/u, "");
1189+const normalizedArgs = [...commandArgs];
1190+for (let index = 1; index < optionEnd; index += 1) {
1191+const arg = normalizedArgs[index];
1192+if (arg.startsWith("-") && runOptionName(arg) === normalizedName) {
1193+normalizedArgs.splice(index, 1, "--script", scriptPath);
1194+return normalizedArgs;
1195+}
1196+if (!arg.includes("=") && currentRunValueOptions().has(runOptionName(arg))) {
1197+index += 1;
1198+}
1199+}
1200+return normalizedArgs;
1201+}
1202+1203+function prepareAwsMacosScriptStdinBootstrap(commandArgs, providerName) {
1204+if (
1205+!isAwsMacosRemoteTarget(commandArgs, providerName) ||
1206+!hasRunOption(commandArgs, "--script-stdin")
1207+) {
1208+return { args: commandArgs, cleanup: () => {}, prepared: false };
1209+}
1210+1211+const scriptRoot = mkdtempSync(resolve(tmpdir(), "openclaw-crabbox-macos-script-"));
1212+const scriptPath = resolve(scriptRoot, "script.sh");
1213+const script = readFileSync(0, "utf8");
1214+writeFileSync(scriptPath, createAwsMacosScriptStdinWrapper(script), "utf8");
1215+chmodSync(scriptPath, 0o700);
1216+return {
1217+args: replaceRunFlagWithScript(commandArgs, "--script-stdin", scriptPath),
1218+cleanup: () => rmSync(scriptRoot, { recursive: true, force: true }),
1219+prepared: true,
1220+};
1221+}
1222+1223+function createAwsMacosScriptStdinWrapper(script) {
1224+if (!script.startsWith("#!")) {
1225+return `${remoteAwsMacosJsBootstrap()} || exit $?\n${script}`;
1226+}
1227+const delimiter = uniqueHereDocDelimiter(script);
1228+return [
1229+`${remoteAwsMacosJsBootstrap()} || exit $?`,
1230+'tmp_script="$(mktemp "${TMPDIR:-/tmp}/openclaw-crabbox-script.XXXXXX")" || exit $?',
1231+'cleanup_openclaw_crabbox_script() { rm -f "$tmp_script"; }',
1232+"trap cleanup_openclaw_crabbox_script EXIT",
1233+`cat >"$tmp_script" <<'${delimiter}'`,
1234+script.endsWith("\n") ? script.slice(0, -1) : script,
1235+delimiter,
1236+'chmod 700 "$tmp_script" || exit $?',
1237+'"$tmp_script" "$@"',
1238+"",
1239+].join("\n");
1240+}
1241+1242+function uniqueHereDocDelimiter(script) {
1243+let index = 0;
1244+for (;;) {
1245+const delimiter = `OPENCLAW_CRABBOX_SCRIPT_${index}`;
1246+if (!new RegExp(`^${delimiter}$`, "mu").test(script)) {
1247+return delimiter;
1248+}
1249+index += 1;
1250+}
1251+}
1252+11591253function isSparseCheckout() {
11601254const config = gitOutput(["config", "--bool", "core.sparseCheckout"]);
11611255if (config.status === 0 && config.stdout === "true") {
@@ -1320,7 +1414,7 @@ const providers = parseProvidersFromHelp(help.text);
13201414const displayBinary = binary === "crabbox" ? "crabbox" : relative(repoRoot, binary);
13211415const provider = selectedProvider(args);
13221416const commandProviderValue = commandProvider(args);
1323-const normalizedArgs = ensureAwsMacOnDemandMarket(args, provider);
1417+let normalizedArgs = ensureAwsMacOnDemandMarket(args, provider);
1324141813251419console.error(
13261420`[crabbox] bin=${displayBinary} version=${version.text || "unknown"} provider=${provider || "unknown"} providers=${providers.join(",") || "unknown"}`,
@@ -1365,36 +1459,50 @@ let childCwd = repoRoot;
13651459let cleanupChildCwd = () => {};
13661460let cleanupDone = false;
13671461let remoteChangedGateBase = "";
1368-if (shouldUseFullCheckoutForCleanSparseRemoteSync(normalizedArgs, provider)) {
1369-const runWords = runCommandArgs(normalizedArgs);
1370-const changedGateBase = isChangedGateCommand(runWords) ? mergeBaseForChangedGate() : "";
1371-const checkout = prepareFullCheckoutForSync({ changedGateBase });
1372-childCwd = checkout.dir;
1373-cleanupChildCwd = () => checkout.cleanup();
1374-remoteChangedGateBase = checkout.changedGateBase;
1375-console.error(
1376-`[crabbox] sparse clean checkout detected; syncing from temporary full checkout ${checkout.dir}`,
1377-);
1378-if (checkout.changedGateBase) {
1462+let scriptStdinPrepared = false;
1463+const scriptBootstrap = prepareAwsMacosScriptStdinBootstrap(normalizedArgs, provider);
1464+normalizedArgs = scriptBootstrap.args;
1465+scriptStdinPrepared = scriptBootstrap.prepared;
1466+try {
1467+if (shouldUseFullCheckoutForCleanSparseRemoteSync(normalizedArgs, provider)) {
1468+const runWords = runCommandArgs(normalizedArgs);
1469+const changedGateBase = isChangedGateCommand(runWords) ? mergeBaseForChangedGate() : "";
1470+const checkout = prepareFullCheckoutForSync({ changedGateBase });
1471+childCwd = checkout.dir;
1472+cleanupChildCwd = () => checkout.cleanup();
1473+remoteChangedGateBase = checkout.changedGateBase;
13791474console.error(
1380-`[crabbox] remote changed gate detected; overlaying local HEAD as worktree changes from ${checkout.changedGateBase}`,
1475+`[crabbox] sparse clean checkout detected; syncing from temporary full checkout ${checkout.dir}`,
13811476);
1477+if (checkout.changedGateBase) {
1478+console.error(
1479+`[crabbox] remote changed gate detected; overlaying local HEAD as worktree changes from ${checkout.changedGateBase}`,
1480+);
1481+}
13821482}
1483+} catch (error) {
1484+scriptBootstrap.cleanup();
1485+throw error;
13831486}
1384148713851488function cleanupOnce() {
13861489if (cleanupDone) {
13871490return;
13881491}
13891492cleanupDone = true;
1493+scriptBootstrap.cleanup();
13901494cleanupChildCwd();
13911495}
1392149613931497const runtimeEntrypoint = commandRuntimeEntrypoint(runCommandArgs(normalizedArgs));
1394-if (normalizedArgs[0] === "run" && provider === "aws" && runtimeEntrypoint) {
1498+if (
1499+normalizedArgs[0] === "run" &&
1500+provider === "aws" &&
1501+(runtimeEntrypoint || scriptStdinPrepared)
1502+) {
13951503if (isAwsMacosRemoteTarget(normalizedArgs, provider)) {
13961504console.error(
1397-`[crabbox] provider=aws macOS raw boxes may lack Node/Corepack/pnpm for ${runtimeEntrypoint}; bootstrapping a pinned user-local Node toolchain before the command`,
1505+`[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`,
13981506);
13991507} else {
14001508const id = optionValue(normalizedArgs, "--id");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。