test / scripts /main.sh
GGSheng's picture
feat: deploy Gemma 4 to hf space
55ba4a3 verified
#!/usr/bin/env bash
# ============================================================
# OpenClaw 工具箱 — 本地开发工具集
#
# 交互式菜单,选择要执行的功能。
# 也支持命令行直接调用:./main.sh <命令> [参数...]
#
# 命令列表:
# bootstrap 交互式部署 OpenClaw 到 HF Space
# rebuild-space 推送代码到 Space 并触发重建
# restart-space 重启 Space
# pause-space 暂停 Space
# factory-rebuild Factory 重建 Space(删除重建)
# cleanup 批量清理 Dataset 中的旧备份
# find-backup 查找最佳备份(可选清理旧备份)
# rm-hf 删除 HF 仓库/文件/存储
# storage HF 存储工具(上传/下载/同步)
# ============================================================
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)"
# ---- 检测 uv 并设置 Python 命令 ----
if command -v uv &>/dev/null && [[ -f "$REPO_ROOT/pyproject.toml" ]]; then
PYTHON="uv run python3"
else
PYTHON="python3"
fi
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
info() { printf "${GREEN}%s${NC}\n" "$*"; }
warn() { printf "${YELLOW}%s${NC}\n" "$*" >&2; }
error() { printf "${RED}%s${NC}\n" "$*" >&2; }
title() { printf "\n${CYAN}${BOLD}%s${NC}\n" "$*"; }
# ============================================================
# 命令实现
# ============================================================
cmd_bootstrap() {
info "▶ 启动交互式部署引导..."
exec "$SCRIPT_DIR/bootstrap-hf.sh"
}
cmd_rebuild() {
if [ $# -gt 0 ]; then
exec "$SCRIPT_DIR/rebuild-space.sh" "$@"
fi
read -r -p "Space ID (如 GGSheng/page): " repo
read -r -p "HF_TOKEN (留空从文件读取): " token
exec "$SCRIPT_DIR/rebuild-space.sh" "${repo}" ${token:+"$token"}
}
cmd_cleanup() {
if [ $# -gt 1 ]; then
exec "$SCRIPT_DIR/delete-backups.sh" "$@"
fi
read -r -p "Dataset ID (如 GGSheng/page-backup): " repo
read -r -p "删除此日期及更早的备份 (YYYYMMDD): " date
read -r -p "HF_TOKEN (留空从文件读取): " token
exec "$SCRIPT_DIR/delete-backups.sh" "${repo}" "${date}" ${token:+"$token"}
}
cmd_find_backup() {
if [ $# -gt 0 ]; then
exec $PYTHON "$SCRIPT_DIR/find-largest-backup.py" "$@"
fi
read -r -p "Dataset ID (如 GGSheng/page-backup): " repo
shift_args=()
read -r -p "详细模式? (y/n, 默认 n): " verbose
[[ "$verbose" == "y" ]] && shift_args+=("--verbose")
read -r -p "找到最佳备份后清理旧备份? (y/n, 默认 n): " del
[[ "$del" == "y" ]] && shift_args+=("--delete-before")
exec $PYTHON "$SCRIPT_DIR/find-largest-backup.py" "$repo" "${shift_args[@]}"
}
cmd_delete_hf() {
if [ $# -gt 0 ]; then
exec $PYTHON "$SCRIPT_DIR/delete-hf.py" "$@"
fi
echo "删除类型:"
echo " 1) 删除整个仓库 (Space/Dataset/Model)"
echo " 2) 按通配符批量删除文件"
echo " 3) 删除 Space 持久存储"
read -r -p "请选择 [1-3]: " t
case "$t" in
1) read -r -p "Repo ID: " rid; read -r -p "类型 (space/dataset/model): " rtype
exec $PYTHON "$SCRIPT_DIR/delete-hf.py" repo "$rid" --type "$rtype" ;;
2) read -r -p "Repo ID: " rid; read -r -p "通配符模式: " pat
exec $PYTHON "$SCRIPT_DIR/delete-hf.py" files "$rid" --pattern "$pat" ;;
3) read -r -p "Space ID: " sid
exec $PYTHON "$SCRIPT_DIR/delete-hf.py" storage "$sid" ;;
esac
}
cmd_restart_space() {
local repo="$1"
if [ -z "$repo" ]; then
read -r -p "Space ID (如 GGSheng/page): " repo
fi
info "▶ 重启 Space: $repo"
if hf spaces restart "$repo" 2>&1; then
info "✓ 重启请求已发送"
else
error "✗ 重启失败"
return 1
fi
}
cmd_pause_space() {
local repo="$1"
if [ -z "$repo" ]; then
read -r -p "Space ID (如 GGSheng/page): " repo
fi
warn "▶ 暂停 Space: $repo"
warn "警告: Space 暂停后无法通过网络访问,需手动重启恢复"
read -r -p "确认暂停? (y/n): " confirm
[[ "$confirm" != "y" ]] && info "已取消" && return 0
if hf spaces pause "$repo" 2>&1; then
info "✓ Space 已暂停"
else
error "✗ 暂停失败"
return 1
fi
}
cmd_factory_rebuild() {
local repo="$1"
if [ -z "$repo" ]; then
read -r -p "Space ID (如 GGSheng/page): " repo
fi
warn "▶ Factory 重建 Space: $repo"
warn "警告: 这将删除 Space 后重新创建!所有持久存储数据将被清除!"
read -r -p "确认重建? (输入 Space 名称确认): " confirm
[[ "$confirm" != "${repo#*/}" ]] && error "名称不匹配,已取消" && return 1
info "1/3 删除 Space..."
$PYTHON -c "
from huggingface_hub import HfApi
import os
api = HfApi()
try:
api.delete_repo('${repo}', repo_type='space')
print('✓ 已删除')
except Exception as e:
print(f'删除失败(可能不存在): {e}')
"
sleep 3
info "2/3 重新创建 Space..."
hf repos create "$repo" --repo-type space --space-sdk docker --private
info "3/3 上传代码..."
exec "$SCRIPT_DIR/rebuild-space.sh" "$repo"
}
cmd_storage() {
if [ $# -gt 0 ]; then
exec "$SCRIPT_DIR/hf-storage.sh" "$@"
fi
echo "存储操作:"
echo " 1) 上传文件"
echo " 2) 上传目录"
echo " 3) 下载文件"
echo " 4) 列出文件"
echo " 5) 同步目录"
read -r -p "请选择 [1-5]: " op
case "$op" in
1) read -r -p "文件路径: " f; read -r -p "目标路径 (留空同上): " d
exec "$SCRIPT_DIR/hf-storage.sh" upload "$f" ${d:+"$d"} ;;
2) read -r -p "目录路径: " d; read -r -p "前缀 (留空无前缀): " p
exec "$SCRIPT_DIR/hf-storage.sh" upload-dir "$d" ${p:+"$p"} ;;
3) read -r -p "远程文件: " f; read -r -p "本地路径 (留空当前目录): " l
exec "$SCRIPT_DIR/hf-storage.sh" download "$f" ${l:+"$l"} ;;
4) exec "$SCRIPT_DIR/hf-storage.sh" list ;;
5) read -r -p "本地目录: " l; read -r -p "远程前缀 (留空无): " r
exec "$SCRIPT_DIR/hf-storage.sh" sync "$l" ${r:+"$r"} ;;
esac
}
show_menu() {
clear 2>/dev/null || true
title "╔══════════════════════════════════════╗"
title "║ OpenClaw 工具箱 ║"
title "║ 本地开发工具集 ║"
title "╚══════════════════════════════════════╝"
echo ""
info " 1) 🚀 部署到 HF Space"
echo " 交互式全流程部署 OpenClaw 到 Hugging Face Space"
echo ""
info " 2) 📤 推送代码到 Space"
echo " 将本地最新代码强制推送到 Space 并触发重建"
echo ""
info " 3) 🗑️ 清理备份"
echo " 删除 Dataset 中指定日期及更早的所有备份文件"
echo ""
info " 4) 🔍 查找最佳备份"
echo " 综合评分找出最佳备份,可选清理旧备份"
echo ""
info " 5) ❌ 删除 HF 资源"
echo " 删除仓库、批量删除文件、或删除 Space 持久存储"
echo ""
info " 6) 📦 存储管理"
echo " HuggingFace 存储工具:上传/下载/同步文件"
echo ""
info " ── Space 运维 ──"
echo ""
info " 7) 🔄 重启 Space"
echo " 发送重启请求到 HuggingFace Space"
echo ""
info " 8) ⏸️ 暂停 Space"
echo " 暂停 Space,暂停后无法网络访问"
echo ""
info " 9) 🏭 Factory 重建"
echo " 删除 Space 后重新创建并上传代码(清除所有数据和持久存储)"
echo ""
info " 0) ❎ 退出"
echo ""
}
# ============================================================
# 交互菜单
# ============================================================
interactive_mode() {
while true; do
show_menu
read -r -p "请选择 [0-9]: " choice
echo ""
case "$choice" in
1) cmd_bootstrap ;;
2) cmd_rebuild ;;
3) cmd_cleanup ;;
4) cmd_find_backup ;;
5) cmd_delete_hf ;;
6) cmd_storage ;;
7) cmd_restart_space ;;
8) cmd_pause_space ;;
9) cmd_factory_rebuild ;;
0) info "再见!"; exit 0 ;;
*) warn "无效选择,请重新输入"; sleep 1 ;;
esac
done
}
show_usage() {
title "OpenClaw 工具箱 — 本地开发工具集"
echo ""
echo "用法: $0 [命令] [参数...]"
echo ""
echo "不带参数时启动交互式菜单。"
echo ""
info "命令模式:"
echo " $0 bootstrap 交互式部署到 HF Space"
echo " $0 rebuild-space <ID> [TOKEN] 推送代码到 Space"
echo " $0 restart-space <ID> 重启 Space"
echo " $0 pause-space <ID> 暂停 Space"
echo " $0 factory-rebuild <ID> Factory 重建 Space(删除重建)"
echo " $0 cleanup <ID> <日期> [TOKEN] 清理旧备份"
echo " $0 find-backup <ID> [选项] 查找最佳备份"
echo " $0 rm-hf <子命令> [参数] 删除 HF 资源"
echo " $0 storage <子命令> [参数] 存储管理"
echo ""
info "示例:"
echo " $0 # 交互菜单"
echo " $0 rebuild-space GGSheng/page # 推送代码"
echo " $0 restart-space GGSheng/page # 重启 Space"
echo " $0 cleanup GGSheng/page-backup 20260427 # 清理备份"
}
# ============================================================
# 主入口
# ============================================================
main() {
if [ $# -eq 0 ]; then
interactive_mode
exit 0
fi
local cmd="$1"
shift
case "$cmd" in
-h|--help|help) show_usage ;;
bootstrap) cmd_bootstrap "$@" ;;
rebuild-space|rebuild) cmd_rebuild "$@" ;;
restart-space) cmd_restart_space "$@" ;;
pause-space) cmd_pause_space "$@" ;;
factory-rebuild) cmd_factory_rebuild "$@" ;;
cleanup) cmd_cleanup "$@" ;;
find-backup|find) cmd_find_backup "$@" ;;
rm-hf|delete-hf) cmd_delete_hf "$@" ;;
storage) cmd_storage "$@" ;;
*)
error "未知命令: $cmd"
echo "使用 '$0 --help' 查看可用命令"
exit 1
;;
esac
}
main "$@"