diff --git a/README.md b/README.md index 1d07ecb..117d454 100644 --- a/README.md +++ b/README.md @@ -308,6 +308,27 @@ open http://127.0.0.1:7891 > ๐Ÿ’ก ่ฏฆ็ป†ๆ•™็จ‹่ฏท็œ‹ [Getting Started ๆŒ‡ๅ—](docs/getting-started.md) +#### ๅธ่ฝฝ + +```bash +# ๆ™ฎ้€šๅธ่ฝฝ๏ผˆๆŽจ่ๅ…ˆ็”จ่ฟ™ไธช๏ผ‰ +chmod +x uninstall.sh && ./uninstall.sh + +# ๆทฑๅบฆๅธ่ฝฝ๏ผˆ้ขๅค–ๆธ…็†ๅฎ‰่ฃ…ๅค‡ไปฝ๏ผ‰ +./uninstall.sh --purge +``` + +ๅธ่ฝฝ่„šๆœฌไผšๆ‰ง่กŒ๏ผš +- โœ… ๅค‡ไปฝ็Žฐๆœ‰ๆ•ฐๆฎๅˆฐ `~/.openclaw/backups/pre-uninstall-*` +- โœ… ๅˆ ้™คไธ‰็œๅ…ญ้ƒจ workspace๏ผˆ`~/.openclaw/workspace-{taizi,zhongshu,menxia,...}`๏ผ‰ +- โœ… ไปŽ `openclaw.json` ๆณจ้”€ไธ‰็œๅ…ญ้ƒจ agents +- โœ… ๆธ…็†ไป“ๅบ“ `data/` ไธ‹ๅฎ‰่ฃ…่„šๆœฌๅˆๅง‹ๅŒ–็š„ๆ–‡ไปถ + +`--purge` ไผš้ขๅค–ๆ‰ง่กŒ๏ผš +- โœ… ๅˆ ้™ค `~/.openclaw/agents/` ไธ‹ไธ‰็œๅ…ญ้ƒจ็›ธๅ…ณ็›ฎๅฝ•๏ผˆ่‹ฅๅญ˜ๅœจ๏ผ‰ +- โœ… ๆธ…็†ๅฎ‰่ฃ…่„šๆœฌไบง็”Ÿ็š„ `pre-install-*` ๅค‡ไปฝ +- โœ… ๆธ…็† `openclaw.json.bak.sansheng-*` ็ญ‰้…็ฝฎๅค‡ไปฝๆ–‡ไปถ + --- ## ๐Ÿ›๏ธ ๆžถๆž„ diff --git a/README_EN.md b/README_EN.md index 106493b..1aa4852 100644 --- a/README_EN.md +++ b/README_EN.md @@ -225,6 +225,27 @@ open http://127.0.0.1:7891 > ๐Ÿ“– See [Getting Started Guide](docs/getting-started.md) for detailed walkthrough. +### Uninstall + +```bash +# Standard uninstall (recommended first) +chmod +x uninstall.sh && ./uninstall.sh + +# Deep uninstall (extra cleanup of installer backups) +./uninstall.sh --purge +``` + +The uninstall script will: +- โœ… Back up existing data to `~/.openclaw/backups/pre-uninstall-*` +- โœ… Remove Three Departments & Six Ministries workspaces (`~/.openclaw/workspace-{taizi,zhongshu,menxia,...}`) +- โœ… Unregister related agents from `openclaw.json` +- โœ… Clean installer-initialized files in the repo `data/` directory + +`--purge` additionally: +- โœ… Removes related directories under `~/.openclaw/agents/` (if present) +- โœ… Cleans installer-generated `pre-install-*` backups +- โœ… Cleans project-generated backups like `openclaw.json.bak.sansheng-*` + --- ## ๐Ÿ›๏ธ Architecture diff --git a/uninstall.sh b/uninstall.sh new file mode 100644 index 0000000..59e775b --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,305 @@ +#!/bin/bash +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# ไธ‰็œๅ…ญ้ƒจ ยท OpenClaw Multi-Agent System ไธ€้”ฎๅธ่ฝฝ่„šๆœฌ +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +set -e + +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OC_HOME="$HOME/.openclaw" +OC_CFG="$OC_HOME/openclaw.json" + +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m' + +PURGE=false + +banner() { + echo "" + echo -e "${BLUE}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" + echo -e "${BLUE}โ•‘ ๐Ÿงน ไธ‰็œๅ…ญ้ƒจ ยท OpenClaw Multi-Agent โ•‘${NC}" + echo -e "${BLUE}โ•‘ ๅธ่ฝฝๅ‘ๅฏผ โ•‘${NC}" + echo -e "${BLUE}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" + echo "" +} + +usage() { + echo "็”จๆณ•: ./uninstall.sh [--purge]" + echo "" + echo "้€‰้กน:" + echo " --purge ๆ‰ง่กŒๆทฑๅบฆๆธ…็†๏ผˆๆธ…็†ๅฎ‰่ฃ…่„šๆœฌไบง็”Ÿ็š„ๅค‡ไปฝ๏ผ‰" + echo " -h, --help ๆ˜พ็คบๅธฎๅŠฉ" +} + +log() { echo -e "${GREEN}โœ… $1${NC}"; } +warn() { echo -e "${YELLOW}โš ๏ธ $1${NC}"; } +error() { echo -e "${RED}โŒ $1${NC}"; } +info() { echo -e "${BLUE}โ„น๏ธ $1${NC}"; } + +AGENTS=(taizi zhongshu menxia shangshu hubu libu bingbu xingbu gongbu libu_hr zaochao) + +parse_args() { + while [ "$#" -gt 0 ]; do + case "$1" in + --purge) + PURGE=true + ;; + -h|--help) + usage + exit 0 + ;; + *) + error "ๆœช็Ÿฅๅ‚ๆ•ฐ: $1" + usage + exit 1 + ;; + esac + shift + done +} + +# โ”€โ”€ Step 0: ไพ่ต–ๆฃ€ๆŸฅ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +check_deps() { + info "ๆฃ€ๆŸฅ็Žฏๅขƒ..." + + if [ ! -d "$OC_HOME" ]; then + warn "ๆœชๆ‰พๅˆฐ OpenClaw ็›ฎๅฝ•: $OC_HOME๏ผˆๅฏ่ƒฝๅทฒๅธ่ฝฝ๏ผ‰" + else + log "OpenClaw ็›ฎๅฝ•: $OC_HOME" + fi + + if [ ! -f "$OC_CFG" ]; then + warn "ๆœชๆ‰พๅˆฐ openclaw.json๏ผˆๅฐ†่ทณ่ฟ‡ๆณจ้”€ๆญฅ้ชค๏ผ‰" + else + log "openclaw.json: $OC_CFG" + fi +} + +# โ”€โ”€ Step 1: ๅค‡ไปฝๅทฒๆœ‰ๆ•ฐๆฎ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +backup_existing() { + BACKUP_DIR="$OC_HOME/backups/pre-uninstall-$(date +%Y%m%d-%H%M%S)" + NEED_BACKUP=false + + for d in "$OC_HOME"/workspace-*/; do + if [ -d "$d" ]; then + NEED_BACKUP=true + break + fi + done + + if [ -f "$OC_CFG" ] || [ -d "$OC_HOME/agents" ]; then + NEED_BACKUP=true + fi + + if $NEED_BACKUP; then + info "ๆฃ€ๆต‹ๅˆฐๅทฒๆœ‰ๆ•ฐๆฎ๏ผŒ่‡ชๅŠจๅค‡ไปฝไธญ..." + mkdir -p "$BACKUP_DIR" + + for d in "$OC_HOME"/workspace-*/; do + if [ -d "$d" ]; then + ws_name=$(basename "$d") + cp -R "$d" "$BACKUP_DIR/$ws_name" + fi + done + + if [ -f "$OC_CFG" ]; then + cp "$OC_CFG" "$BACKUP_DIR/openclaw.json" + fi + + if [ -d "$OC_HOME/agents" ]; then + cp -R "$OC_HOME/agents" "$BACKUP_DIR/agents" + fi + + log "ๅทฒๅค‡ไปฝๅˆฐ: $BACKUP_DIR" + else + warn "ๆœชๅ‘็Žฐๅฏๅค‡ไปฝๅ†…ๅฎน๏ผŒ่ทณ่ฟ‡" + fi +} + +# โ”€โ”€ Step 2: ๅˆ ้™ค Workspace โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +remove_workspaces() { + info "ๅˆ ้™คไธ‰็œๅ…ญ้ƒจ Workspace..." + removed=0 + + for agent in "${AGENTS[@]}"; do + ws="$OC_HOME/workspace-$agent" + if [ -d "$ws" ]; then + rm -rf "$ws" + removed=$((removed+1)) + log "ๅทฒๅˆ ้™ค: $ws" + fi + done + + if [ "$removed" -eq 0 ]; then + warn "ๆœชๆ‰พๅˆฐไธ‰็œๅ…ญ้ƒจ Workspace๏ผˆๅฏ่ƒฝๅทฒๅˆ ้™ค๏ผ‰" + fi +} + +# โ”€โ”€ Step 3: ๆณจ้”€ Agents โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +unregister_agents() { + info "ไปŽ openclaw.json ๆณจ้”€ไธ‰็œๅ…ญ้ƒจ Agents..." + + if [ ! -f "$OC_CFG" ]; then + warn "openclaw.json ไธๅญ˜ๅœจ๏ผŒ่ทณ่ฟ‡ๆณจ้”€" + return + fi + + if ! command -v python3 &>/dev/null; then + warn "ๆœชๆ‰พๅˆฐ python3๏ผŒ่ทณ่ฟ‡ agents ๆณจ้”€" + warn "่ฏทๆ‰‹ๅŠจ็ผ–่พ‘ openclaw.json ็งป้™คไธ‰็œๅ…ญ้ƒจ agents" + return + fi + + cp "$OC_CFG" "$OC_CFG.bak.sansheng-uninstall-$(date +%Y%m%d-%H%M%S)" + log "ๅทฒๅค‡ไปฝ้…็ฝฎ: $OC_CFG.bak.*" + + python3 << 'PYEOF' +import json +import pathlib +import tempfile +import shutil + +cfg_path = pathlib.Path.home() / '.openclaw' / 'openclaw.json' + +try: + cfg = json.loads(cfg_path.read_text()) +except Exception as e: + print(f'ERROR: Failed to parse {cfg_path}: {e}') + exit(1) + +remove_ids = { + 'taizi', 'zhongshu', 'menxia', 'shangshu', + 'hubu', 'libu', 'bingbu', 'xingbu', 'gongbu', + 'libu_hr', 'zaochao', +} + +agents_cfg = cfg.get('agents', {}) +agents_list = agents_cfg.get('list', []) +before = len(agents_list) + +agents_cfg['list'] = [a for a in agents_list if a.get('id') not in remove_ids] +cfg['agents'] = agents_cfg + +# ๅŽŸๅญๅ†™ๅ…ฅ๏ผšๅ…ˆๅ†™ไธดๆ—ถๆ–‡ไปถ๏ผŒๅ† mv +temp_fd, temp_path = tempfile.mkstemp(dir=cfg_path.parent, suffix='.tmp') +try: + with open(temp_fd, 'w') as f: + json.dump(cfg, f, ensure_ascii=False, indent=2) + shutil.move(temp_path, cfg_path) + print(f'Done: {before - len(agents_cfg["list"])} agents removed') +except Exception as e: + pathlib.Path(temp_path).unlink(missing_ok=True) + print(f'ERROR: Failed to write config: {e}') + exit(1) +PYEOF + + log "Agents ๆณจ้”€ๅฎŒๆˆ" +} + +# โ”€โ”€ Step 4: ๆธ…็†ไป“ๅบ“ๆ•ฐๆฎ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +cleanup_repo_data() { + info "ๆธ…็†ไป“ๅบ“ data ๅˆๅง‹ๅŒ–ๆ–‡ไปถ..." + + if [ ! -d "$REPO_DIR/data" ]; then + warn "ๆœชๆ‰พๅˆฐ $REPO_DIR/data๏ผŒ่ทณ่ฟ‡" + return + fi + + FILES=( + "$REPO_DIR/data/live_status.json" + "$REPO_DIR/data/agent_config.json" + "$REPO_DIR/data/model_change_log.json" + "$REPO_DIR/data/pending_model_changes.json" + "$REPO_DIR/data/tasks_source.json" + ) + + removed_any=false + for f in "${FILES[@]}"; do + if [ -f "$f" ]; then + rm -f "$f" + log "ๅทฒๅˆ ้™ค: $f" + removed_any=true + fi + done + + if ! $removed_any; then + warn "ๆœชๅ‘็Žฐ้œ€่ฆๆธ…็†็š„ๅˆๅง‹ๅŒ–ๆ–‡ไปถ" + fi +} + +# โ”€โ”€ Step 5: ๆทฑๅบฆๆธ…็†๏ผˆ--purge๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +purge_cleanup() { + if ! $PURGE; then + return + fi + + info "ๆ‰ง่กŒ --purge ๆทฑๅบฆๆธ…็†..." + + # 1) ๅˆ ้™ค ~/.openclaw/agents ไธ‹็›ธๅ…ณ็›ฎๅฝ•๏ผˆๅฆ‚ๆžœๅญ˜ๅœจ๏ผ‰ + for agent in "${AGENTS[@]}"; do + if [ -d "$OC_HOME/agents/$agent" ]; then + rm -rf "$OC_HOME/agents/$agent" + log "ๅทฒๅˆ ้™ค: $OC_HOME/agents/$agent" + fi + done + + # 2) ๆธ…็†ๆœฌ้กน็›ฎ็”Ÿๆˆ็š„้…็ฝฎๅค‡ไปฝ + rm -f "$OC_CFG".bak.sansheng-* 2>/dev/null || true + log "ๅทฒๆธ…็† openclaw.json ็›ธๅ…ณๅค‡ไปฝ๏ผˆsansheng ๅ‰็ผ€๏ผ‰" + + # 3) ๆธ…็†ๅฎ‰่ฃ…่„šๆœฌไบง็”Ÿ็š„ๅค‡ไปฝ๏ผˆไป… pre-install-*, ไธๅˆ  pre-uninstall-*๏ผ‰ + if [ -d "$OC_HOME/backups" ]; then + rm -rf "$OC_HOME/backups"/pre-install-* 2>/dev/null || true + log "ๅทฒๆธ…็† pre-install ๅค‡ไปฝ" + fi + + # 4) ๆธ…็†ๆœฌไป“ๅบ“ data ็›ฎๅฝ•๏ผˆ่‹ฅไธบ็ฉบๅˆ™ๅˆ ้™ค๏ผ‰ + if [ -d "$REPO_DIR/data" ] && [ -z "$(ls -A "$REPO_DIR/data" 2>/dev/null)" ]; then + rmdir "$REPO_DIR/data" 2>/dev/null || true + log "data ็›ฎๅฝ•ไธบ็ฉบ๏ผŒๅทฒๅˆ ้™ค: $REPO_DIR/data" + fi +} + +# โ”€โ”€ Step 6: ้‡ๅฏ Gateway โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +restart_gateway() { + info "้‡ๅฏ OpenClaw Gateway..." + if command -v openclaw &>/dev/null; then + if openclaw gateway restart 2>/dev/null; then + log "Gateway ้‡ๅฏๆˆๅŠŸ" + else + warn "Gateway ้‡ๅฏๅคฑ่ดฅ๏ผŒ่ฏทๆ‰‹ๅŠจ้‡ๅฏ๏ผšopenclaw gateway restart" + fi + else + warn "ๆœชๆ‰พๅˆฐ openclaw CLI๏ผŒ่ทณ่ฟ‡ Gateway ้‡ๅฏ" + fi +} + +# โ”€โ”€ Main โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +parse_args "$@" +banner +check_deps +backup_existing +remove_workspaces +unregister_agents +cleanup_repo_data +purge_cleanup +restart_gateway + +echo "" +echo -e "${GREEN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}" +if $PURGE; then + echo -e "${GREEN}โ•‘ ๐Ÿงน ไธ‰็œๅ…ญ้ƒจๆทฑๅบฆๅธ่ฝฝๅฎŒๆˆ๏ผˆ--purge๏ผ‰๏ผ โ•‘${NC}" +else + echo -e "${GREEN}โ•‘ ๐Ÿงน ไธ‰็œๅ…ญ้ƒจๅธ่ฝฝๅฎŒๆˆ๏ผ โ•‘${NC}" +fi +echo -e "${GREEN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}" +echo "" +echo "ๅทฒๆ‰ง่กŒ๏ผš" +echo " 1. ๅค‡ไปฝ็Žฐๆœ‰ๆ•ฐๆฎๅˆฐ ~/.openclaw/backups/pre-uninstall-*" +echo " 2. ๅˆ ้™คไธ‰็œๅ…ญ้ƒจ workspace๏ผˆ~/.openclaw/workspace-*๏ผ‰" +echo " 3. ไปŽ openclaw.json ๆณจ้”€ไธ‰็œๅ…ญ้ƒจ agents" +echo " 4. ๆธ…็†ๆœฌไป“ๅบ“ data/ ไธ‹ๅˆๅง‹ๅŒ–ๆ–‡ไปถ" +if $PURGE; then + echo " 5. ๆทฑๅบฆๆธ…็†๏ผˆๅฎ‰่ฃ…ๅค‡ไปฝใ€sansheng-* ้…็ฝฎๅค‡ไปฝ๏ผ‰" +else + echo " 5. ๅฆ‚้œ€ๆทฑๅบฆๆธ…็†๏ผŒ่ฏทๆ‰ง่กŒ: ./uninstall.sh --purge" +fi +echo ""