Spaces:
Running
Running
| set -e | |
| # 强制使用北京时间(解决 HF Spaces 默认 UTC 导致汇报时间错误) | |
| # 使用 OpenClaw 3.13 新增的 OPENCLAW_TZ 环境变量 | |
| export TZ="Asia/Shanghai" | |
| export OPENCLAW_TZ="Asia/Shanghai" | |
| CONFIG="/root/.openclaw/openclaw.json" | |
| IP_RECORD="/root/.openclaw/.last_outbound_ip" | |
| export OPENCLAW_STATE_DIR="/root/.openclaw" | |
| export OPENCLAW_CONFIG_PATH="$CONFIG" | |
| # ============================================================ | |
| # 从 GitHub 仓库根目录复制部署文件 | |
| # 默认仓库:Viciy2023/huggingface-new-worker | |
| # 默认路径:仓库根目录 | |
| # 需要通过 GitHub Token 认证 | |
| # ============================================================ | |
| GITHUB_OWNER="${GITHUB_OWNER:-Viciy2023}" | |
| GITHUB_REPO="${GITHUB_REPO:-huggingface-new-worker}" | |
| GITHUB_BRANCH="${GITHUB_BRANCH:-main}" | |
| GITHUB_TOKEN="${GITHUB_TOKEN:-}" | |
| GITHUB_CLONE_ROOT="/tmp/github-deploy-source" | |
| GITHUB_CLONE_DIR="${GITHUB_CLONE_ROOT}/repo" | |
| prepare_github_source() { | |
| if [ -z "$GITHUB_TOKEN" ]; then | |
| echo "❌ GITHUB_TOKEN is not set" | |
| return 1 | |
| fi | |
| rm -rf "$GITHUB_CLONE_ROOT" | |
| mkdir -p "$GITHUB_CLONE_ROOT" | |
| local repo_url="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_OWNER}/${GITHUB_REPO}.git" | |
| echo "=== Cloning deploy files from GitHub repository ===" | |
| echo "Repository: ${GITHUB_OWNER}/${GITHUB_REPO}" | |
| echo "Branch: ${GITHUB_BRANCH}" | |
| echo "Source path: repository root" | |
| if ! git clone --depth 1 --branch "$GITHUB_BRANCH" "$repo_url" "$GITHUB_CLONE_DIR"; then | |
| echo "❌ Failed to clone GitHub repository" | |
| return 1 | |
| fi | |
| return 0 | |
| } | |
| copy_repo_file() { | |
| local src="$1" | |
| local dest="$2" | |
| local source_path="${GITHUB_CLONE_DIR}/${src}" | |
| mkdir -p "$(dirname "$dest")" | |
| echo " Copying: ${src}" | |
| echo " From: ${source_path}" | |
| echo " To: ${dest}" | |
| if [ -f "$source_path" ]; then | |
| cp "$source_path" "$dest" | |
| echo "✅ Copied: $src" | |
| return 0 | |
| fi | |
| echo "❌ Failed: $src (file not found in GitHub repository root)" | |
| return 1 | |
| } | |
| if [ -n "$GITHUB_OWNER" ] && [ -n "$GITHUB_REPO" ]; then | |
| FAIL_COUNT=0 | |
| echo "=== Using HF Secrets for environment variables ===" | |
| echo "⚠️ .env download is disabled; runtime secrets must come from HF Space Secrets" | |
| if prepare_github_source; then | |
| # 配置文件 | |
| copy_repo_file "openclaw.json" "/root/.openclaw/openclaw.json" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| # workspace 文件(角色设定、任务文档等) | |
| # 注意:OpenClaw 3.13 只加载一个内存引导文件,MEMORY.md 优先 | |
| copy_repo_file "SOUL.md" "/root/.openclaw/workspace/SOUL.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "IDENTITY.md" "/root/.openclaw/workspace/IDENTITY.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "USER.md" "/root/.openclaw/workspace/USER.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "AGENTS.md" "/root/.openclaw/workspace/AGENTS.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "TOOLS.md" "/root/.openclaw/workspace/TOOLS.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "BOOTSTRAP.md" "/root/.openclaw/workspace/BOOTSTRAP.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "MEMORY.md" "/root/.openclaw/workspace/MEMORY.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "HEARTBEAT.md" "/root/.openclaw/workspace/HEARTBEAT.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "WORKFLOW_AUTO.md" "/root/.openclaw/workspace/WORKFLOW_AUTO.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "task-dispatch.md" "/root/.openclaw/workspace/task-dispatch.md" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| # cron 任务配置 | |
| copy_repo_file "cron/jobs.json" "/root/.openclaw/cron/jobs.json" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| # ClawEdit 项目文件 - 文章配套媒体生成系统 (原生插件模式) | |
| # 源路径:GitHub 子目录中的 clawedit 目录 | |
| # 目标路径:~/.openclaw/extensions/clawedit | |
| CLAWEDIT_DEST="/root/.openclaw/extensions/clawedit" | |
| copy_repo_file "clawedit/index.ts" "$CLAWEDIT_DEST/index.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/package.json" "$CLAWEDIT_DEST/package.json" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/openclaw.plugin.json" "$CLAWEDIT_DEST/openclaw.plugin.json" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/core/types.ts" "$CLAWEDIT_DEST/core/types.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/core/config.ts" "$CLAWEDIT_DEST/core/config.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/core/errors.ts" "$CLAWEDIT_DEST/core/errors.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/core/process.ts" "$CLAWEDIT_DEST/core/process.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/generator/image-pipeline.ts" "$CLAWEDIT_DEST/generator/image-pipeline.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/generator/video-pipeline.ts" "$CLAWEDIT_DEST/generator/video-pipeline.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/generator/batch-generator.ts" "$CLAWEDIT_DEST/generator/batch-generator.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/planner/article-planner.ts" "$CLAWEDIT_DEST/planner/article-planner.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| copy_repo_file "clawedit/editor/markdown-enricher.ts" "$CLAWEDIT_DEST/editor/markdown-enricher.ts" || FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| echo "=== Deploy files copy complete (failures: $FAIL_COUNT) ===" | |
| if [ "$FAIL_COUNT" -gt 0 ]; then | |
| echo "⚠️ WARNING: $FAIL_COUNT file(s) failed to copy, service may not work correctly" | |
| fi | |
| else | |
| echo "❌ GitHub deploy source preparation failed" | |
| fi | |
| else | |
| echo "⚠️ GitHub deploy source is not configured, skipping deploy file copy" | |
| fi | |
| # ============================================================ | |
| # 调试:检查环境变量是否正确加载 | |
| # ============================================================ | |
| echo "=== Debug: Checking environment variables ===" | |
| echo "GATEWAY_TOKEN length: ${#GATEWAY_TOKEN}" | |
| echo "GATEWAY_TOKEN first 20 chars: ${GATEWAY_TOKEN:0:20}..." | |
| echo "CLIPROXY_BASE_URL: ${CLIPROXY_BASE_URL}" | |
| echo "WECOM_TOKEN length: ${#WECOM_TOKEN}" | |
| echo "" | |
| echo "=== Debug: Checking config file before replacement ===" | |
| grep -n "GATEWAY_TOKEN" "$CONFIG" | head -5 | |
| echo "" | |
| # ============================================================ | |
| # 替换 openclaw.json 中的占位符 | |
| # 环境变量全部由 HF Secrets 注入 | |
| # ============================================================ | |
| echo "=== Replacing placeholders in openclaw.json ===" | |
| CONTROL_UI_ORIGIN="${PUBLIC_BASE_URL%/}" | |
| if [ -n "$CONTROL_UI_ORIGIN" ]; then | |
| CONTROL_UI_ORIGIN="${CONTROL_UI_ORIGIN%%/*}" | |
| if [[ "$PUBLIC_BASE_URL" =~ ^https?:// ]]; then | |
| CONTROL_UI_ORIGIN="${PUBLIC_BASE_URL%/}" | |
| fi | |
| fi | |
| sed -i "s|__PUBLIC_BASE_URL__|${CONTROL_UI_ORIGIN}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_API_BASE_URL__|${WECOM_APP_API_BASE_URL}|g" "$CONFIG" | |
| sed -i "s|__GATEWAY_TOKEN__|${GATEWAY_TOKEN}|g" "$CONFIG" | |
| # 主模型配置(动态替换) | |
| sed -i "s|__PRIMARY_PROVIDER_NAME__|${PRIMARY_PROVIDER_NAME}|g" "$CONFIG" | |
| sed -i "s|__PRIMARY_PROVIDER_BASE_URL__|${PRIMARY_PROVIDER_BASE_URL}|g" "$CONFIG" | |
| sed -i "s|__PRIMARY_PROVIDER_API_KEY__|${PRIMARY_PROVIDER_API_KEY}|g" "$CONFIG" | |
| sed -i "s|__PRIMARY_PROVIDER_API__|${PRIMARY_PROVIDER_API}|g" "$CONFIG" | |
| sed -i "s|__PRIMARY_MODEL_ID__|${PRIMARY_MODEL_ID}|g" "$CONFIG" | |
| sed -i "s|__PRIMARY_MODEL_NAME__|${PRIMARY_MODEL_NAME}|g" "$CONFIG" | |
| # CLIPROXY 配置已删除,不再使用 | |
| # sed -i "s|__CLIPROXY_BASE_URL__|${CLIPROXY_BASE_URL}|g" "$CONFIG" | |
| # sed -i "s|__CLIPROXY_API_KEY__|${CLIPROXY_API_KEY}|g" "$CONFIG" | |
| # 旧的 GROKPROXY 配置(保留兼容性,如果新变量未设置则使用旧变量) | |
| sed -i "s|__GROKPROXY_BASE_URL__|${GROKPROXY_BASE_URL}|g" "$CONFIG" | |
| sed -i "s|__GROKPROXY_API_KEY__|${GROKPROXY_API_KEY}|g" "$CONFIG" | |
| sed -i "s|__HFGROK2API_B_KEY__|${HFGROK2API_B_KEY}|g" "$CONFIG" | |
| sed -i "s|__HFGROK2API_B_BASE_URL__|${HFGROK2API_B_BASE_URL}|g" "$CONFIG" | |
| sed -i "s|__WECOM_WS_BOT_ID__|${WECOM_WS_BOT_ID}|g" "$CONFIG" | |
| sed -i "s|__WECOM_WS_SECRET__|${WECOM_WS_SECRET}|g" "$CONFIG" | |
| sed -i "s|__WECOM_TOKEN__|${WECOM_TOKEN}|g" "$CONFIG" | |
| sed -i "s|__WECOM_AES_KEY__|${WECOM_AES_KEY}|g" "$CONFIG" | |
| sed -i "s|__WECOM_CORP_ID__|${WECOM_CORP_ID}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_TOKEN__|${WECOM_APP_TOKEN}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_AES_KEY__|${WECOM_APP_AES_KEY}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_SECRET__|${WECOM_APP_SECRET}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_ASR_APP_ID__|${WECOM_APP_ASR_APP_ID}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_ASR_SECRET_ID__|${WECOM_APP_ASR_SECRET_ID}|g" "$CONFIG" | |
| sed -i "s|__WECOM_APP_ASR_SECRET_KEY__|${WECOM_APP_ASR_SECRET_KEY}|g" "$CONFIG" | |
| sed -i "s|__QQBOT_APP_ID__|${QQBOT_APP_ID}|g" "$CONFIG" | |
| sed -i "s|__QQBOT_CLIENT_SECRET__|${QQBOT_CLIENT_SECRET}|g" "$CONFIG" | |
| sed -i "s|__QQBOT_ASR_APP_ID__|${QQBOT_ASR_APP_ID}|g" "$CONFIG" | |
| sed -i "s|__QQBOT_ASR_SECRET_ID__|${QQBOT_ASR_SECRET_ID}|g" "$CONFIG" | |
| sed -i "s|__QQBOT_ASR_SECRET_KEY__|${QQBOT_ASR_SECRET_KEY}|g" "$CONFIG" | |
| sed -i "s|__FEISHU_APP_ID__|${FEISHU_APP_ID}|g" "$CONFIG" | |
| sed -i "s|__FEISHU_APP_SECRET__|${FEISHU_APP_SECRET}|g" "$CONFIG" | |
| sed -i "s|__FEISHU_VERIFICATION_TOKEN__|${FEISHU_VERIFICATION_TOKEN}|g" "$CONFIG" | |
| sed -i "s|__FEISHU_ENCRYPT_KEY__|${FEISHU_ENCRYPT_KEY}|g" "$CONFIG" | |
| # 以下 Grok2 API 节点配置已删除,不再使用 | |
| # sed -i "s|__VOLCENGINE_ARK_API_KEY__|${VOLCENGINE_ARK_API_KEY}|g" "$CONFIG" | |
| # sed -i "s|__VOLCENGINE_PROXY_TOKEN__|${VOLCENGINE_PROXY_TOKEN}|g" "$CONFIG" | |
| # sed -i "s|__VOLCENGINE_PROXY_URL__|${VOLCENGINE_PROXY_URL}|g" "$CONFIG" | |
| # sed -i "s|__HFOPCF_GROK2API_KEY__|${HFOPCF_GROK2API_KEY}|g" "$CONFIG" | |
| # sed -i "s|__HFOPCF_GROK2API_BASE_URL__|${HFOPCF_GROK2API_BASE_URL}|g" "$CONFIG" | |
| # sed -i "s|__HFOP_GROK2API_B_KEY__|${HFOP_GROK2API_B_KEY}|g" "$CONFIG" | |
| # sed -i "s|__HFOP_GROK2API_B_BASE_URL__|${HFOP_GROK2API_B_BASE_URL}|g" "$CONFIG" | |
| # sed -i "s|__HFOPKUAKE_GROK2API_KEY__|${HFOPKUAKE_GROK2API_KEY}|g" "$CONFIG" | |
| # sed -i "s|__HFOPKUAKE_GROK2API_BASE_URL__|${HFOPKUAKE_GROK2API_BASE_URL}|g" "$CONFIG" | |
| # sed -i "s|__HFOPSOUGOU_GROK2API_KEY__|${HFOPSOUGOU_GROK2API_KEY}|g" "$CONFIG" | |
| # sed -i "s|__HFOPSOUGOU_GROK2API_BASE_URL__|${HFOPSOUGOU_GROK2API_BASE_URL}|g" "$CONFIG" | |
| # sed -i "s|__HFOPVIDEOSOUGOU_GROK_API_KEY__|${HFOPVIDEOSOUGOU_GROK_API_KEY}|g" "$CONFIG" | |
| # sed -i "s|__HFOPVIDEOSOUGOU_GROK_BASE_URL__|${HFOPVIDEOSOUGOU_GROK_BASE_URL}|g" "$CONFIG" | |
| # sed -i "s|__HFGROK2API_KEY__|${HFGROK2API_KEY}|g" "$CONFIG" | |
| # sed -i "s|__HFGROK2API_BASE_URL__|${HFGROK2API_BASE_URL}|g" "$CONFIG" | |
| echo "✅ Placeholders replaced" | |
| echo "" | |
| echo "=== Debug: Checking config file after replacement ===" | |
| grep -n '"token"' "$CONFIG" | head -10 | |
| echo "" | |
| echo "=== Debug: Checking if any placeholders remain ===" | |
| PLACEHOLDER_COUNT=$(grep -o "__[A-Z_]*__" "$CONFIG" | wc -l) | |
| echo "Remaining placeholders: $PLACEHOLDER_COUNT" | |
| if [ "$PLACEHOLDER_COUNT" -ne 0 ]; then | |
| echo "⚠️ WARNING: Found unreplaced placeholders:" | |
| grep -o "__[A-Z_]*__" "$CONFIG" | sort -u | |
| fi | |
| echo "" | |
| # Fix config file permission (suppress security audit warning) | |
| chmod 600 "$CONFIG" | |
| # Check outbound IP and notify if changed | |
| CURRENT_IP=$(curl -s --max-time 10 https://ifconfig.me || curl -s --max-time 10 https://api.ipify.org || echo "unknown") | |
| # ============================================================ | |
| # 打印HF空间当前动态IP地址(醒目显示) | |
| # ============================================================ | |
| echo "" | |
| echo "════════════════════════════════════════════════════════════════" | |
| echo "🌐 HF Space Outbound IP: ${CURRENT_IP}" | |
| echo "════════════════════════════════════════════════════════════════" | |
| echo "" | |
| # ============================================================ | |
| # 测试微信公众号 API 连通性 | |
| # ============================================================ | |
| if [ -n "$WECHAT_APP_ID" ] && [ -n "$WECHAT_APP_SECRET" ]; then | |
| echo "=== Testing WeChat Official Account API connectivity ===" | |
| WECHAT_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${WECHAT_APP_ID}&secret=${WECHAT_APP_SECRET}" | |
| WECHAT_RESPONSE=$(curl -s --max-time 10 "$WECHAT_TOKEN_URL" || echo '{"errcode":-1,"errmsg":"network error"}') | |
| # 检查是否成功获取 access_token | |
| if echo "$WECHAT_RESPONSE" | grep -q '"access_token"'; then | |
| echo "✅ WeChat API connection successful" | |
| echo " Access Token obtained (expires in 7200s)" | |
| else | |
| echo "❌ WeChat API connection FAILED" | |
| echo " Response: $WECHAT_RESPONSE" | |
| # 解析错误信息 | |
| ERRCODE=$(echo "$WECHAT_RESPONSE" | grep -o '"errcode":[0-9-]*' | cut -d':' -f2) | |
| ERRMSG=$(echo "$WECHAT_RESPONSE" | grep -o '"errmsg":"[^"]*"' | cut -d'"' -f4) | |
| if [ -n "$ERRCODE" ]; then | |
| echo " ❌ Error Code: $ERRCODE" | |
| echo " ❌ Error Message: $ERRMSG" | |
| # 常见错误提示 | |
| case "$ERRCODE" in | |
| 40013) | |
| echo " 💡 Hint: Invalid AppID, please check WECHAT_APP_ID" | |
| ;; | |
| 40001) | |
| echo " 💡 Hint: Invalid AppSecret, please check WECHAT_APP_SECRET" | |
| ;; | |
| 40164) | |
| echo " 💡 Hint: IP not in whitelist, please add ${CURRENT_IP} to WeChat Official Account IP whitelist" | |
| ;; | |
| -1) | |
| echo " 💡 Hint: Network error or API timeout" | |
| ;; | |
| esac | |
| fi | |
| fi | |
| echo "" | |
| else | |
| echo "⚠️ WECHAT_APP_ID or WECHAT_APP_SECRET not set, skipping WeChat API test" | |
| echo "" | |
| fi | |
| LAST_IP="" | |
| if [ -f "$IP_RECORD" ]; then | |
| LAST_IP=$(cat "$IP_RECORD") | |
| fi | |
| if [ "$CURRENT_IP" != "unknown" ] && [ "$CURRENT_IP" != "$LAST_IP" ]; then | |
| echo "$CURRENT_IP" > "$IP_RECORD" | |
| if [ -n "$WECOM_WEBHOOK_KEY" ]; then | |
| WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WECOM_WEBHOOK_KEY}" | |
| if [ -z "$LAST_IP" ]; then | |
| MSG="🦞 OpenClaw HF Space 首次启动\n\n出口IP: ${CURRENT_IP}\n\n请确认该IP已添加到企业微信可信IP白名单中。" | |
| else | |
| MSG="⚠️ OpenClaw HF Space 出口IP已变更\n\n旧IP: ${LAST_IP}\n新IP: ${CURRENT_IP}\n\n请立即到企业微信后台更新可信IP白名单,否则 wecom-app 将无法主动发送消息。" | |
| fi | |
| curl -s -X POST "$WEBHOOK_URL" \ | |
| -H "Content-Type: application/json" \ | |
| -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"${MSG}\"}}" \ | |
| || echo "Failed to send webhook notification" | |
| fi | |
| fi | |
| # ============================================================ | |
| # 验证 openclaw-china channels 插件(已在 Dockerfile 中安装) | |
| # ============================================================ | |
| echo "=== Verifying openclaw-china channels plugin ===" | |
| if node /app/openclaw.mjs plugins list 2>&1 | grep -qi "channels"; then | |
| echo "✅ @openclaw-china/channels plugin is installed and loaded" | |
| else | |
| echo "⚠️ @openclaw-china/channels plugin not found, attempting runtime install..." | |
| if node /app/openclaw.mjs plugins install @openclaw-china/channels; then | |
| echo "✅ @openclaw-china/channels plugin installed successfully at runtime" | |
| else | |
| echo "❌ Failed to install @openclaw-china/channels plugin" | |
| fi | |
| fi | |
| # ============================================================ | |
| # 克隆 wechat-allauto-gzh 项目(运行时克隆,确保始终获取 fork 最新版本) | |
| # ============================================================ | |
| echo "=== Cloning wechat-allauto-gzh project from fork ===" | |
| WECHAT_SKILL_DIR="/root/.openclaw/workspace/wechat-allauto-gzh" | |
| WECHAT_ALLAUTO_GZH_REPO_URL="${WECHAT_ALLAUTO_GZH_REPO_URL:-https://github.com/Viciy2023/wechat-allauto-gzh.git}" | |
| WECHAT_ALLAUTO_GZH_BRANCH="${WECHAT_ALLAUTO_GZH_BRANCH:-main}" | |
| if [ -d "$WECHAT_SKILL_DIR/.git" ]; then | |
| echo "⚠️ wechat-allauto-gzh already exists, pulling latest fork changes..." | |
| git -C "$WECHAT_SKILL_DIR" fetch origin "$WECHAT_ALLAUTO_GZH_BRANCH" && \ | |
| git -C "$WECHAT_SKILL_DIR" checkout "$WECHAT_ALLAUTO_GZH_BRANCH" && \ | |
| git -C "$WECHAT_SKILL_DIR" pull --ff-only origin "$WECHAT_ALLAUTO_GZH_BRANCH" || echo "Failed to pull latest fork changes" | |
| else | |
| echo "Cloning wechat-allauto-gzh from fork repository..." | |
| mkdir -p /root/.openclaw/workspace | |
| rm -rf "$WECHAT_SKILL_DIR" | |
| git clone --depth 1 --branch "$WECHAT_ALLAUTO_GZH_BRANCH" "$WECHAT_ALLAUTO_GZH_REPO_URL" "$WECHAT_SKILL_DIR" || \ | |
| echo "❌ Failed to clone wechat-allauto-gzh fork" | |
| fi | |
| if [ -d "$WECHAT_SKILL_DIR" ]; then | |
| echo "✅ wechat-allauto-gzh fork is ready at: $WECHAT_SKILL_DIR" | |
| # 安装 Python 依赖(Agent 只需要 Python 环境) | |
| echo "=== Installing Python dependencies ===" | |
| pip install --no-cache-dir requests pyyaml --break-system-packages || echo "⚠️ pip install failed" | |
| else | |
| echo "❌ wechat-allauto-gzh directory not found after clone attempt" | |
| fi | |
| # ============================================================ | |
| # ClawHub 技能、agent-browser CLI 兜底安装、Skill Node 依赖安装与技能校验 | |
| # 已迁移到 Dockerfile 构建阶段,运行时仅输出状态,避免容器启动时再进行网络安装。 | |
| # ============================================================ | |
| echo "=== ClawHub skills are preinstalled during Docker build ===" | |
| SKILLS_DIR="/root/.openclaw/workspace/skills" | |
| if [ -d "$SKILLS_DIR" ]; then | |
| echo "📂 Workspace skills directory contents:" | |
| ls -la "$SKILLS_DIR" || echo "⚠️ Failed to list skills directory" | |
| else | |
| echo "⚠️ Workspace skills directory not found at runtime: $SKILLS_DIR" | |
| fi | |
| echo "" | |
| echo "=== Verifying preinstalled agent-browser CLI ===" | |
| if command -v agent-browser >/dev/null 2>&1; then | |
| echo "✅ agent-browser CLI is available" | |
| agent-browser --version || echo "⚠️ agent-browser version check failed" | |
| else | |
| echo "⚠️ agent-browser CLI not found at runtime; image build verification may have failed" | |
| fi | |
| echo "" | |
| # ============================================================ | |
| # 跳过容器内 openclaw doctor --fix | |
| # doctor 会触发 systemd/gateway 相关检查,不适合 HF 容器前台启动模式 | |
| # ============================================================ | |
| echo "=== Skipping openclaw doctor --fix in container runtime ===" | |
| # ============================================================ | |
| # 安装微信 CLI | |
| # ============================================================ | |
| echo "=== Installing WeChat CLI ===" | |
| if npx -y @tencent-weixin/openclaw-weixin-cli@latest install; then | |
| echo "✅ WeChat CLI installed successfully" | |
| else | |
| echo "⚠️ WeChat CLI installation failed, continuing anyway..." | |
| fi | |
| # ============================================================ | |
| # 配置微信公众号凭证 | |
| # ============================================================ | |
| echo "=== Configuring WeChat Official Account credentials ===" | |
| WECHAT_CREDS_FILE="/root/.openclaw/workspace/wechat-allauto-gzh/credentials.json" | |
| if [ -n "$WECHAT_APP_ID" ] && [ -n "$WECHAT_APP_SECRET" ]; then | |
| cat > "$WECHAT_CREDS_FILE" <<EOF | |
| { | |
| "AppID": "${WECHAT_APP_ID}", | |
| "AppSecret": "${WECHAT_APP_SECRET}" | |
| } | |
| EOF | |
| chmod 600 "$WECHAT_CREDS_FILE" | |
| echo "✅ WeChat credentials.json created at: $WECHAT_CREDS_FILE" | |
| echo " AppID: ${WECHAT_APP_ID}" | |
| else | |
| echo "⚠️ WECHAT_APP_ID or WECHAT_APP_SECRET not set" | |
| fi | |
| # 验证 wechat-allauto-gzh 技能是否正确安装 | |
| echo "=== Verifying wechat-allauto-gzh skill installation ===" | |
| if [ -d "/root/.openclaw/workspace/wechat-allauto-gzh" ]; then | |
| echo "✅ wechat-allauto-gzh directory exists at workspace" | |
| if [ -f "/root/.openclaw/workspace/wechat-allauto-gzh/SKILL.md" ]; then | |
| echo "✅ SKILL.md found" | |
| else | |
| echo "❌ SKILL.md NOT found" | |
| fi | |
| if [ -d "/root/.openclaw/workspace/wechat-allauto-gzh/src/skills" ]; then | |
| echo "✅ Python skills directory exists" | |
| ls -la /root/.openclaw/workspace/wechat-allauto-gzh/src/skills/ || true | |
| else | |
| echo "❌ Python skills directory NOT found" | |
| fi | |
| if [ -f "$WECHAT_CREDS_FILE" ]; then | |
| echo "✅ credentials.json exists" | |
| else | |
| echo "❌ credentials.json NOT found" | |
| fi | |
| else | |
| echo "❌ wechat-allauto-gzh directory NOT found in workspace" | |
| fi | |
| echo "✅ Config fixed" | |
| # Start gateway | |
| exec node /app/openclaw.mjs gateway --port 7860 --bind lan --allow-unconfigured | |