154 lines
5.3 KiB
Bash
Executable File
154 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
||
set -e
|
||
|
||
# Vala SkillHub 自动同步脚本
|
||
# 自动检测本地skill变更并推送到SkillHub
|
||
# 遵循use_vala_skillhub.vala技能规范
|
||
|
||
# 加载配置
|
||
CONFIG_FILE="/root/.openclaw/workspace-xiaobian/.vala_skillhub_config"
|
||
if [ ! -f "${CONFIG_FILE}" ]; then
|
||
echo "错误:配置文件 ${CONFIG_FILE} 不存在,请先创建配置文件"
|
||
exit 1
|
||
fi
|
||
source "${CONFIG_FILE}"
|
||
|
||
# 检查必填配置
|
||
if [ -z "${GITEA_TOKEN}" ]; then
|
||
echo "错误:GITEA_TOKEN 未配置,请在 ${CONFIG_FILE} 中填写有效的Gitea API Token"
|
||
exit 1
|
||
fi
|
||
if [ -z "${SOURCE_NAME}" ]; then
|
||
echo "错误:SOURCE_NAME 未配置,请在 ${CONFIG_FILE} 中填写当前数字员工名称"
|
||
exit 1
|
||
fi
|
||
|
||
# 配置路径
|
||
SKILLS_DIR="/root/.openclaw/workspace-xiaobian/skills"
|
||
HASH_FILE="/root/.openclaw/workspace-xiaobian/.vala_skill_hashes"
|
||
TMP_DIR="/root/.openclaw/workspace-xiaobian/tmp/skill_push"
|
||
|
||
# 创建必要目录
|
||
mkdir -p "${TMP_DIR}"
|
||
touch "${HASH_FILE}"
|
||
|
||
# 计算skill目录哈希函数
|
||
compute_skill_hash() {
|
||
local skill_dir="$1"
|
||
(cd "${skill_dir}" && find . -type f -not -path '*/\.*' | LC_ALL=C sort | while read f; do echo "FILE:$f"; cat "$f"; done | sha256sum | awk '{print $1}')
|
||
}
|
||
|
||
# 统计变量
|
||
synced_count=0
|
||
skipped_count=0
|
||
synced_skills=()
|
||
|
||
echo "=== Vala SkillHub 自动同步开始 $(date +"%Y-%m-%d %H:%M:%S") ==="
|
||
echo "当前数字员工:${SOURCE_NAME}"
|
||
echo "SkillHub地址:${GITEA_URL}/${GITEA_OWNER}"
|
||
echo ""
|
||
|
||
# 遍历所有skill目录
|
||
for skill_dir in "${SKILLS_DIR}"/*/; do
|
||
skill_name=$(basename "${skill_dir}")
|
||
|
||
# 跳过use_vala_skillhub自身(兼容带和不带.vala后缀的命名)
|
||
if [[ "${skill_name}" == "use_vala_skillhub"* ]]; then
|
||
continue
|
||
fi
|
||
|
||
echo "检查技能:${skill_name}"
|
||
|
||
# 计算当前哈希
|
||
current_hash=$(compute_skill_hash "${skill_dir}")
|
||
|
||
# 读取上次推送的哈希
|
||
stored_hash=$(grep "^${skill_name} " "${HASH_FILE}" | awk '{print $2}' || true)
|
||
|
||
if [ "${current_hash}" = "${stored_hash}" ]; then
|
||
echo "✅ 无变更,跳过推送"
|
||
skipped_count=$((skipped_count + 1))
|
||
echo ""
|
||
continue
|
||
fi
|
||
|
||
echo "🔄 检测到变更,开始推送..."
|
||
synced_count=$((synced_count + 1))
|
||
synced_skills+=("${skill_name}")
|
||
|
||
repo_name="${skill_name}.${SOURCE_NAME}"
|
||
|
||
# 检查远程仓库是否存在
|
||
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
||
"${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${repo_name}" \
|
||
-H "Authorization: token ${GITEA_TOKEN}")
|
||
|
||
# 如果不存在则创建仓库
|
||
if [ "${http_code}" = "404" ]; then
|
||
echo "📦 远程仓库不存在,创建新仓库:${repo_name}"
|
||
# 读取skill描述
|
||
desc=""
|
||
if [ -f "${skill_dir}/SKILL.md" ]; then
|
||
# 从SKILL.md提取description
|
||
desc=$(grep -A5 "description:" "${skill_dir}/SKILL.md" | head -3 | tr '\n' ' ' | sed 's/.*description:[[:space:]]*//g' | sed 's/---.*//g' | sed 's/"/\\"/g')
|
||
fi
|
||
curl -s -X POST "${GITEA_URL}/api/v1/orgs/${GITEA_OWNER}/repos" \
|
||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"name": "'"${repo_name}"'", "private": false, "description": "'"${desc}"'", "auto_init": false}' > /dev/null
|
||
fi
|
||
|
||
# 复制到临时目录
|
||
rm -rf "${TMP_DIR}/${repo_name}"
|
||
mkdir -p "${TMP_DIR}/${repo_name}"
|
||
cp -r "${skill_dir}"/* "${TMP_DIR}/${repo_name}/"
|
||
cp -r "${skill_dir}"/.[!.]* "${TMP_DIR}/${repo_name}/" 2>/dev/null || true
|
||
|
||
# 执行git推送
|
||
cd "${TMP_DIR}/${repo_name}"
|
||
git init > /dev/null 2>&1
|
||
git checkout -b main > /dev/null 2>&1
|
||
git config user.name "OpenClaw Bot"
|
||
git config user.email "bot@valavala.com"
|
||
git add -A > /dev/null 2>&1
|
||
git commit -m "auto-sync: ${skill_name} $(date +%Y-%m-%d_%H:%M)" > /dev/null 2>&1
|
||
git remote add origin "https://oauth2:${GITEA_TOKEN}@${GITEA_URL#https://}/${GITEA_OWNER}/${repo_name}.git" > /dev/null 2>&1
|
||
git push -u origin main --force > /dev/null 2>&1
|
||
cd - > /dev/null
|
||
|
||
# 清理临时目录
|
||
rm -rf "${TMP_DIR}/${repo_name}"
|
||
|
||
# 更新哈希记录
|
||
grep -v "^${skill_name} " "${HASH_FILE}" > "${HASH_FILE}.tmp" || true
|
||
echo "${skill_name} ${current_hash}" >> "${HASH_FILE}.tmp"
|
||
mv "${HASH_FILE}.tmp" "${HASH_FILE}"
|
||
|
||
echo "✅ 推送完成:${repo_name}"
|
||
echo ""
|
||
done
|
||
|
||
# 输出同步摘要
|
||
echo "=== 同步完成 $(date +"%Y-%m-%d %H:%M:%S") ==="
|
||
echo "本次同步技能数:${synced_count}"
|
||
if [ ${synced_count} -gt 0 ]; then
|
||
echo "已同步技能:${synced_skills[*]}"
|
||
# 推送成功后发送通知给李若松
|
||
APP_ID=$(jq -r '.apps[0].appId' /root/.openclaw/credentials/xiaobian/config.json)
|
||
APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials/xiaobian/config.json)
|
||
FEISHU_TOKEN=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" | jq -r '.tenant_access_token')
|
||
|
||
# 发送消息给李若松
|
||
curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id" \
|
||
-H "Authorization: Bearer $FEISHU_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"receive_id": "4aagb443", "msg_type": "text", "content": "{\"text\":\"✅ Skill自动同步到公司SkillHub成功,本次同步技能:'${synced_skills[*]}'\"}"}' > /dev/null
|
||
fi
|
||
echo "跳过无变更技能数:${skipped_count}"
|
||
echo ""
|
||
|
||
# 如果有变更,返回非0码
|
||
exit ${synced_count}
|