Files
NetMesh/scripts/prepare-ai-research-input.sh
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

133 lines
5.1 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
input_path="${1:?input path is required}"
research_dir="${2:?research directory is required}"
attachment_urls_path="$research_dir/attachment-urls.json"
node -e '
const fs = require("node:fs");
const auto = require(process.env.RUNNER_TEMP + "/ai-automation.cjs");
const input = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
const urls = auto.extractGithubUserAttachmentAssetUrls(input);
fs.writeFileSync(process.argv[2], JSON.stringify(urls) + "\n");
' "$input_path" "$attachment_urls_path"
attachment_count="$(node -p 'require(process.argv[1]).length' "$attachment_urls_path")"
if (( attachment_count > 4 )); then
echo "Too many GitHub image attachments for bounded research: ${attachment_count}" >&2
exit 1
fi
if (( attachment_count == 0 )); then
cp "$input_path" "$research_dir/input.json"
exit 0
fi
mkdir -p "$research_dir/attachments"
attachment_kinds_path="$research_dir/attachment-kinds.txt"
: > "$attachment_kinds_path"
image_count=0
for (( index=0; index<attachment_count; index++ )); do
source_url="$(node -e '
process.stdout.write(require(process.argv[1])[Number(process.argv[2])]);
' "$attachment_urls_path" "$index")"
headers_path="$(mktemp "${RUNNER_TEMP}/ai-attachment-headers.XXXXXX")"
curl --proto '=https' --tlsv1.2 --retry 3 --retry-all-errors \
--connect-timeout 3 --max-time 20 --max-redirs 0 -fsS \
-D "$headers_path" -o /dev/null "$source_url"
kind="$(node -e '
const fs = require("node:fs");
const auto = require(process.env.RUNNER_TEMP + "/ai-automation.cjs");
process.stdout.write(auto.classifyGithubUserAttachmentRedirect(
fs.readFileSync(process.argv[1], "utf8"),
));
' "$headers_path")"
rm -f "$headers_path"
if [[ "$kind" != "image" && "$kind" != "unsupported_media" ]]; then
echo "GitHub attachment did not provide a trusted image/video/audio redirect." >&2
exit 1
fi
printf '%s\n' "$kind" >> "$attachment_kinds_path"
if [[ "$kind" == "image" ]]; then
image_count=$((image_count + 1))
fi
done
container_name="ai-research-imgproxy-${GITHUB_RUN_ID}-${GITHUB_JOB}"
if (( image_count > 0 )); then
docker run -d --rm --name "$container_name" \
--cap-drop=ALL --security-opt=no-new-privileges --read-only \
--memory=512m --cpus=1 --pids-limit=128 \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
-p 127.0.0.1:18081:8080 \
-e IMGPROXY_ALLOWED_SOURCES=https://github.com/user-attachments/assets/ \
-e IMGPROXY_ALLOW_LOOPBACK_SOURCE_ADDRESSES=false \
-e IMGPROXY_ALLOW_LINK_LOCAL_SOURCE_ADDRESSES=false \
-e IMGPROXY_ALLOW_PRIVATE_SOURCE_ADDRESSES=false \
-e IMGPROXY_MAX_SRC_FILE_SIZE=10485760 \
-e IMGPROXY_MAX_SRC_RESOLUTION=50 \
-e IMGPROXY_MAX_RESULT_DIMENSION=4096 \
-e IMGPROXY_MAX_REDIRECTS=2 \
-e IMGPROXY_MAX_ANIMATION_FRAMES=1 \
-e IMGPROXY_ALWAYS_RASTERIZE_SVG=true \
-e IMGPROXY_ALLOW_SECURITY_OPTIONS=false \
-e IMGPROXY_COOKIE_PASSTHROUGH=false \
-e IMGPROXY_COOKIE_PASSTHROUGH_ALL=false \
"$AI_RESEARCH_IMGPROXY_IMAGE" >/dev/null
fi
stop_imgproxy() {
if (( image_count > 0 )); then
docker stop "$container_name" >/dev/null 2>&1 || true
fi
}
trap stop_imgproxy EXIT
for (( index=0; index<attachment_count; index++ )); do
kind="$(sed -n "$((index + 1))p" "$attachment_kinds_path")"
if [[ "$kind" != "image" ]]; then
continue
fi
source_url="$(node -e '
process.stdout.write(require(process.argv[1])[Number(process.argv[2])]);
' "$attachment_urls_path" "$index")"
encoded_source="$(node -e '
process.stdout.write(Buffer.from(process.argv[1]).toString("base64url"));
' "$source_url")"
output_path="$research_dir/attachments/issue-image-$((index + 1)).png"
curl --retry 8 --retry-all-errors --retry-delay 1 --retry-max-time 45 \
--connect-timeout 3 --max-time 30 -fsS \
"http://127.0.0.1:18081/unsafe/${encoded_source}.png" \
-o "$output_path"
node -e '
const fs = require("node:fs");
const expected = Buffer.from("89504e470d0a1a0a", "hex");
const actual = fs.readFileSync(process.argv[1]).subarray(0, expected.length);
if (!actual.equals(expected)) throw new Error("imgproxy did not produce PNG output");
' "$output_path"
done
stop_imgproxy
trap - EXIT
# The single-quoted program intentionally contains JavaScript template syntax.
# shellcheck disable=SC2016
node -e '
const fs = require("node:fs");
const auto = require(process.env.RUNNER_TEMP + "/ai-automation.cjs");
const input = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
const urls = require(process.argv[2]);
const kinds = fs.readFileSync(process.argv[3], "utf8").trim().split("\n");
const attachments = urls.map((sourceUrl, index) => ({
sourceUrl,
kind: kinds[index],
...(kinds[index] === "image"
? { relativePath: `attachments/issue-image-${index + 1}.png` }
: {}),
}));
fs.writeFileSync(
process.argv[4],
JSON.stringify(auto.rewriteExternalResearchInputAttachments(input, attachments), null, 2) + "\n",
);
' "$input_path" "$attachment_urls_path" "$attachment_kinds_path" "$research_dir/input.json"
rm -f "$attachment_urls_path" "$attachment_kinds_path"