deploy-to-openclaw.sh 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/usr/bin/env bash
  2. # OpenClaw WeChat Skill Deploy v1.2.0 (Bash, Linux/Mac)
  3. #
  4. # Usage:
  5. # ./deploy-to-openclaw.sh # normal deploy
  6. # ./deploy-to-openclaw.sh --dry-run # preview
  7. # SKILLS_ROOT=/custom/path ./deploy-to-openclaw.sh
  8. set -euo pipefail
  9. DRY_RUN=0
  10. for arg in "$@"; do
  11. case "$arg" in
  12. --dry-run|-DryRun) DRY_RUN=1 ;;
  13. esac
  14. done
  15. SOURCE_ROOT="${SOURCE_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
  16. SKILLS_ROOT="${SKILLS_ROOT:-$HOME/.openclaw/skills}"
  17. CATEGORIES=("wechat")
  18. # Colors (disabled if not TTY)
  19. if [ -t 1 ]; then
  20. CYAN=$'\e[36m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m'; RED=$'\e[31m'; NC=$'\e[0m'
  21. else
  22. CYAN=""; GREEN=""; YELLOW=""; RED=""; NC=""
  23. fi
  24. echo "=== OpenClaw WeChat Skill Deploy v1.2.0 ==="
  25. echo "Source: $SOURCE_ROOT"
  26. echo "Target: $SKILLS_ROOT"
  27. [ "$DRY_RUN" -eq 1 ] && echo "${YELLOW}[DRY RUN]${NC}"
  28. [ "$DRY_RUN" -eq 0 ] && mkdir -p "$SKILLS_ROOT"
  29. deployed=0; skipped=0; errors=0
  30. # JSON validator: prefer python3, fallback to node, else skip validation
  31. validate_json() {
  32. local file="$1"
  33. if command -v python3 >/dev/null 2>&1; then
  34. python3 -c "import json,sys; json.load(open(sys.argv[1],encoding='utf-8'))" "$file" >/dev/null 2>&1
  35. elif command -v node >/dev/null 2>&1; then
  36. node -e "JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'))" "$file" >/dev/null 2>&1
  37. else
  38. return 0
  39. fi
  40. }
  41. for cat in "${CATEGORIES[@]}"; do
  42. cat_path="$SOURCE_ROOT/$cat"
  43. [ -d "$cat_path" ] || continue
  44. echo "${CYAN}--- $cat ---${NC}"
  45. for skill_dir in "$cat_path"/*/; do
  46. [ -d "$skill_dir" ] || continue
  47. name=$(basename "$skill_dir")
  48. sm="$skill_dir/SKILL.md"
  49. ac="$skill_dir/api-config.json"
  50. if [ ! -f "$sm" ]; then
  51. skipped=$((skipped+1)); continue
  52. fi
  53. # api-config.json is optional reference material in v1.1.0+
  54. if [ -f "$ac" ] && ! validate_json "$ac"; then
  55. echo " ${RED}[ERR] $name: invalid api-config.json${NC}"
  56. errors=$((errors+1)); continue
  57. fi
  58. dest="$SKILLS_ROOT/$name"
  59. if [ "$DRY_RUN" -eq 1 ]; then
  60. if [ -d "$dest" ]; then echo " [UPDATE] $name"; else echo " [NEW] $name"; fi
  61. else
  62. rm -rf "$dest"
  63. mkdir -p "$dest"
  64. # copy files (non-recursive, skill files only)
  65. find "$skill_dir" -maxdepth 1 -type f -exec cp {} "$dest/" \;
  66. echo " ${GREEN}[OK] $name${NC}"
  67. fi
  68. deployed=$((deployed+1))
  69. done
  70. done
  71. echo "Result: $deployed deployed, $skipped skipped, $errors errors"
  72. # ---- Workflows ----
  73. wf_source="$SOURCE_ROOT/workflows"
  74. wf_target="$(dirname "$SKILLS_ROOT")/workflows"
  75. if [ -d "$wf_source" ]; then
  76. echo "${CYAN}--- workflows ---${NC}"
  77. if [ "$DRY_RUN" -eq 0 ]; then
  78. mkdir -p "$wf_target"
  79. find "$wf_source" -maxdepth 1 -type f | while read -r f; do
  80. cp "$f" "$wf_target/"
  81. echo " ${GREEN}[OK] $(basename "$f")${NC}"
  82. done
  83. else
  84. find "$wf_source" -maxdepth 1 -type f | while read -r f; do
  85. echo " [WORKFLOW] $(basename "$f")"
  86. done
  87. fi
  88. fi
  89. # ---- Credentials ----
  90. parent="$(dirname "$SKILLS_ROOT")"
  91. if [ "$DRY_RUN" -eq 0 ]; then
  92. tpl="$SOURCE_ROOT/__config/wechat-credentials.template.json"
  93. if [ -f "$tpl" ]; then
  94. cp "$tpl" "$parent/wechat-credentials.template.json"
  95. echo "Template: $parent/wechat-credentials.template.json"
  96. cred_file="$parent/wechat-credentials.json"
  97. if [ ! -f "$cred_file" ]; then
  98. cp "$tpl" "$cred_file"
  99. echo "${YELLOW}[!] Created $cred_file - please edit wechatApiBase to your server address${NC}"
  100. fi
  101. fi
  102. fi
  103. # ---- Auto-reply daemon + config ----
  104. daemon_src="$SOURCE_ROOT/daemon/auto-reply-daemon.js"
  105. daemon_dst="$parent/auto-reply-daemon.js"
  106. cfg_tpl_src="$SOURCE_ROOT/daemon/wechat-auto-reply-config.template.json"
  107. cfg_tpl_dst="$parent/wechat-auto-reply-config.template.json"
  108. cfg_dst="$parent/wechat-auto-reply-config.json"
  109. if [ -f "$daemon_src" ]; then
  110. echo "${CYAN}--- auto-reply daemon ---${NC}"
  111. if [ "$DRY_RUN" -eq 1 ]; then
  112. echo " [DAEMON] $daemon_dst"
  113. echo " [CONFIG-TEMPLATE] $cfg_tpl_dst"
  114. [ ! -f "$cfg_dst" ] && echo " [CONFIG-DEFAULT] $cfg_dst"
  115. else
  116. cp "$daemon_src" "$daemon_dst"
  117. chmod +x "$daemon_dst" 2>/dev/null || true
  118. echo " ${GREEN}[OK] $daemon_dst${NC}"
  119. if [ -f "$cfg_tpl_src" ]; then
  120. cp "$cfg_tpl_src" "$cfg_tpl_dst"
  121. echo " ${GREEN}[OK] $cfg_tpl_dst${NC}"
  122. if [ ! -f "$cfg_dst" ]; then
  123. cp "$cfg_tpl_src" "$cfg_dst"
  124. echo " ${YELLOW}[!] Created default config: $cfg_dst (edit to customize reply rules)${NC}"
  125. fi
  126. fi
  127. fi
  128. fi
  129. [ "$DRY_RUN" -eq 0 ] && echo "${GREEN}Done!${NC}"
  130. exit $([ "$errors" -gt 0 ] && echo 1 || echo 0)