- build-usb.sh: one-click USB drive builder (downloads Node.js + OpenClaw from China mirrors, packages into USB-ready directory) - Mac-Install.command: install from USB to Mac (~/.uclaw/), offline-first with China mirror fallback - Windows-Install.bat: same for Windows - README.md rewritten to position project as "USB drive builder toolkit"
263 lines
7.5 KiB
Bash
Executable File
263 lines
7.5 KiB
Bash
Executable File
#!/bin/bash
|
||
# ============================================================
|
||
# U-Claw USB Builder - 一键制作 U 盘
|
||
# 运行后自动下载所有依赖,打包成可直接拷贝到 U 盘的完整目录
|
||
# ============================================================
|
||
|
||
set -e
|
||
|
||
GREEN='\033[0;32m'
|
||
CYAN='\033[0;36m'
|
||
RED='\033[0;31m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m'
|
||
BOLD='\033[1m'
|
||
DIM='\033[2m'
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||
NODE_VER="v22.14.0"
|
||
MIRROR="https://registry.npmmirror.com"
|
||
NODE_MIRROR="https://npmmirror.com/mirrors/node"
|
||
|
||
# Output directory
|
||
OUTPUT_DIR="$REPO_DIR/usb-build"
|
||
USB_DIR="$OUTPUT_DIR/U-Claw"
|
||
|
||
clear
|
||
echo ""
|
||
echo -e "${CYAN}${BOLD}"
|
||
echo " ╔══════════════════════════════════════╗"
|
||
echo " ║ U-Claw USB Builder ║"
|
||
echo " ║ 一键制作 U 盘 ║"
|
||
echo " ╚══════════════════════════════════════╝"
|
||
echo -e "${NC}"
|
||
echo ""
|
||
|
||
# ---- Detect platform ----
|
||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||
ARCH=$(uname -m)
|
||
|
||
echo -e " ${BOLD}系统:${NC} $OS $ARCH"
|
||
echo ""
|
||
|
||
# Ask which platforms to build for
|
||
echo -e " ${BOLD}选择要打包的平台:${NC}"
|
||
echo -e " ${GREEN}[1]${NC} 仅 Mac Apple Silicon (arm64)"
|
||
echo -e " ${GREEN}[2]${NC} 仅 Windows (x64)"
|
||
echo -e " ${GREEN}[3]${NC} Mac + Windows (全部)"
|
||
echo ""
|
||
|
||
if [ -t 0 ]; then
|
||
read -p " 选择 [1-3, 默认 3]: " PLATFORM_CHOICE
|
||
else
|
||
PLATFORM_CHOICE="3"
|
||
fi
|
||
PLATFORM_CHOICE="${PLATFORM_CHOICE:-3}"
|
||
|
||
BUILD_MAC=false
|
||
BUILD_WIN=false
|
||
case $PLATFORM_CHOICE in
|
||
1) BUILD_MAC=true ;;
|
||
2) BUILD_WIN=true ;;
|
||
*) BUILD_MAC=true; BUILD_WIN=true ;;
|
||
esac
|
||
|
||
echo ""
|
||
|
||
# ---- Clean previous build ----
|
||
if [ -d "$USB_DIR" ]; then
|
||
echo -e " ${YELLOW}清理上次构建...${NC}"
|
||
rm -rf "$USB_DIR"
|
||
fi
|
||
mkdir -p "$USB_DIR"
|
||
|
||
# ---- Step 1: Copy scripts and HTML ----
|
||
echo -e " ${BOLD}[1/5] 复制脚本和页面...${NC}"
|
||
|
||
# Copy all launch scripts and HTML pages
|
||
for f in Mac-Start.command Mac-Menu.command Windows-Start.bat Windows-Menu.bat \
|
||
Config.html U-Claw.html SkillHub.html default-config.json migrate.js setup.sh; do
|
||
if [ -f "$SCRIPT_DIR/$f" ]; then
|
||
cp "$SCRIPT_DIR/$f" "$USB_DIR/"
|
||
echo -e " ${DIM} + $f${NC}"
|
||
fi
|
||
done
|
||
|
||
# Make scripts executable
|
||
chmod +x "$USB_DIR"/*.command 2>/dev/null || true
|
||
chmod +x "$USB_DIR"/*.sh 2>/dev/null || true
|
||
|
||
echo -e " ${GREEN}脚本复制完成 ✓${NC}"
|
||
echo ""
|
||
|
||
# ---- Step 2: Create data directory structure ----
|
||
echo -e " ${BOLD}[2/5] 创建数据目录...${NC}"
|
||
|
||
mkdir -p "$USB_DIR/data/.openclaw"
|
||
mkdir -p "$USB_DIR/data/memory"
|
||
mkdir -p "$USB_DIR/data/backups"
|
||
|
||
# Default config
|
||
cat > "$USB_DIR/data/.openclaw/openclaw.json" << 'CFGEOF'
|
||
{
|
||
"gateway": {
|
||
"mode": "local",
|
||
"auth": { "token": "uclaw" }
|
||
}
|
||
}
|
||
CFGEOF
|
||
|
||
echo -e " ${GREEN}数据目录创建完成 ✓${NC}"
|
||
echo ""
|
||
|
||
# ---- Step 3: Download Node.js runtimes ----
|
||
echo -e " ${BOLD}[3/5] 下载 Node.js 运行时...${NC}"
|
||
|
||
download_node() {
|
||
local PLATFORM=$1
|
||
local TARGET_DIR=$2
|
||
|
||
if [ -d "$TARGET_DIR" ] && [ -f "$TARGET_DIR/bin/node" -o -f "$TARGET_DIR/node.exe" ]; then
|
||
echo -e " ${GREEN}$PLATFORM 已存在,跳过${NC}"
|
||
return
|
||
fi
|
||
|
||
mkdir -p "$TARGET_DIR"
|
||
|
||
if echo "$PLATFORM" | grep -q "win"; then
|
||
local ZIPNAME="node-${NODE_VER}-${PLATFORM}.zip"
|
||
local URL="${NODE_MIRROR}/${NODE_VER}/${ZIPNAME}"
|
||
echo -e " ${CYAN}下载 $ZIPNAME...${NC}"
|
||
curl -# -L "$URL" -o "/tmp/$ZIPNAME"
|
||
|
||
# Unzip
|
||
local TMPEXTRACT="/tmp/node-extract-$$"
|
||
mkdir -p "$TMPEXTRACT"
|
||
unzip -q "/tmp/$ZIPNAME" -d "$TMPEXTRACT"
|
||
cp -R "$TMPEXTRACT"/node-${NODE_VER}-${PLATFORM}/* "$TARGET_DIR/"
|
||
rm -rf "$TMPEXTRACT" "/tmp/$ZIPNAME"
|
||
else
|
||
local TARBALL="node-${NODE_VER}-${PLATFORM}.tar.gz"
|
||
local URL="${NODE_MIRROR}/${NODE_VER}/${TARBALL}"
|
||
echo -e " ${CYAN}下载 $TARBALL...${NC}"
|
||
curl -# -L "$URL" -o "/tmp/$TARBALL"
|
||
tar -xzf "/tmp/$TARBALL" -C "$TARGET_DIR" --strip-components=1
|
||
rm -f "/tmp/$TARBALL"
|
||
chmod +x "$TARGET_DIR/bin/node"
|
||
fi
|
||
|
||
echo -e " ${GREEN}$PLATFORM 下载完成 ✓${NC}"
|
||
}
|
||
|
||
RUNTIME_DIR="$USB_DIR/app/runtime"
|
||
mkdir -p "$RUNTIME_DIR"
|
||
|
||
if $BUILD_MAC; then
|
||
download_node "darwin-arm64" "$RUNTIME_DIR/node-mac-arm64"
|
||
fi
|
||
|
||
if $BUILD_WIN; then
|
||
download_node "win-x64" "$RUNTIME_DIR/node-win-x64"
|
||
fi
|
||
|
||
echo ""
|
||
|
||
# ---- Step 4: Install OpenClaw + plugins ----
|
||
echo -e " ${BOLD}[4/5] 安装 OpenClaw + QQ 插件...${NC}"
|
||
|
||
CORE_DIR="$USB_DIR/app/core"
|
||
mkdir -p "$CORE_DIR"
|
||
|
||
# Determine which Node.js to use for npm install
|
||
if $BUILD_MAC && [ -f "$RUNTIME_DIR/node-mac-arm64/bin/node" ]; then
|
||
INSTALL_NODE="$RUNTIME_DIR/node-mac-arm64/bin/node"
|
||
INSTALL_NPM="$RUNTIME_DIR/node-mac-arm64/bin/npm"
|
||
elif command -v node >/dev/null 2>&1; then
|
||
INSTALL_NODE="node"
|
||
INSTALL_NPM="npm"
|
||
else
|
||
echo -e " ${RED}没有可用的 Node.js,无法安装依赖${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Create package.json
|
||
cat > "$CORE_DIR/package.json" << 'PKGEOF'
|
||
{
|
||
"name": "u-claw-core",
|
||
"version": "1.0.0",
|
||
"private": true,
|
||
"dependencies": {
|
||
"openclaw": "latest"
|
||
}
|
||
}
|
||
PKGEOF
|
||
|
||
echo -e " ${CYAN}安装 OpenClaw (国内镜像)...${NC}"
|
||
cd "$CORE_DIR"
|
||
"$INSTALL_NODE" "$INSTALL_NPM" install --registry="$MIRROR" 2>&1 | tail -3
|
||
|
||
# Install QQ plugin
|
||
echo -e " ${CYAN}安装 QQ 插件...${NC}"
|
||
"$INSTALL_NODE" "$INSTALL_NPM" install @sliverp/qqbot@latest --registry="$MIRROR" 2>&1 | tail -2
|
||
|
||
echo -e " ${GREEN}OpenClaw + QQ 插件安装完成 ✓${NC}"
|
||
echo ""
|
||
|
||
# ---- Step 5: Calculate size and finish ----
|
||
echo -e " ${BOLD}[5/5] 完成!${NC}"
|
||
echo ""
|
||
|
||
USB_SIZE=$(du -sh "$USB_DIR" | cut -f1)
|
||
FILE_COUNT=$(find "$USB_DIR" -type f | wc -l | tr -d ' ')
|
||
|
||
echo -e " ${GREEN}${BOLD}╔══════════════════════════════════════════╗"
|
||
echo -e " ║ ✅ U 盘制作完成! ║"
|
||
echo -e " ╚══════════════════════════════════════════╝${NC}"
|
||
echo ""
|
||
echo -e " ${BOLD}输出目录:${NC} $USB_DIR"
|
||
echo -e " ${BOLD}总大小:${NC} $USB_SIZE"
|
||
echo -e " ${BOLD}文件数:${NC} $FILE_COUNT"
|
||
echo ""
|
||
|
||
if $BUILD_MAC; then
|
||
echo -e " ${GREEN}✓${NC} Mac Apple Silicon (arm64)"
|
||
fi
|
||
if $BUILD_WIN; then
|
||
echo -e " ${GREEN}✓${NC} Windows x64"
|
||
fi
|
||
echo ""
|
||
|
||
echo -e " ${BOLD}接下来:${NC}"
|
||
echo ""
|
||
echo -e " ${CYAN}1. 插入 U 盘(建议 4GB 以上)${NC}"
|
||
echo -e " ${CYAN}2. 复制到 U 盘:${NC}"
|
||
echo ""
|
||
echo -e " ${BOLD}Mac:${NC}"
|
||
echo -e " cp -R $USB_DIR /Volumes/你的U盘/"
|
||
echo ""
|
||
echo -e " ${BOLD}或者用 Finder:${NC}"
|
||
echo -e " 直接把 ${BOLD}U-Claw${NC} 文件夹拖到 U 盘"
|
||
echo ""
|
||
echo -e " ${CYAN}3. 在目标电脑上:${NC}"
|
||
echo -e " Mac: 双击 ${BOLD}Mac-Start.command${NC}"
|
||
echo -e " Win: 双击 ${BOLD}Windows-Start.bat${NC}"
|
||
echo ""
|
||
|
||
# Optional: create tar.gz
|
||
if [ -t 0 ]; then
|
||
read -p " 是否也打包成 tar.gz 方便分发?(y/n): " -n 1 PACK
|
||
echo ""
|
||
if [ "$PACK" = "y" ] || [ "$PACK" = "Y" ]; then
|
||
echo ""
|
||
echo -e " ${CYAN}打包中...${NC}"
|
||
cd "$OUTPUT_DIR"
|
||
tar -czf "U-Claw.tar.gz" "U-Claw/"
|
||
PACK_SIZE=$(du -sh "$OUTPUT_DIR/U-Claw.tar.gz" | cut -f1)
|
||
echo -e " ${GREEN}打包完成: $OUTPUT_DIR/U-Claw.tar.gz ($PACK_SIZE)${NC}"
|
||
fi
|
||
fi
|
||
|
||
echo ""
|
||
echo -e " ${DIM}完成!${NC}"
|