run_local_skills.sh 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/bin/bash
  2. set -euo pipefail
  3. # 本地一键 skills 同步与规范校验。
  4. # 默认行为:
  5. # 1) 同步各技能的 references/terminology.md 到统一占位模板
  6. # 2) 使用 skill-creator 的 quick_validate.py 校验每个技能
  7. # 3) 校验 agents/openai.yaml 关键字段与默认 prompt 的技能名引用
  8. #
  9. # 可选参数:
  10. # --sync-only 仅执行同步
  11. # --validate-only 仅执行校验
  12. scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  13. cd "${scriptDir}"
  14. doSync=1
  15. doValidate=1
  16. while (($# > 0)); do
  17. case "$1" in
  18. --sync-only)
  19. doValidate=0
  20. ;;
  21. --validate-only)
  22. doSync=0
  23. ;;
  24. -h | --help)
  25. echo "用法: bash ./run_local_skills.sh [--sync-only|--validate-only]"
  26. exit 0
  27. ;;
  28. *)
  29. echo "[错误] 未知参数: $1"
  30. echo "用法: bash ./run_local_skills.sh [--sync-only|--validate-only]"
  31. exit 2
  32. ;;
  33. esac
  34. shift
  35. done
  36. validator="/root/.codex/skills/.system/skill-creator/scripts/quick_validate.py"
  37. if [[ ! -f "${validator}" ]]; then
  38. echo "[错误] 未找到技能校验脚本: ${validator}"
  39. exit 1
  40. fi
  41. mapfile -t skillDirs < <(find skills -mindepth 1 -maxdepth 1 -type d ! -name shared | sort)
  42. if [[ ${#skillDirs[@]} -eq 0 ]]; then
  43. echo "[信息] 未发现可处理的技能目录(skills/*,排除 skills/shared)"
  44. exit 0
  45. fi
  46. echo "===================================================="
  47. echo "本地 Skills 任务启动"
  48. echo " - sync=${doSync}"
  49. echo " - validate=${doValidate}"
  50. echo " - skills=${#skillDirs[@]}"
  51. echo "===================================================="
  52. if [[ ${doSync} -eq 1 ]]; then
  53. echo "[阶段] 同步术语占位文档..."
  54. for skillDir in "${skillDirs[@]}"; do
  55. termFile="${skillDir}/references/terminology.md"
  56. mkdir -p "$(dirname "${termFile}")"
  57. if [[ ! -f "${termFile}" ]]; then
  58. cat > "${termFile}" <<'EOF'
  59. # 术语字典
  60. - 统一术语定义复用共享文档:`../../shared/terminology.md`。
  61. - 如出现本技能专属术语,可在本文件追加扩展,不覆盖共享定义。
  62. EOF
  63. echo " - synced ${termFile} (created)"
  64. elif grep -Fq '../../shared/terminology.md' "${termFile}"; then
  65. echo " - synced ${termFile} (already linked)"
  66. else
  67. tmpFile="$(mktemp)"
  68. cat > "${tmpFile}" <<'EOF'
  69. # 术语字典
  70. - 统一术语定义复用共享文档:`../../shared/terminology.md`。
  71. - 如出现本技能专属术语,可在本文件追加扩展,不覆盖共享定义。
  72. EOF
  73. cat "${termFile}" >> "${tmpFile}"
  74. mv "${tmpFile}" "${termFile}"
  75. echo " - synced ${termFile} (prefixed)"
  76. fi
  77. done
  78. fi
  79. if [[ ${doValidate} -eq 1 ]]; then
  80. echo "[阶段] 校验技能结构与 agents 元数据..."
  81. for skillDir in "${skillDirs[@]}"; do
  82. skillFile="${skillDir}/SKILL.md"
  83. openaiFile="${skillDir}/agents/openai.yaml"
  84. python3 "${validator}" "${skillDir}" >/dev/null
  85. if [[ ! -f "${openaiFile}" ]]; then
  86. echo "[错误] 缺少 agents/openai.yaml: ${openaiFile}"
  87. exit 1
  88. fi
  89. if ! rg -q '^[[:space:]]*display_name:' "${openaiFile}"; then
  90. echo "[错误] 缺少 interface.display_name: ${openaiFile}"
  91. exit 1
  92. fi
  93. if ! rg -q '^[[:space:]]*short_description:' "${openaiFile}"; then
  94. echo "[错误] 缺少 interface.short_description: ${openaiFile}"
  95. exit 1
  96. fi
  97. if ! rg -q '^[[:space:]]*default_prompt:' "${openaiFile}"; then
  98. echo "[错误] 缺少 interface.default_prompt: ${openaiFile}"
  99. exit 1
  100. fi
  101. skillName="$(awk '
  102. BEGIN { inFm=0 }
  103. /^---[[:space:]]*$/ { if (inFm==0) { inFm=1; next } else { exit } }
  104. inFm==1 && /^name:[[:space:]]*/ {
  105. sub(/^name:[[:space:]]*/, "", $0)
  106. print $0
  107. exit
  108. }
  109. ' "${skillFile}")"
  110. if [[ -z "${skillName}" ]]; then
  111. echo "[错误] 未能从 ${skillFile} 读取 name"
  112. exit 1
  113. fi
  114. if ! grep -Fq "\$${skillName}" "${openaiFile}"; then
  115. echo "[错误] default_prompt 未引用 \$${skillName}: ${openaiFile}"
  116. exit 1
  117. fi
  118. echo " - valid ${skillDir}"
  119. done
  120. fi
  121. echo "===================================================="
  122. echo "本地 Skills 任务完成"
  123. echo "===================================================="