set -e
if [ -t 1 ]; then
GREEN='\033[0;32m'; YELLOW='\033[0;33m'; RED='\033[0;31m'
CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
else
GREEN=''; YELLOW=''; RED=''; CYAN=''; BOLD=''; DIM=''; NC=''
fi
ok() { echo -e " ${DIM}${GREEN}✓${NC}${DIM} $*${NC}"; }
warn() { echo -e " ${YELLOW}⚠${NC}${DIM} $*${NC}"; }
err() { echo -e " ${RED}✗${NC}${DIM} $*${NC}"; }
info() { echo -e " ${DIM}${CYAN}→${NC}${DIM} $*${NC}"; }
step() { echo -e "${DIM}$*${NC}"; }
detect_trae_variant() {
if [ -d "$HOME/.trae-cn" ]; then
TRAE_VARIANT="ide"
elif [ -d "$HOME/.marscode" ]; then
TRAE_VARIANT="plugin"
elif [ -d "$HOME/.traecli" ]; then
TRAE_VARIANT="cli"
else
TRAE_VARIANT="unknown"
fi
}
BRAND="cannbot"
VERSION="1.0.0"
EXCLUDED_SKILL=""
INCLUDED_SKILLS="ascendc-tiling-design npu-arch ascendc-api-best-practices ascendc-regbase-best-practice ops-precision-standard ascendc-docs-search ascendc-env-check ascendc-precision-debug ops-profiling ascendc-direct-invoke-template torch-ascendc-op-extension ascendc-runtime-debug ascendc-crash-debug ascendc-code-review"
INCLUDED_AGENT_PATTERN="ascendc-kernel-*"
show_banner() {
echo ""
echo -e "${CYAN}"
cat << 'BANNER'
____ _ _ _ _ _ ____ _
/ ___| / \ | \ | | \ | | __ ) ___ | |_
| | / _ \ | \| | \| | _ \ / _ \| __|
| |___ / ___ \| |\ | |\ | |_) | (_) | |_
\____/_/ \_\_| \_|_| \_|____/ \___/ \__|
BANNER
echo -e "${NC}"
echo -e " ${BOLD}Ascend C Kernel Dev Team${NC}"
echo ""
}
show_help() {
cat << EOF
CANNBot - Ascend C Kernel Development Environment Installer
Usage: init.sh [level] [tool] [install_path]
Arguments:
level - Installation level: "project" (default) or "global"
tool - Target tool: "opencode" (default), "claude", "trae", or "cursor"
install_path - Project-level installation directory (default: current working directory)
Options:
--help - Show this help message
Examples:
init.sh # Project-level, OpenCode
init.sh project opencode # Project-level, OpenCode
init.sh global claude # Global-level, Claude Code
init.sh project claude # Project-level, Claude Code
init.sh project trae # Project-level, Trae
init.sh project cursor # Project-level, Cursor
init.sh project opencode /path/to/proj # Project-level, OpenCode, custom path
init.sh project trae /path/to/proj # Project-level, Trae, custom path
Installation paths (CANNBot brand):
OpenCode: .opencode/{skills,agents}/ + AGENTS.md in project root
Claude: .claude/{skills,agents}/ + CLAUDE.md in project root
Trae IDE: .trae/{skills,agents}/ + AGENTS.md in project root
Trae Plugin: .marscode/{skills,agents}/ + AGENTS.md in project root
Trae CLI: .traecli/{skills,agents}/ + AGENTS.md in project root
Cursor: .cursor/{skills,agents}/ + AGENTS.md in project root
After installation, launch directly:
OpenCode: opencode
Claude: claude
Trae: 通过 CLI 或 IDE 启动
Cursor: 通过 Cursor IDE 启动
EOF
}
LEVEL="project"
TOOL="opencode"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_ROOT="$SCRIPT_DIR"
LOCAL_AGENT_ROOT="$PLUGIN_ROOT/agents"
SHARED_SKILL_ROOT="$(cd "$PLUGIN_ROOT/../../ops" && pwd)"
for arg in "$@"; do
case "$arg" in
--help) show_help; exit 0 ;;
global|project) LEVEL="$arg" ;;
opencode|claude|trae|cursor) TOOL="$arg" ;;
esac
done
if [ $# -gt 0 ]; then
last_arg="${!#}"
case "$last_arg" in
--help|global|project|opencode|claude|trae|cursor) ;;
*) INSTALL_PATH="$last_arg" ;;
esac
fi
if [ "$LEVEL" = "global" ]; then
if [ "$TOOL" = "opencode" ]; then
CONFIG_ROOT="$HOME/.config/opencode"
elif [ "$TOOL" = "trae" ]; then
detect_trae_variant
case "$TRAE_VARIANT" in
plugin) CONFIG_ROOT="$HOME/.marscode" ;;
cli) CONFIG_ROOT="$HOME/.traecli" ;;
*) CONFIG_ROOT="$HOME/.trae-cn" ;;
esac
elif [ "$TOOL" = "cursor" ]; then
CONFIG_ROOT="$HOME/.cursor"
else
CONFIG_ROOT="$HOME/.claude"
fi
else
if [ -n "$INSTALL_PATH" ]; then
INSTALL_BASE="$(cd "$INSTALL_PATH" && pwd)"
CONFIG_ROOT_BASE="$INSTALL_BASE"
else
INSTALL_BASE="$PWD"
CONFIG_ROOT_BASE="$INSTALL_BASE"
fi
if [ "$TOOL" = "opencode" ]; then
CONFIG_ROOT="$CONFIG_ROOT_BASE/.opencode"
elif [ "$TOOL" = "trae" ]; then
detect_trae_variant
case "$TRAE_VARIANT" in
plugin) CONFIG_ROOT="$CONFIG_ROOT_BASE/.marscode" ;;
cli) CONFIG_ROOT="$CONFIG_ROOT_BASE/.traecli" ;;
*) CONFIG_ROOT="$CONFIG_ROOT_BASE/.trae" ;;
esac
elif [ "$TOOL" = "cursor" ]; then
CONFIG_ROOT="$CONFIG_ROOT_BASE/.cursor"
else
CONFIG_ROOT="$CONFIG_ROOT_BASE/.claude"
fi
fi
CANNBOT_DIR="$CONFIG_ROOT"
if [ -e "$CONFIG_ROOT/$BRAND" ] || [ -L "$CONFIG_ROOT/$BRAND" ]; then
rm -rf "$CONFIG_ROOT/$BRAND"
fi
if [ "$TOOL" = "opencode" ] && [ -L "$CONFIG_ROOT/teams" ]; then
rm -f "$CONFIG_ROOT/teams"
fi
show_banner
echo " Tool: $TOOL"
echo " Level: $LEVEL"
echo " Path: $CONFIG_ROOT"
echo ""
if [ "$TOOL" = "trae" ]; then
case "$TRAE_VARIANT" in
ide)
info "Detected: TRAE IDE (.trae-cn / .trae)"
;;
plugin)
info "Detected: TRAE Plugin (.marscode)"
;;
cli)
info "Detected: TRAE CLI (.traecli)"
;;
unknown)
warn "TRAE variant not detected; defaulting to IDE path"
warn "If you use TRAE Plugin, ensure ~/.marscode exists before re-running"
warn "If you use TRAE CLI, ensure ~/.traecli exists before re-running"
;;
esac
echo ""
fi
step "[0/5] Checking items to be installed..."
SKILLS_TO_INSTALL=""
SKILL_COUNT=0
for skill_dir in "$SHARED_SKILL_ROOT"/*/; do
[ -d "$skill_dir" ] || continue
name=$(basename "$skill_dir")
echo "$INCLUDED_SKILLS" | grep -qw "$name" || continue
[ -n "$EXCLUDED_SKILL" ] && [ "$name" = "$EXCLUDED_SKILL" ] && continue
SKILLS_TO_INSTALL="$SKILLS_TO_INSTALL $name"
SKILL_COUNT=$((SKILL_COUNT + 1))
done
AGENTS_TO_INSTALL=""
AGENT_COUNT=0
for agent_entry in "$LOCAL_AGENT_ROOT"/*; do
[ -e "$agent_entry" ] || continue
name=$(basename "$agent_entry")
base="${name%.md}"
[[ "$base" != $INCLUDED_AGENT_PATTERN ]] && continue
AGENTS_TO_INSTALL="$AGENTS_TO_INSTALL $name"
AGENT_COUNT=$((AGENT_COUNT + 1))
done
echo ""
echo -e "${BOLD}以下内容将被安装/替换:${NC}"
echo ""
if [ "$SKILL_COUNT" -gt 0 ]; then
echo -e "${CYAN}Skills (${SKILL_COUNT} 项):${NC}"
for name in $SKILLS_TO_INSTALL; do
target="$CANNBOT_DIR/skills/$name"
if [ -e "$target" ] || [ -L "$target" ]; then
echo -e " ${YELLOW}$name${NC}"
else
echo -e " ${GREEN}$name${NC}"
fi
done
echo ""
fi
if [ "$AGENT_COUNT" -gt 0 ]; then
echo -e "${CYAN}Agents (${AGENT_COUNT} 项):${NC}"
for name in $AGENTS_TO_INSTALL; do
target="$CANNBOT_DIR/agents/$name"
if [ -e "$target" ] || [ -L "$target" ]; then
echo -e " ${YELLOW}$name${NC}"
else
echo -e " ${GREEN}$name${NC}"
fi
done
echo ""
fi
echo -e "${CYAN}配置文件:${NC}"
config_src="$PLUGIN_ROOT/AGENTS.md"
if [ "$TOOL" = "opencode" ]; then
if [ "$LEVEL" = "project" ]; then
config_target="$INSTALL_BASE/AGENTS.md"
if [ "$PLUGIN_ROOT" = "$INSTALL_BASE" ]; then
echo -e " ${GREEN}AGENTS.md${NC} (已存在,无需操作)"
elif [ -e "$config_target" ] || [ -L "$config_target" ]; then
echo -e " ${YELLOW}AGENTS.md${NC} (将被替换)"
else
echo -e " ${GREEN}AGENTS.md${NC} (将创建)"
fi
else
config_target="$CONFIG_ROOT/AGENTS.md"
if [ -e "$config_target" ] || [ -L "$config_target" ]; then
echo -e " ${YELLOW}AGENTS.md${NC} (将被替换)"
else
echo -e " ${GREEN}AGENTS.md${NC} (将创建)"
fi
fi
elif [ "$TOOL" = "claude" ]; then
if [ "$LEVEL" = "project" ]; then
config_target="$INSTALL_BASE/CLAUDE.md"
else
config_target="$CONFIG_ROOT/CLAUDE.md"
fi
if [ -e "$config_target" ] || [ -L "$config_target" ]; then
echo -e " ${YELLOW}CLAUDE.md${NC} (将被替换)"
else
echo -e " ${GREEN}CLAUDE.md${NC} (将创建)"
fi
else
if [ "$LEVEL" = "project" ]; then
config_target="$INSTALL_BASE/AGENTS.md"
else
config_target="$CONFIG_ROOT/AGENTS.md"
fi
if [ -e "$config_target" ] || [ -L "$config_target" ]; then
echo -e " ${YELLOW}AGENTS.md${NC} (将被替换)"
else
echo -e " ${GREEN}AGENTS.md${NC} (将创建)"
fi
fi
echo ""
echo -e "${BOLD}${YELLOW}注意:仅替换上述白名单内的内容,不影响其他已存在的 skills/agents${NC}"
echo ""
ok "开始安装..."
echo ""
step "[1/5] Setting up CANNBot directory..."
mkdir -p "$CANNBOT_DIR"
step1_summary=""
step1_warns=""
if [ "$TOOL" = "opencode" ]; then
mkdir -p "$CANNBOT_DIR/skills"
for skill_dir in "$SHARED_SKILL_ROOT"/*/; do
[ -d "$skill_dir" ] || continue
name=$(basename "$skill_dir")
echo "$INCLUDED_SKILLS" | grep -qw "$name" || continue
target="$CANNBOT_DIR/skills/$name"
[ -e "$target" ] || [ -L "$target" ] && rm -rf "$target"
done
skill_count=0
for skill_dir in "$SHARED_SKILL_ROOT"/*/; do
[ -d "$skill_dir" ] || continue
name=$(basename "$skill_dir")
echo "$INCLUDED_SKILLS" | grep -qw "$name" || continue
[ -n "$EXCLUDED_SKILL" ] && [ "$name" = "$EXCLUDED_SKILL" ] && continue
ln -sfn "$(realpath "$skill_dir")" "$CANNBOT_DIR/skills/$name"
skill_count=$((skill_count + 1))
done
step1_summary="skills(${skill_count}) "
mkdir -p "$CANNBOT_DIR/agents"
for agent_entry in "$LOCAL_AGENT_ROOT"/*; do
[ -e "$agent_entry" ] || continue
name=$(basename "$agent_entry")
base_name="${name%.md}"
[[ "$base_name" != $INCLUDED_AGENT_PATTERN ]] && continue
target="$CANNBOT_DIR/agents/$name"
[ -e "$target" ] || [ -L "$target" ] && rm -rf "$target"
done
agent_count=0
for agent_entry in "$LOCAL_AGENT_ROOT"/*; do
[ -e "$agent_entry" ] || continue
name=$(basename "$agent_entry")
base_name="${name%.md}"
[[ "$base_name" != $INCLUDED_AGENT_PATTERN ]] && continue
ln -sfn "$(realpath "$agent_entry")" "$CANNBOT_DIR/agents/$name"
agent_count=$((agent_count + 1))
done
step1_summary="${step1_summary}agents(${agent_count})"
ok "Linked: $step1_summary"
else
mkdir -p "$CONFIG_ROOT/skills" "$CONFIG_ROOT/agents"
ok "Prepared: skills/, agents/, rules/"
fi
[ -n "$step1_warns" ] && echo -e "$step1_warns"
echo ""
step "[2/5] Installing configuration..."
config_src="$PLUGIN_ROOT/AGENTS.md"
if [ "$TOOL" = "opencode" ]; then
if [ "$LEVEL" = "project" ]; then
config_target="$INSTALL_BASE/AGENTS.md"
else
config_target="$CONFIG_ROOT/AGENTS.md"
fi
if [ "$LEVEL" = "project" ] && [ "$PLUGIN_ROOT" = "$INSTALL_BASE" ]; then
ok "AGENTS.md already in project directory"
else
if [ "$LEVEL" = "global" ] || { [ "$LEVEL" = "project" ] && [ "$INSTALL_BASE" != "$SCRIPT_DIR" ]; }; then
[ -e "$config_target" ] || [ -L "$config_target" ] && rm -f "$config_target"
PLUGIN_ROOT_ABS="$(realpath "$PLUGIN_ROOT")"
ESCAPED_ROOT="$(echo "$PLUGIN_ROOT_ABS" | sed 's/#/\\#/g')"
sed \
-e "s#bash workflows/scripts/#bash ${ESCAPED_ROOT}/workflows/scripts/#g" \
-e "s#](workflows/#](${ESCAPED_ROOT}/workflows/#g" \
-e "s#\`workflows/#\`${ESCAPED_ROOT}/workflows/#g" \
-e "s#asc-devkit/docs/#${ESCAPED_ROOT}/asc-devkit/docs/#g" \
-e "s#asc-devkit/examples/#${ESCAPED_ROOT}/asc-devkit/examples/#g" \
"$config_src" > "$config_target"
if [ "$LEVEL" = "global" ]; then
ok "AGENTS.md (absolute paths for global mode)"
else
ok "AGENTS.md (absolute paths for project mode)"
fi
else
ln -sf "$config_src" "$config_target"
ok "AGENTS.md"
fi
fi
elif [ "$TOOL" = "claude" ]; then
if [ "$LEVEL" = "project" ]; then
config_target="$INSTALL_BASE/CLAUDE.md"
else
config_target="$CONFIG_ROOT/CLAUDE.md"
fi
if [ "$config_src" = "$config_target" ]; then
info "$(basename "$config_target") already at target location"
elif [ "$LEVEL" = "global" ] || { [ "$LEVEL" = "project" ] && [ "$INSTALL_BASE" != "$SCRIPT_DIR" ]; }; then
[ -e "$config_target" ] || [ -L "$config_target" ] && rm -f "$config_target"
PLUGIN_ROOT_ABS="$(realpath "$PLUGIN_ROOT")"
ESCAPED_ROOT="$(echo "$PLUGIN_ROOT_ABS" | sed 's/#/\\#/g')"
sed \
-e "s#bash workflows/scripts/#bash ${ESCAPED_ROOT}/workflows/scripts/#g" \
-e "s#](workflows/#](${ESCAPED_ROOT}/workflows/#g" \
-e "s#\`workflows/#\`${ESCAPED_ROOT}/workflows/#g" \
-e "s#asc-devkit/docs/#${ESCAPED_ROOT}/asc-devkit/docs/#g" \
-e "s#asc-devkit/examples/#${ESCAPED_ROOT}/asc-devkit/examples/#g" \
"$config_src" > "$config_target"
if [ "$LEVEL" = "global" ]; then
ok "CLAUDE.md (absolute paths for global mode)"
else
ok "CLAUDE.md (absolute paths for project mode)"
fi
else
[ -e "$config_target" ] || [ -L "$config_target" ] && rm -f "$config_target"
ln -sf "$config_src" "$config_target"
ok "CLAUDE.md"
fi
else
if [ "$LEVEL" = "project" ]; then
config_target="$INSTALL_BASE/AGENTS.md"
else
config_target="$CONFIG_ROOT/AGENTS.md"
fi
if [ "$config_src" = "$config_target" ]; then
info "$(basename "$config_target") already at target location"
elif [ "$LEVEL" = "global" ] || { [ "$LEVEL" = "project" ] && [ "$INSTALL_BASE" != "$SCRIPT_DIR" ]; }; then
[ -e "$config_target" ] || [ -L "$config_target" ] && rm -f "$config_target"
PLUGIN_ROOT_ABS="$(realpath "$PLUGIN_ROOT")"
ESCAPED_ROOT="$(echo "$PLUGIN_ROOT_ABS" | sed 's/#/\\#/g')"
sed \
-e "s#bash workflows/scripts/#bash ${ESCAPED_ROOT}/workflows/scripts/#g" \
-e "s#](workflows/#](${ESCAPED_ROOT}/workflows/#g" \
-e "s#\`workflows/#\`${ESCAPED_ROOT}/workflows/#g" \
-e "s#asc-devkit/docs/#${ESCAPED_ROOT}/asc-devkit/docs/#g" \
-e "s#asc-devkit/examples/#${ESCAPED_ROOT}/asc-devkit/examples/#g" \
"$config_src" > "$config_target"
if [ "$LEVEL" = "global" ]; then
ok "AGENTS.md (absolute paths for global mode)"
else
ok "AGENTS.md (absolute paths for project mode)"
fi
else
[ -e "$config_target" ] || [ -L "$config_target" ] && rm -f "$config_target"
ln -sf "$config_src" "$config_target"
ok "AGENTS.md"
fi
fi
if [ -d "$PLUGIN_ROOT/workflows" ]; then
mkdir -p "$CONFIG_ROOT"
ln -sfn "$(realpath "$PLUGIN_ROOT/workflows")" "$CONFIG_ROOT/workflows"
ok "workflows"
else
warn "workflows/ not found, skipping"
fi
echo ""
step "[3/5] Configuring tool discovery..."
if [ "$TOOL" = "opencode" ]; then
ok "Auto-scan: skills/, agents/"
else
DISCOVERY="$CONFIG_ROOT/skills"
for skill_dir in "$SHARED_SKILL_ROOT"/*/; do
[ -d "$skill_dir" ] || continue
name=$(basename "$skill_dir")
echo "$INCLUDED_SKILLS" | grep -qw "$name" || continue
target="$DISCOVERY/$name"
[ -e "$target" ] || [ -L "$target" ] && rm -rf "$target"
done
link_count=0
for skill_dir in "$SHARED_SKILL_ROOT"/*/; do
[ -d "$skill_dir" ] || continue
name=$(basename "$skill_dir")
echo "$INCLUDED_SKILLS" | grep -qw "$name" || continue
[ -n "$EXCLUDED_SKILL" ] && [ "$name" = "$EXCLUDED_SKILL" ] && continue
target="$DISCOVERY/$name"
ln -sfn "$(realpath "$skill_dir")" "$target"
link_count=$((link_count + 1))
done
for link in "$DISCOVERY"/*/; do
link="${link%/}"
[ -L "$link" ] && [ ! -e "$link" ] && rm "$link"
done
ok "Skills: $link_count discovery symlinks"
AGENT_DISCOVERY="$CONFIG_ROOT/agents"
for agent_entry in "$LOCAL_AGENT_ROOT"/*; do
[ -e "$agent_entry" ] || continue
name=$(basename "$agent_entry")
base="${name%.md}"
[[ "$base" != $INCLUDED_AGENT_PATTERN ]] && continue
target="$AGENT_DISCOVERY/$name"
[ -e "$target" ] || [ -L "$target" ] && rm -rf "$target"
done
agent_link_count=0
for agent_entry in "$LOCAL_AGENT_ROOT"/*; do
[ -e "$agent_entry" ] || continue
name=$(basename "$agent_entry")
base="${name%.md}"
[[ "$base" != $INCLUDED_AGENT_PATTERN ]] && continue
target="$AGENT_DISCOVERY/$name"
ln -sfn "$(realpath "$agent_entry")" "$target"
agent_link_count=$((agent_link_count + 1))
done
for link in "$AGENT_DISCOVERY"/*; do
[ -L "$link" ] && [ ! -e "$link" ] && rm "$link"
done
ok "Agents: $agent_link_count discovery symlinks"
fi
echo ""
step "[4/5] Setting up asc-devkit..."
ASC_DEVKIT_DIR="$SCRIPT_DIR/asc-devkit"
if [ -d "$ASC_DEVKIT_DIR" ]; then
cd "$ASC_DEVKIT_DIR"
git checkout . 2>/dev/null || true
git pull --quiet 2>/dev/null || warn "git pull failed, using existing version"
cd "$SCRIPT_DIR"
ok "asc-devkit updated"
else
git clone --quiet https://gitcode.com/cann/asc-devkit.git "$ASC_DEVKIT_DIR" 2>/dev/null && cd "$ASC_DEVKIT_DIR" && git checkout --quiet 31f3ab38 || warn "git clone failed, skipping asc-devkit"
[ -d "$ASC_DEVKIT_DIR" ] && ok "asc-devkit cloned"
fi
if [ -d "$ASC_DEVKIT_DIR" ]; then
python3 "$SHARED_SKILL_ROOT/ascendc-docs-search/scripts/clean_markdown.py" --dir "$ASC_DEVKIT_DIR" --no-backup --quiet > /dev/null 2>&1 || warn "markdown cleanup failed"
fi
if [ "$LEVEL" = "global" ] && [ -d "$ASC_DEVKIT_DIR" ]; then
ln -sfn "$(realpath "$ASC_DEVKIT_DIR")" "$CONFIG_ROOT/asc-devkit"
ok "asc-devkit → $CONFIG_ROOT/"
fi
if [ "$LEVEL" = "project" ] && [ -d "$ASC_DEVKIT_DIR" ]; then
if [ "$INSTALL_BASE" != "$SCRIPT_DIR" ]; then
ln -sfn "$(realpath "$ASC_DEVKIT_DIR")" "$INSTALL_BASE/asc-devkit"
ok "asc-devkit → $INSTALL_BASE/"
fi
fi
echo ""
step "[5/5] Running health check..."
health_ok=true
health_errors=""
for sub in skills agents; do
target="$CANNBOT_DIR/$sub"
if [ -d "$target" ]; then
count=$(ls -d "$target"/* 2>/dev/null | wc -l)
[ "$count" -eq 0 ] && { health_errors="${health_errors}\n ${YELLOW}⚠${NC} $sub/ is empty"; }
else
health_errors="${health_errors}\n ${RED}✗${NC} $sub/ missing"
health_ok=false
fi
done
if [ ! -d "$ASC_DEVKIT_DIR" ]; then
health_errors="${health_errors}\n ${YELLOW}⚠${NC} asc-devkit not available"
fi
if [ "$LEVEL" = "global" ] && [ ! -d "$CONFIG_ROOT/asc-devkit" ]; then
health_errors="${health_errors}\n ${YELLOW}⚠${NC} asc-devkit symlink missing in $CONFIG_ROOT"
fi
if [ "$LEVEL" = "project" ] && [ "$INSTALL_BASE" != "$SCRIPT_DIR" ] && [ ! -d "$INSTALL_BASE/asc-devkit" ]; then
health_errors="${health_errors}\n ${YELLOW}⚠${NC} asc-devkit symlink missing in $INSTALL_BASE"
fi
if [ "$TOOL" = "opencode" ]; then
if [ "$LEVEL" = "project" ]; then
[ -f "$INSTALL_BASE/AGENTS.md" ] || { health_errors="${health_errors}\n ${RED}✗${NC} AGENTS.md missing in project directory"; health_ok=false; }
else
[ -f "$CONFIG_ROOT/AGENTS.md" ] || { health_errors="${health_errors}\n ${RED}✗${NC} AGENTS.md missing"; health_ok=false; }
fi
elif [ "$TOOL" = "claude" ]; then
if [ "$LEVEL" = "project" ]; then
[ -f "$INSTALL_BASE/CLAUDE.md" ] || { health_errors="${health_errors}\n ${RED}✗${NC} CLAUDE.md missing in project directory"; health_ok=false; }
else
[ -f "$CONFIG_ROOT/CLAUDE.md" ] || { health_errors="${health_errors}\n ${RED}✗${NC} CLAUDE.md missing"; health_ok=false; }
fi
else
if [ "$LEVEL" = "project" ]; then
[ -f "$INSTALL_BASE/AGENTS.md" ] || { health_errors="${health_errors}\n ${RED}✗${NC} AGENTS.md missing in project directory"; health_ok=false; }
else
[ -f "$CONFIG_ROOT/AGENTS.md" ] || { health_errors="${health_errors}\n ${RED}✗${NC} AGENTS.md missing"; health_ok=false; }
fi
fi
MANIFEST="$CONFIG_ROOT/cannbot-manifest.json"
SKILLS_JSON="[]"
if [ -d "$CANNBOT_DIR/skills" ]; then
SKILLS_JSON=$(ls -d "$CANNBOT_DIR/skills"/*/ 2>/dev/null | while read d; do
basename "$d"
done | python3 -c "import sys,json; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))" 2>/dev/null || echo "[]")
fi
AGENTS_JSON="[]"
if [ -d "$CANNBOT_DIR/agents" ]; then
AGENTS_JSON=$(ls -d "$CANNBOT_DIR/agents"/* 2>/dev/null | while read d; do
basename "$d"
done | python3 -c "import sys,json; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))" 2>/dev/null || echo "[]")
fi
cat > "$MANIFEST" << MANIFEST_EOF
{
"brand": "CANNBot",
"version": "$VERSION",
"team": "$(basename "$SCRIPT_DIR")",
"level": "$LEVEL",
"tool": "$TOOL",
"installed_skills": $SKILLS_JSON,
"installed_agents": $AGENTS_JSON,
"brand_dir": "$CONFIG_ROOT",
"install_time": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
MANIFEST_EOF
[ -f "$MANIFEST" ] || { health_errors="${health_errors}\n ${RED}✗${NC} Manifest generation failed"; health_ok=false; }
if [ "$health_ok" = true ] && [ -z "$health_errors" ]; then
ok "All checks passed"
else
echo -e "$health_errors"
[ "$health_ok" = true ] && warn "Some warnings, see above" || err "Some checks failed, see above"
fi
echo ""
echo -e " ${GREEN}${BOLD}✓ CANNBot installed successfully!${NC}"
echo ""
echo -e " ${BOLD}Quick Start:${NC}"
if [ "$TOOL" = "opencode" ]; then
echo -e " ${CYAN}1.${NC} 启动 CLI: ${GREEN}opencode${NC}"
echo -e " ${CYAN}2.${NC} 告诉 CANNBot: ${GREEN}${BOLD}帮我开发一个 abs 算子,支持 float16 数据类型,shape 主要是 [1,128]、[4,2048]、[32,4096]${NC}"
elif [ "$TOOL" = "trae" ]; then
echo -e " ${CYAN}1.${NC} 通过 CLI/IDE 启动${NC}"
echo -e " ${CYAN}2.${NC} 告诉 CANNBot: ${GREEN}${BOLD}帮我开发一个 abs 算子,支持 float16 数据类型,shape 主要是 [1,128]、[4,2048]、[32,4096]${NC}"
elif [ "$TOOL" = "cursor" ]; then
echo -e " ${CYAN}1.${NC} 通过 Cursor IDE 启动${NC}"
echo -e " ${CYAN}2.${NC} 告诉 CANNBot: ${GREEN}${BOLD}帮我开发一个 abs 算子,支持 float16 数据类型,shape 主要是 [1,128]、[4,2048]、[32,4096]${NC}"
else
echo -e " ${CYAN}1.${NC} 启动 CLI: ${GREEN}claude${NC}"
echo -e " ${CYAN}2.${NC} 告诉 CANNBot: ${GREEN}${BOLD}帮我开发一个 abs 算子,支持 float16 数据类型,shape 主要是 [1,128]、[4,2048]、[32,4096]${NC}"
fi
echo ""