Files
wehub-resource-sync 5dab37cb35
CI / Validate agent files (push) Has been cancelled
Sync to Gitee / sync (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:44:34 +08:00

622 lines
23 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#
# install.sh -- 将智能体安装到本地 AI 工具中(中文版适配)
#
# 读取 integrations/ 中的转换文件,复制到各工具的配置目录。
# 请先运行 scripts/convert.sh 生成集成文件。
#
# 用法:
# ./scripts/install.sh [--tool <name>] [--no-interactive] [--help]
#
# 支持的工具:
# claude-code -- 复制到 ~/.claude/agents/
# copilot -- 复制到 ~/.github/agents/
# antigravity -- 复制到 ~/.gemini/antigravity/skills/
# gemini-cli -- 安装到 ~/.gemini/extensions/agency-agents/
# opencode -- 复制到 .opencode/agent/(当前目录)
# cursor -- 复制到 .cursor/rules/(当前目录)
# trae -- 复制到 .trae/rules/(当前目录)
# aider -- 复制 CONVENTIONS.md(当前目录)
# windsurf -- 复制 .windsurfrules(当前目录)
# openclaw -- 复制到 ~/.openclaw/agency-agents/
# qwen -- 复制 SubAgent 到 .qwen/agents/(项目级)
# codex -- 复制到 .codex/agents/(项目级)
# deerflow -- 复制到 DeerFlow custom skills 目录(Docker 项目级)
# workbuddy -- 复制到 ~/.workbuddy/skills/(全局)
# codewhale -- 复制到 ~/.codewhale/skills/(全局,原 DeepSeek-TUI
# hermes -- 复制到 ~/.hermes/skills/(全局)
# kiro -- 复制到 ~/.kiro/agents/(全局)
# qoder -- 复制到 .qoder/agents/(项目级)
# all -- 安装所有已检测到的工具(默认)
#
# Hermes 专属参数:
# --category <名称> 只安装某一分类下的 skills,可重复传入多次。
# 分类取 integrations/hermes/ 下的目录名,例如:
# --category marketing
# --category engineering --category design
# Discord 模式下 Hermes 会把每个 skill 注册为斜杠命令,
# 总 JSON 超过 8000 字符会被 Discord API 拒绝 (error 50035)
# 若需要在 Discord 中使用建议按分类分批安装。
set -euo pipefail
# --- 颜色 ---
if [[ -t 1 ]]; then
C_GREEN=$'\033[0;32m'; C_YELLOW=$'\033[1;33m'; C_RED=$'\033[0;31m'
C_CYAN=$'\033[0;36m'; C_BOLD=$'\033[1m'; C_DIM=$'\033[2m'; C_RESET=$'\033[0m'
else
C_GREEN=''; C_YELLOW=''; C_RED=''; C_CYAN=''; C_BOLD=''; C_DIM=''; C_RESET=''
fi
ok() { printf "${C_GREEN}[OK]${C_RESET} %s\n" "$*"; }
warn() { printf "${C_YELLOW}[!!]${C_RESET} %s\n" "$*"; }
err() { printf "${C_RED}[ERR]${C_RESET} %s\n" "$*" >&2; }
header() { printf "\n${C_BOLD}%s${C_RESET}\n" "$*"; }
dim() { printf "${C_DIM}%s${C_RESET}\n" "$*"; }
# --- 路径 ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
INTEGRATIONS="$REPO_ROOT/integrations"
ALL_TOOLS=(claude-code copilot antigravity gemini-cli opencode openclaw cursor trae aider windsurf qwen codex deerflow workbuddy codewhale hermes kiro qoder)
# --- 用法 ---
usage() {
sed -n '3,26p' "$0" | sed 's/^# \{0,1\}//'
exit 0
}
# --- 预检 ---
check_integrations() {
if [[ ! -d "$INTEGRATIONS" ]]; then
err "integrations/ 不存在。请先运行 ./scripts/convert.sh"
exit 1
fi
}
# --- 工具检测 ---
detect_claude_code() { [[ -d "${HOME}/.claude" ]]; }
detect_copilot() { command -v code >/dev/null 2>&1 || [[ -d "${HOME}/.github" ]] || [[ -d "${HOME}/.copilot" ]]; }
detect_antigravity() { [[ -d "${HOME}/.gemini/antigravity/skills" ]]; }
detect_gemini_cli() { command -v gemini >/dev/null 2>&1 || [[ -d "${HOME}/.gemini" ]]; }
detect_cursor() { command -v cursor >/dev/null 2>&1 || [[ -d "${HOME}/.cursor" ]]; }
detect_trae() { command -v trae >/dev/null 2>&1 || [[ -d "${HOME}/.trae" ]]; }
detect_opencode() { command -v opencode >/dev/null 2>&1 || [[ -d "${HOME}/.config/opencode" ]]; }
detect_aider() { command -v aider >/dev/null 2>&1; }
detect_openclaw() { command -v openclaw >/dev/null 2>&1 || [[ -d "${HOME}/.openclaw" ]]; }
detect_windsurf() { command -v windsurf >/dev/null 2>&1 || [[ -d "${HOME}/.codeium" ]]; }
detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${HOME}/.qwen" ]]; }
detect_codex() { command -v codex >/dev/null 2>&1 || [[ -d "${HOME}/.codex" ]]; }
detect_deerflow() { command -v deerflow >/dev/null 2>&1 || [[ -d "${HOME}/.deerflow" ]] || docker ps --format '{{.Names}}' 2>/dev/null | grep -q deerflow; }
detect_workbuddy() { command -v workbuddy >/dev/null 2>&1 || [[ -d "${HOME}/.workbuddy" ]]; }
detect_codewhale() { command -v codewhale >/dev/null 2>&1 || [[ -d "${HOME}/.codewhale" ]] || [[ -d "${HOME}/.deepseek" ]]; }
detect_hermes() { command -v hermes >/dev/null 2>&1 || [[ -d "${HOME}/.hermes" ]]; }
detect_kiro() { command -v kiro >/dev/null 2>&1 || command -v kiro-cli >/dev/null 2>&1 || [[ -d "${HOME}/.kiro" ]]; }
detect_qoder() { command -v qoder >/dev/null 2>&1 || [[ -d "${HOME}/.qoder" ]]; }
is_detected() {
case "$1" in
claude-code) detect_claude_code ;;
copilot) detect_copilot ;;
antigravity) detect_antigravity ;;
gemini-cli) detect_gemini_cli ;;
opencode) detect_opencode ;;
openclaw) detect_openclaw ;;
cursor) detect_cursor ;;
trae) detect_trae ;;
aider) detect_aider ;;
windsurf) detect_windsurf ;;
qwen) detect_qwen ;;
codex) detect_codex ;;
deerflow) detect_deerflow ;;
workbuddy) detect_workbuddy ;;
codewhale) detect_codewhale ;;
hermes) detect_hermes ;;
kiro) detect_kiro ;;
qoder) detect_qoder ;;
*) return 1 ;;
esac
}
tool_label() {
case "$1" in
claude-code) printf "%-14s %s" "Claude Code" "(~/.claude/agents)" ;;
copilot) printf "%-14s %s" "Copilot" "(~/.github + ~/.copilot)" ;;
antigravity) printf "%-14s %s" "Antigravity" "(~/.gemini/antigravity)" ;;
gemini-cli) printf "%-14s %s" "Gemini CLI" "(gemini 扩展)" ;;
opencode) printf "%-14s %s" "OpenCode" "(opencode.ai)" ;;
openclaw) printf "%-14s %s" "OpenClaw" "(~/.openclaw)" ;;
cursor) printf "%-14s %s" "Cursor" "(.cursor/rules)" ;;
trae) printf "%-14s %s" "Trae" "(.trae/rules)" ;;
aider) printf "%-14s %s" "Aider" "(CONVENTIONS.md)" ;;
windsurf) printf "%-14s %s" "Windsurf" "(.windsurfrules)" ;;
qwen) printf "%-14s %s" "Qwen Code" "(~/.qwen/agents)" ;;
codex) printf "%-14s %s" "Codex CLI" "(.codex/agents)" ;;
deerflow) printf "%-14s %s" "DeerFlow" "(skills/custom)" ;;
workbuddy) printf "%-14s %s" "WorkBuddy" "(~/.workbuddy/skills)" ;;
codewhale) printf "%-14s %s" "CodeWhale" "(~/.codewhale/skills)" ;;
hermes) printf "%-14s %s" "Hermes Agent" "(~/.hermes/skills)" ;;
kiro) printf "%-14s %s" "Kiro" "(~/.kiro/agents)" ;;
qoder) printf "%-14s %s" "Qoder" "(.qoder/agents)" ;;
esac
}
# --- 安装器 ---
install_claude_code() {
local dest="${HOME}/.claude/agents"
local count=0
mkdir -p "$dest"
local dir f first_line
for dir in academic design engineering finance game-development gis hr legal marketing paid-media sales product \
project-management security supply-chain testing support spatial-computing specialized; do
[[ -d "$REPO_ROOT/$dir" ]] || continue
while IFS= read -r -d '' f; do
first_line="$(head -1 "$f")"
[[ "$first_line" == "---" ]] || continue
cp "$f" "$dest/"
(( count++ )) || true
done < <(find "$REPO_ROOT/$dir" -name "*.md" -type f -print0)
done
ok "Claude Code: $count 个智能体 -> $dest"
}
install_copilot() {
local dest1="${HOME}/.github/agents"
local dest2="${HOME}/.copilot/agents"
local count=0
mkdir -p "$dest1" "$dest2"
local dir f first_line
for dir in academic design engineering finance game-development gis hr legal marketing paid-media sales product \
project-management security supply-chain testing support spatial-computing specialized; do
[[ -d "$REPO_ROOT/$dir" ]] || continue
while IFS= read -r -d '' f; do
first_line="$(head -1 "$f")"
[[ "$first_line" == "---" ]] || continue
cp "$f" "$dest1/"
cp "$f" "$dest2/"
(( count++ )) || true
done < <(find "$REPO_ROOT/$dir" -name "*.md" -type f -print0)
done
ok "Copilot: $count 个智能体 -> $dest1 + $dest2"
}
install_antigravity() {
local src="$INTEGRATIONS/antigravity"
local dest="${HOME}/.gemini/antigravity/skills"
local count=0
[[ -d "$src" ]] || { err "integrations/antigravity 不存在。请先运行 convert.sh"; return 1; }
mkdir -p "$dest"
local d
while IFS= read -r -d '' d; do
local name; name="$(basename "$d")"
mkdir -p "$dest/$name"
cp "$d/SKILL.md" "$dest/$name/SKILL.md"
(( count++ )) || true
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
ok "Antigravity: $count 个 skills -> $dest"
}
install_gemini_cli() {
local src="$INTEGRATIONS/gemini-cli"
local dest="${HOME}/.gemini/extensions/agency-agents"
local count=0
[[ -d "$src" ]] || { err "integrations/gemini-cli 不存在。请先运行 convert.sh --tool gemini-cli"; return 1; }
[[ -f "$src/gemini-extension.json" ]] || { err "gemini-extension.json 缺失。请先运行 convert.sh --tool gemini-cli"; return 1; }
[[ -d "$src/skills" ]] || { err "skills/ 目录缺失。请先运行 convert.sh --tool gemini-cli"; return 1; }
mkdir -p "$dest/skills"
cp "$src/gemini-extension.json" "$dest/gemini-extension.json"
local d
while IFS= read -r -d '' d; do
local name; name="$(basename "$d")"
mkdir -p "$dest/skills/$name"
cp "$d/SKILL.md" "$dest/skills/$name/SKILL.md"
(( count++ )) || true
done < <(find "$src/skills" -mindepth 1 -maxdepth 1 -type d -print0)
ok "Gemini CLI: $count 个 skills -> $dest"
}
install_opencode() {
local src="$INTEGRATIONS/opencode/agents"
local dest="${PWD}/.opencode/agents"
local count=0
[[ -d "$src" ]] || { err "integrations/opencode 不存在。请先运行 convert.sh"; return 1; }
mkdir -p "$dest"
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"; (( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.md" -print0)
ok "OpenCode: $count 个智能体 -> $dest"
warn "OpenCode: 项目级安装。请在项目根目录运行。"
}
install_openclaw() {
local src="$INTEGRATIONS/openclaw"
local dest="${HOME}/.openclaw/agency-agents"
local count=0
[[ -d "$src" ]] || { err "integrations/openclaw 不存在。请先运行 convert.sh"; return 1; }
mkdir -p "$dest"
local d
while IFS= read -r -d '' d; do
local name; name="$(basename "$d")"
mkdir -p "$dest/$name"
cp "$d/SOUL.md" "$dest/$name/SOUL.md"
cp "$d/AGENTS.md" "$dest/$name/AGENTS.md"
cp "$d/IDENTITY.md" "$dest/$name/IDENTITY.md"
if command -v openclaw >/dev/null 2>&1; then
# 跳过已注册的智能体,避免重复 add 导致阻塞(#34)
if openclaw agents list 2>/dev/null | grep -q "$name"; then
dim " 跳过已注册: $name"
else
# 超时 30s 防止命令挂起(macOS 兼容写法)
if command -v timeout >/dev/null 2>&1; then
timeout 30 openclaw agents add "$name" --workspace "$dest/$name" --non-interactive 2>/dev/null || true
else
openclaw agents add "$name" --workspace "$dest/$name" --non-interactive 2>/dev/null &
local pid=$!
( sleep 30 && kill "$pid" 2>/dev/null ) &
wait "$pid" 2>/dev/null || true
fi
fi
fi
(( count++ )) || true
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
ok "OpenClaw: $count 个工作空间 -> $dest"
if command -v openclaw >/dev/null 2>&1; then
warn "OpenClaw: 运行 'openclaw gateway restart' 激活新智能体"
fi
}
install_cursor() {
local src="$INTEGRATIONS/cursor/rules"
local dest="${PWD}/.cursor/rules"
local count=0
[[ -d "$src" ]] || { err "integrations/cursor 不存在。请先运行 convert.sh"; return 1; }
mkdir -p "$dest"
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"; (( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.mdc" -print0)
ok "Cursor: $count 个规则 -> $dest"
warn "Cursor: 项目级安装。请在项目根目录运行。"
}
install_trae() {
local src="$INTEGRATIONS/trae/rules"
local dest="${PWD}/.trae/rules"
local count=0
[[ -d "$src" ]] || { err "integrations/trae 不存在。请先运行 convert.sh --tool trae"; return 1; }
mkdir -p "$dest"
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"; (( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.md" -print0)
ok "Trae: $count 个规则 -> $dest"
warn "Trae: 项目级安装。请在项目根目录运行。"
}
install_aider() {
local src="$INTEGRATIONS/aider/CONVENTIONS.md"
local dest="${PWD}/CONVENTIONS.md"
[[ -f "$src" ]] || { err "integrations/aider/CONVENTIONS.md 不存在。请先运行 convert.sh"; return 1; }
if [[ -f "$dest" ]]; then
warn "Aider: CONVENTIONS.md 已存在 ($dest),删除后重试。"
return 0
fi
cp "$src" "$dest"
ok "Aider: 已安装 -> $dest"
warn "Aider: 项目级安装。请在项目根目录运行。"
}
install_windsurf() {
local src="$INTEGRATIONS/windsurf/.windsurfrules"
local dest="${PWD}/.windsurfrules"
[[ -f "$src" ]] || { err "integrations/windsurf/.windsurfrules 不存在。请先运行 convert.sh"; return 1; }
if [[ -f "$dest" ]]; then
warn "Windsurf: .windsurfrules 已存在 ($dest),删除后重试。"
return 0
fi
cp "$src" "$dest"
ok "Windsurf: 已安装 -> $dest"
warn "Windsurf: 项目级安装。请在项目根目录运行。"
}
install_qwen() {
local src="$INTEGRATIONS/qwen/agents"
local dest="${PWD}/.qwen/agents"
local count=0
[[ -d "$src" ]] || { err "integrations/qwen 不存在。请先运行 convert.sh"; return 1; }
mkdir -p "$dest"
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"
(( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.md" -print0)
ok "Qwen Code: $count 个智能体 -> $dest"
warn "Qwen Code: 项目级安装。请在项目根目录运行。"
warn "提示: 在 Qwen Code 中运行 '/agents manage' 刷新,或重启会话"
}
install_codex() {
local src="$INTEGRATIONS/codex/agents"
local dest="${PWD}/.codex/agents"
local count=0
[[ -d "$src" ]] || { err "integrations/codex 不存在。请先运行 convert.sh --tool codex"; return 1; }
mkdir -p "$dest"
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"
(( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.toml" -print0)
ok "Codex CLI: $count 个智能体 -> $dest"
warn "Codex CLI: 项目级安装。请在项目根目录运行。"
}
install_deerflow() {
local src="$INTEGRATIONS/deerflow"
local dest="${DEERFLOW_SKILLS_DIR:-./skills/custom}"
local count=0
[[ -d "$src" ]] || { err "integrations/deerflow 不存在。请先运行 convert.sh --tool deerflow"; return 1; }
mkdir -p "$dest"
local d
while IFS= read -r -d '' d; do
local name; name="$(basename "$d")"
[[ -f "$d/SKILL.md" ]] || continue
mkdir -p "$dest/$name"
cp "$d/SKILL.md" "$dest/$name/SKILL.md"
(( count++ )) || true
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
ok "DeerFlow: $count 个 skills -> $dest"
warn "DeerFlow: 默认安装到 ./skills/custom/。设置 DEERFLOW_SKILLS_DIR 可自定义路径。"
}
install_workbuddy() {
local src="$INTEGRATIONS/workbuddy"
local dest="${HOME}/.workbuddy/skills"
local count=0
[[ -d "$src" ]] || { err "integrations/workbuddy 不存在。请先运行 convert.sh --tool workbuddy"; return 1; }
mkdir -p "$dest"
local d
while IFS= read -r -d '' d; do
local name; name="$(basename "$d")"
[[ -f "$d/SKILL.md" ]] || continue
mkdir -p "$dest/$name"
cp "$d/SKILL.md" "$dest/$name/SKILL.md"
(( count++ )) || true
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
ok "WorkBuddy: $count 个 skills -> $dest"
}
install_codewhale() {
local src="$INTEGRATIONS/codewhale"
local dest="${HOME}/.codewhale/skills"
local count=0
[[ -d "$src" ]] || { err "integrations/codewhale 不存在。请先运行 convert.sh --tool codewhale"; return 1; }
mkdir -p "$dest"
local d
while IFS= read -r -d '' d; do
local name; name="$(basename "$d")"
[[ -f "$d/SKILL.md" ]] || continue
mkdir -p "$dest/$name"
cp "$d/SKILL.md" "$dest/$name/SKILL.md"
(( count++ )) || true
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
ok "CodeWhale: $count 个 skills -> $dest"
}
install_hermes() {
local src="$INTEGRATIONS/hermes"
# 安装目录优先级(issue #82):官方环境变量 HERMES_HOME > Windows 新版默认位置 > 传统位置
local dest
if [[ -n "${HERMES_HOME:-}" ]]; then
dest="${HERMES_HOME}/skills"
elif [[ -n "${LOCALAPPDATA:-}" && -d "${LOCALAPPDATA}/hermes" ]]; then
dest="${LOCALAPPDATA}/hermes/skills"
else
dest="${HOME}/.hermes/skills"
fi
local count=0
[[ -d "$src" ]] || { err "integrations/hermes 不存在。请先运行 convert.sh --tool hermes"; return 1; }
# 若指定了 --category,只安装命中的分类;否则安装全部
local filter_note=""
if [[ ${#HERMES_CATEGORIES[@]} -gt 0 ]]; then
local c
for c in "${HERMES_CATEGORIES[@]}"; do
[[ -d "$src/$c" ]] || { err "hermes 分类不存在: ${c}(可选: $(ls "$src" | tr '\n' ' ')"; return 1; }
done
filter_note=" [分类: ${HERMES_CATEGORIES[*]}]"
fi
mkdir -p "$dest"
# Hermes 保留两级目录结构:category/skill-name/SKILL.md
local catdir
while IFS= read -r -d '' catdir; do
local catname; catname="$(basename "$catdir")"
if [[ ${#HERMES_CATEGORIES[@]} -gt 0 ]]; then
local matched=false c
for c in "${HERMES_CATEGORIES[@]}"; do [[ "$c" == "$catname" ]] && matched=true && break; done
$matched || continue
fi
local skilldir
while IFS= read -r -d '' skilldir; do
local skillname; skillname="$(basename "$skilldir")"
[[ -f "$skilldir/SKILL.md" ]] || continue
mkdir -p "$dest/$catname/$skillname"
cp "$skilldir/SKILL.md" "$dest/$catname/$skillname/SKILL.md"
(( count++ )) || true
done < <(find "$catdir" -mindepth 1 -maxdepth 1 -type d -print0)
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
ok "Hermes Agent: $count 个 skills -> $dest$filter_note"
if [[ ${#HERMES_CATEGORIES[@]} -eq 0 && $count -gt 80 ]]; then
warn "Hermes Discord 模式对斜杠命令总长有 8000 字符上限(error 50035)。"
warn "若要在 Discord 中使用,建议用 --category <名称> 按分类分批安装。"
fi
}
install_kiro() {
local src="$INTEGRATIONS/kiro"
local dest="${HOME}/.kiro/agents"
local count=0
[[ -d "$src" ]] || { err "integrations/kiro 不存在。请先运行 convert.sh --tool kiro"; return 1; }
mkdir -p "$dest"
# Kiro 自定义智能体格式:.md 文件(带 YAML frontmatter
# 参考:https://kiro.dev/docs/chat/subagents/
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"
(( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.md" -print0)
ok "Kiro: $count 个智能体 -> $dest"
warn "提示: Kiro 会自动识别 ~/.kiro/agents/ 下的 .md 文件作为自定义子智能体"
warn "提示: 在对话中使用 '/<agent-name>' 或让 Kiro 自动选择合适的子智能体"
}
install_qoder() {
local src="$INTEGRATIONS/qoder/agents"
local dest="${PWD}/.qoder/agents"
local count=0
[[ -d "$src" ]] || { err "integrations/qoder 不存在。请先运行 convert.sh --tool qoder"; return 1; }
mkdir -p "$dest"
local f
while IFS= read -r -d '' f; do
cp "$f" "$dest/"
(( count++ )) || true
done < <(find "$src" -maxdepth 1 -name "*.md" -print0)
ok "Qoder: $count 个智能体 -> $dest"
warn "Qoder: 项目级安装。请在项目根目录运行。"
}
install_tool() {
case "$1" in
claude-code) install_claude_code ;;
copilot) install_copilot ;;
antigravity) install_antigravity ;;
gemini-cli) install_gemini_cli ;;
opencode) install_opencode ;;
openclaw) install_openclaw ;;
cursor) install_cursor ;;
trae) install_trae ;;
aider) install_aider ;;
windsurf) install_windsurf ;;
qwen) install_qwen ;;
codex) install_codex ;;
deerflow) install_deerflow ;;
workbuddy) install_workbuddy ;;
codewhale) install_codewhale ;;
hermes) install_hermes ;;
kiro) install_kiro ;;
qoder) install_qoder ;;
esac
}
# --- 入口 ---
main() {
local tool="all"
HERMES_CATEGORIES=()
while [[ $# -gt 0 ]]; do
case "$1" in
--tool) tool="${2:?'--tool 需要一个值'}"; shift 2 ;;
--category) HERMES_CATEGORIES+=("${2:?'--category 需要一个值'}"); shift 2 ;;
--no-interactive) shift ;;
--help|-h) usage ;;
*) err "未知选项: $1"; usage ;;
esac
done
if [[ ${#HERMES_CATEGORIES[@]} -gt 0 && "$tool" != "hermes" ]]; then
warn "--category 仅对 --tool hermes 生效,已忽略。"
HERMES_CATEGORIES=()
fi
check_integrations
if [[ "$tool" != "all" ]]; then
local valid=false t
for t in "${ALL_TOOLS[@]}"; do [[ "$t" == "$tool" ]] && valid=true && break; done
if ! $valid; then
err "未知工具 '$tool'。可选: ${ALL_TOOLS[*]}"
exit 1
fi
fi
SELECTED_TOOLS=()
if [[ "$tool" != "all" ]]; then
SELECTED_TOOLS=("$tool")
else
header "AI 智能体专家团队 -- 扫描已安装的工具..."
printf "\n"
local t
for t in "${ALL_TOOLS[@]}"; do
if is_detected "$t" 2>/dev/null; then
SELECTED_TOOLS+=("$t")
printf " ${C_GREEN}[*]${C_RESET} %s ${C_DIM}已检测到${C_RESET}\n" "$(tool_label "$t")"
else
printf " ${C_DIM}[ ] %s 未找到${C_RESET}\n" "$(tool_label "$t")"
fi
done
fi
if [[ ${#SELECTED_TOOLS[@]} -eq 0 ]]; then
warn "未选择或检测到任何工具。"
printf "\n"
dim " 提示: 使用 --tool <名称> 强制安装指定工具。"
dim " 可选: ${ALL_TOOLS[*]}"
exit 0
fi
printf "\n"
header "AI 智能体专家团队 -- 安装智能体"
printf " 仓库: %s\n" "$REPO_ROOT"
printf " 安装到: %s\n" "${SELECTED_TOOLS[*]}"
printf "\n"
local installed=0 t
for t in "${SELECTED_TOOLS[@]}"; do
install_tool "$t"
(( installed++ )) || true
done
printf "\n"
ok "完成!已安装 $installed 个工具。"
printf "\n"
dim " 运行 ./scripts/convert.sh 重新生成集成文件。"
printf "\n"
}
main "$@"