
























@@ -141,6 +141,14 @@ const jsRuntimeEntrypoints = new Set([
141141const awsMacosCorepackEntrypoints = new Set(["pnpm", "yarn", "corepack"]);
142142const awsMacosBunEntrypoints = new Set(["bun", "bunx"]);
143143const awsMacosBunVersion = "1.3.14";
144+const awsMacosSwiftEntrypoints = new Set(["swift", "xcodebuild"]);
145+const awsMacosSwiftScriptTargets = new Set([
146+"mac:package",
147+"mac:restart",
148+"scripts/build-and-run-mac.sh",
149+"scripts/package-mac-app.sh",
150+"scripts/restart-mac.sh",
151+]);
144152const minimumBlacksmithCrabboxVersion = [0, 22, 0];
145153const shellControlCommandPrefixes = new Set([
146154"if",
@@ -955,6 +963,89 @@ function commandNeedsAwsMacosBun(commandArgs) {
955963return commandNeedsEntrypoint(commandArgs, awsMacosBunEntrypoints);
956964}
957965966+function commandNeedsAwsMacosSwiftToolchain(commandArgs) {
967+if (commandArgs.length === 1) {
968+return shellCommandWordCandidates(commandArgs[0]).some(commandWordsNeedAwsMacosSwiftToolchain);
969+}
970+return commandWordsNeedAwsMacosSwiftToolchain(normalizedCommandWords(commandArgs));
971+}
972+973+function commandWordsNeedAwsMacosSwiftToolchain(wordsInput) {
974+let words = wordsInput;
975+words = normalizeExecutableWords(words);
976+const first = (words[0] ?? "").split("/").pop();
977+if (isSupportedSystemEnvCommand(first)) {
978+const targetWords = [...words];
979+if (stripEnvCommandOptions(targetWords, { canShimIgnoreEnvironment: true })) {
980+return commandWordsNeedAwsMacosSwiftToolchain(targetWords);
981+}
982+}
983+if (awsMacosSwiftEntrypoints.has(first)) {
984+return true;
985+}
986+987+if (first === "pnpm") {
988+const scriptName = words[1] === "run" ? words[2] : words[1];
989+if (awsMacosSwiftScriptTargets.has(scriptName)) {
990+return true;
991+}
992+}
993+994+if (isAwsMacosSwiftScriptTarget(words[0])) {
995+return true;
996+}
997+998+if (commandWordsRunAwsMacosSwiftScript(words)) {
999+return true;
1000+}
1001+1002+const inlineCommand = shellInlineCommand(words);
1003+if (!inlineCommand) {
1004+return false;
1005+}
1006+return shellCommandWordCandidates(inlineCommand).some(commandWordsNeedAwsMacosSwiftToolchain);
1007+}
1008+1009+function isAwsMacosSwiftScriptTarget(word) {
1010+if (!word) {
1011+return false;
1012+}
1013+const normalized = word.replace(/^\.\//u, "");
1014+return (
1015+awsMacosSwiftScriptTargets.has(normalized) ||
1016+awsMacosSwiftScriptTargets.has(normalized.split("/").pop() ?? "")
1017+);
1018+}
1019+1020+function commandWordsRunAwsMacosSwiftScript(words) {
1021+const first = (words[0] ?? "").split("/").pop();
1022+if (!shellInlineCommandInterpreters.has(first)) {
1023+return false;
1024+}
1025+1026+for (let index = 1; index < words.length; index += 1) {
1027+const word = words[index] ?? "";
1028+if (!word) {
1029+return false;
1030+}
1031+if (word === "--") {
1032+continue;
1033+}
1034+if (word === "-c" || /^-[^-]*c/u.test(word)) {
1035+return false;
1036+}
1037+if (shellInlineCommandOptionConsumesNextValue(word)) {
1038+index += 1;
1039+continue;
1040+}
1041+if (word.startsWith("-") || word.startsWith("+")) {
1042+continue;
1043+}
1044+return isAwsMacosSwiftScriptTarget(word);
1045+}
1046+return false;
1047+}
1048+9581049function commandNeedsEntrypoint(commandArgs, entrypoints) {
9591050if (commandArgs.length === 1) {
9601051return shellCommandWordCandidates(commandArgs[0]).some((words) =>
@@ -2078,6 +2169,62 @@ function injectRemoteAwsMacosJsBootstrap(commandArgs, providerName) {
20782169return normalizedArgs;
20792170}
208021712172+function remoteAwsMacosSwiftBootstrap() {
2173+return [
2174+"openclaw_crabbox_require_macos_swift_62() {",
2175+'openclaw_xcode="";',
2176+'for openclaw_candidate in /Applications/Xcode_26.1.app /Applications/Xcode_26*.app /Applications/Xcode-26*.app; do if [ -d "$openclaw_candidate" ]; then openclaw_xcode="$openclaw_candidate"; fi; done;',
2177+'if [ -n "$openclaw_xcode" ]; then openclaw_developer="$openclaw_xcode/Contents/Developer"; if [ ! -d "$openclaw_developer" ]; then openclaw_developer="$openclaw_xcode"; fi; sudo xcode-select -s "$openclaw_developer" || return 1; fi;',
2178+'openclaw_swift_version="$(swift --version 2>&1)" || { status=$?; printf "%s\\n" "$openclaw_swift_version" >&2; return "$status"; };',
2179+'printf "%s\\n" "$openclaw_swift_version" >&2;',
2180+'openclaw_swift_major_minor="$(printf "%s\\n" "$openclaw_swift_version" | sed -nE "s/.*Apple Swift version ([0-9]+)\\.([0-9]+).*/\\1 \\2/p" | head -n 1)";',
2181+'if [ -z "$openclaw_swift_major_minor" ]; then echo "[crabbox] OpenClaw macOS app proof requires Swift tools 6.2+; unable to parse swift --version." >&2; return 2; fi;',
2182+"set -- $openclaw_swift_major_minor;",
2183+'if [ "$1" -lt 6 ] || { [ "$1" -eq 6 ] && [ "$2" -lt 2 ]; }; then',
2184+'echo "[crabbox] OpenClaw macOS app proof requires Swift tools 6.2+ (Xcode 26.x)." >&2;',
2185+'echo "[crabbox] current Swift is $1.$2; select/install Xcode 26.x or use a Blacksmith macOS runner with Xcode_26.1.app." >&2;',
2186+"return 2;",
2187+"fi;",
2188+"};",
2189+"openclaw_crabbox_require_macos_swift_62",
2190+].join(" ");
2191+}
2192+2193+function injectRemoteAwsMacosSwiftBootstrap(commandArgs, providerName, force = false) {
2194+const runArgs = runCommandArgs(commandArgs);
2195+if (
2196+!isAwsMacosRemoteTarget(commandArgs, providerName) ||
2197+(!force && !commandNeedsAwsMacosSwiftToolchain(runArgs))
2198+) {
2199+return commandArgs;
2200+}
2201+2202+const { start, optionEnd } = runCommandBounds(commandArgs);
2203+if (start < 0) {
2204+return commandArgs;
2205+}
2206+2207+const normalizedArgs = [...commandArgs];
2208+const remoteCommand = normalizedArgs.slice(start);
2209+const originalShellCommand =
2210+hasOption(normalizedArgs, "--shell") && remoteCommand.length === 1
2211+ ? remoteCommand[0]
2212+ : shellJoin(remoteCommand);
2213+const shellCommand = `${remoteAwsMacosSwiftBootstrap()} && { ${originalShellCommand}\n}`;
2214+2215+if (!hasOption(normalizedArgs, "--shell")) {
2216+normalizedArgs.splice(optionEnd, 0, "--shell");
2217+}
2218+2219+const updatedBounds = runCommandBounds(normalizedArgs);
2220+normalizedArgs.splice(
2221+updatedBounds.start,
2222+normalizedArgs.length - updatedBounds.start,
2223+shellCommand,
2224+);
2225+return normalizedArgs;
2226+}
2227+20812228function hasRunOption(commandArgs, name) {
20822229if (commandArgs[0] !== "run") {
20832230return false;
@@ -2136,11 +2283,11 @@ function prepareAwsMacosScriptStdinBootstrap(commandArgs, providerName) {
21362283function createAwsMacosScriptStdinWrapper(script) {
21372284const requirements = awsMacosScriptBootstrapRequirements(script);
21382285if (!script.startsWith("#!")) {
2139-return `${remoteAwsMacosJsBootstrap(requirements)} || exit $?\n${script}`;
2286+return `${remoteAwsMacosScriptBootstrap(requirements)} || exit $?\n${script}`;
21402287}
21412288const delimiterValue = uniqueHereDocDelimiter(script);
21422289return [
2143-`${remoteAwsMacosJsBootstrap(requirements)} || exit $?`,
2290+`${remoteAwsMacosScriptBootstrap(requirements)} || exit $?`,
21442291'tmp_script="$(mktemp "${TMPDIR:-/tmp}/openclaw-crabbox-script.XXXXXX")" || exit $?',
21452292'cleanup_openclaw_crabbox_script() { rm -f "$tmp_script"; }',
21462293"trap cleanup_openclaw_crabbox_script EXIT",
@@ -2153,22 +2300,33 @@ function createAwsMacosScriptStdinWrapper(script) {
21532300].join("\n");
21542301}
215523022303+function remoteAwsMacosScriptBootstrap(requirements) {
2304+const bootstraps = [remoteAwsMacosJsBootstrap(requirements)];
2305+if (requirements.swift) {
2306+bootstraps.push(remoteAwsMacosSwiftBootstrap());
2307+}
2308+return bootstraps.join(" && ");
2309+}
2310+21562311function awsMacosScriptBootstrapRequirements(script) {
2157-const requirements = { packageManager: false, bun: false };
2312+const requirements = { packageManager: false, bun: false, swift: false };
21582313const firstLine = script.match(/^[^\r\n]*/u)?.[0] ?? "";
21592314if (firstLine.startsWith("#!")) {
21602315const words = firstLine.slice(2).trim().split(/\s+/u).filter(Boolean);
21612316requirements.packageManager = commandWordsNeedEntrypoint(words, awsMacosCorepackEntrypoints);
21622317requirements.bun = commandWordsNeedEntrypoint(words, awsMacosBunEntrypoints);
2318+requirements.swift = commandWordsNeedAwsMacosSwiftToolchain(words);
21632319if (commandWordsShellEntrypoint(words)) {
21642320const body = script.slice(firstLine.length).replace(/^\r?\n/u, "");
21652321requirements.packageManager ||= commandNeedsAwsMacosPackageManager([body]);
21662322requirements.bun ||= commandNeedsAwsMacosBun([body]);
2323+requirements.swift ||= commandNeedsAwsMacosSwiftToolchain([body]);
21672324}
21682325return requirements;
21692326}
21702327requirements.packageManager = commandNeedsAwsMacosPackageManager([script]);
21712328requirements.bun = commandNeedsAwsMacosBun([script]);
2329+requirements.swift = commandNeedsAwsMacosSwiftToolchain([script]);
21722330return requirements;
21732331}
21742332@@ -2677,15 +2835,26 @@ if (
26772835}
2678283626792837const remoteMarkedArgs = injectRemoteChangedGateEnvironment(normalizedArgs);
2838+const remoteMarkedNeedsAwsMacosSwift =
2839+isAwsMacosRemoteTarget(remoteMarkedArgs, provider) &&
2840+commandNeedsAwsMacosSwiftToolchain(runCommandArgs(remoteMarkedArgs));
26802841const childArgs =
26812842childCwd === repoRoot
26822843 ? injectRemoteWindowsHydratedNodeModulesBootstrap(
2683-injectRemoteAwsMacosJsBootstrap(remoteMarkedArgs, provider),
2844+injectRemoteAwsMacosSwiftBootstrap(
2845+injectRemoteAwsMacosJsBootstrap(remoteMarkedArgs, provider),
2846+provider,
2847+remoteMarkedNeedsAwsMacosSwift,
2848+),
26842849provider,
26852850)
26862851 : injectRemoteChangedGateGitBootstrap(
26872852injectRemoteWindowsHydratedNodeModulesBootstrap(
2688-injectRemoteAwsMacosJsBootstrap(absolutizeLocalRunPaths(remoteMarkedArgs), provider),
2853+injectRemoteAwsMacosSwiftBootstrap(
2854+injectRemoteAwsMacosJsBootstrap(absolutizeLocalRunPaths(remoteMarkedArgs), provider),
2855+provider,
2856+remoteMarkedNeedsAwsMacosSwift,
2857+),
26892858provider,
26902859),
26912860remoteChangedGateBase,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。