|
#!/usr/bin/env bash |
|
set -euo pipefail |
|
|
|
PACKAGE="agent-browser" |
|
PREFIX="${PREFIX:-$HOME/.local}" |
|
VERSION="${VERSION:-}" |
|
|
|
die() { |
|
echo "error: $*" >&2 |
|
exit 1 |
|
} |
|
|
|
for cmd in curl tar sed uname; do |
|
command -v "$cmd" >/dev/null 2>&1 || die "$cmd is required" |
|
done |
|
|
|
# Resolve latest npm version unless explicitly specified. |
|
if [[ -z "$VERSION" ]]; then |
|
echo "Resolving latest $PACKAGE version..." |
|
VERSION="$( |
|
curl -fsSL "https://registry.npmjs.org/$PACKAGE/latest" | |
|
sed -n 's/.*"version":"\([^"]*\)".*/\1/p' |
|
)" |
|
[[ -n "$VERSION" ]] || die "failed to determine latest version" |
|
fi |
|
|
|
VERSION="${VERSION#v}" |
|
|
|
# Detect platform. |
|
case "$(uname -s)" in |
|
Linux*) |
|
os="linux" |
|
;; |
|
Darwin*) |
|
os="darwin" |
|
;; |
|
MINGW*|MSYS*|CYGWIN*) |
|
os="win32" |
|
;; |
|
*) |
|
die "unsupported OS: $(uname -s)" |
|
;; |
|
esac |
|
|
|
# Detect architecture. |
|
case "$(uname -m)" in |
|
x86_64|amd64) |
|
arch="x64" |
|
;; |
|
arm64|aarch64) |
|
if [[ "$os" == "win32" ]]; then |
|
# Upstream currently uses x64 on Windows ARM64. |
|
arch="x64" |
|
else |
|
arch="arm64" |
|
fi |
|
;; |
|
*) |
|
die "unsupported architecture: $(uname -m)" |
|
;; |
|
esac |
|
|
|
# Detect musl. |
|
if [[ "$os" == "linux" ]] && |
|
{ ldd --version 2>&1 || true; } | grep -qi musl; then |
|
os="linux-musl" |
|
fi |
|
|
|
if [[ "$os" == "win32" ]]; then |
|
binary="agent-browser-${os}-${arch}.exe" |
|
link_name="agent-browser.exe" |
|
else |
|
binary="agent-browser-${os}-${arch}" |
|
link_name="agent-browser" |
|
fi |
|
|
|
root="$PREFIX/lib/agent-browser/$VERSION" |
|
bindir="$PREFIX/bin" |
|
link="$bindir/$link_name" |
|
|
|
tmp="$(mktemp -d)" |
|
trap 'rm -rf "$tmp"' EXIT |
|
|
|
url="https://registry.npmjs.org/$PACKAGE/-/$PACKAGE-$VERSION.tgz" |
|
|
|
echo "Installing $PACKAGE $VERSION" |
|
echo " platform: $os-$arch" |
|
echo " prefix: $PREFIX" |
|
echo |
|
|
|
echo "Downloading $url" |
|
curl -fL "$url" -o "$tmp/package.tgz" |
|
|
|
mkdir -p "$tmp/unpacked" |
|
tar -xzf "$tmp/package.tgz" -C "$tmp/unpacked" |
|
|
|
package="$tmp/unpacked/package" |
|
|
|
[[ -d "$package" ]] || |
|
die "invalid npm package" |
|
[[ -f "$package/bin/$binary" ]] || |
|
die "package does not contain bin/$binary" |
|
[[ -d "$package/skills" ]] || |
|
die "package does not contain skills/" |
|
[[ -d "$package/skill-data" ]] || |
|
die "package does not contain skill-data/" |
|
|
|
# ----- Cleanup ----- |
|
|
|
# bin/: retain only our native executable. |
|
find "$package/bin" -mindepth 1 -maxdepth 1 \ |
|
! -name "$binary" \ |
|
-exec rm -rf {} + |
|
|
|
# Node/build/source-only content. |
|
rm -rf \ |
|
"$package/scripts" \ |
|
"$package/cli" |
|
|
|
# Keep these: |
|
# bin/<native binary> |
|
# skills/ |
|
# skill-data/ |
|
# LICENSE |
|
# README.md |
|
# package.json |
|
# |
|
# package.json is tiny and useful as installation metadata. |
|
|
|
# ----- Install ----- |
|
|
|
mkdir -p "$(dirname "$root")" |
|
rm -rf "$root" |
|
mv "$package" "$root" |
|
|
|
if [[ "$os" != "win32" ]]; then |
|
chmod +x "$root/bin/$binary" |
|
fi |
|
|
|
mkdir -p "$bindir" |
|
|
|
# Remove remnants of previous versions/install attempts. |
|
rm -f \ |
|
"$bindir/agent-browser" \ |
|
"$bindir/agent-browser.exe" |
|
|
|
if [[ "$os" == "win32" ]]; then |
|
export MSYS="${MSYS:+$MSYS }winsymlinks:nativestrict" |
|
fi |
|
rm -f "$link" |
|
ln -s "$root/bin/$binary" "$link" |
|
|
|
echo |
|
echo "Installed:" |
|
echo " package: $root" |
|
echo " binary: $root/bin/$binary" |
|
echo " command: $link" |
|
echo |
|
|
|
"$link" --version |
|
|
|
case ":$PATH:" in |
|
*":$bindir:"*) ;; |
|
*) |
|
echo |
|
echo "Note: $bindir is not in PATH." |
|
echo "Add:" |
|
echo " export PATH=\"$bindir:\$PATH\"" |
|
;; |
|
esac |