wangdang commited on
Commit
df25c58
·
verified ·
1 Parent(s): c51d72a

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +89 -0
  2. README.md +5 -8
  3. start-openclaw +107 -0
  4. sync.py +50 -0
Dockerfile ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:22-slim
2
+
3
+ RUN apt-get update && apt-get install -y --no-install-recommends \
4
+ git ca-certificates build-essential python3 python3-pip curl \
5
+ && rm -rf /var/lib/apt/lists/*
6
+
7
+ RUN npm install -g openclaw@latest --unsafe-perm
8
+
9
+ # 安装微信插件
10
+ RUN npx -y @tencent-weixin/openclaw-weixin-cli@latest install
11
+
12
+ ENV PORT=7860 \
13
+ OPENCLAW_GATEWAY_MODE=local \
14
+ HOME=/root
15
+
16
+ RUN echo '#!/bin/bash\n\
17
+ set -e\n\
18
+ mkdir -p /root/.openclaw/sessions\n\
19
+ mkdir -p /root/.openclaw/workspace\n\
20
+ mkdir -p /root/.openclaw/workspace/memory\n\
21
+ mkdir -p /root/.openclaw/wechat-data\n\
22
+ touch /root/.openclaw/workspace/MEMORY.md\n\
23
+ DATE=$(date +%Y-%m-%d)\n\
24
+ touch /root/.openclaw/workspace/memory/$DATE.md\n\
25
+ \n\
26
+ CLEAN_BASE=$(echo "$OPENAI_API_BASE" | sed "s|/chat/completions||g" | sed "s|/v1/|/v1|g" | sed "s|/v1$|/v1|g")\n\
27
+ \n\
28
+ if [ -n "$GEMINI_API_KEY" ]; then\n\
29
+ PROVIDER="google"\n\
30
+ API_KEY_VAR="$GEMINI_API_KEY"\n\
31
+ BASE_URL_VAR="https://generativelanguage.googleapis.com/v1beta"\n\
32
+ MODEL_VAR="$MODEL"\n\
33
+ PRIMARY_MODEL="google/$MODEL_VAR"\n\
34
+ API_TYPE="google-generative-ai"\n\
35
+ else\n\
36
+ PROVIDER="openai"\n\
37
+ API_KEY_VAR="$OPENAI_API_KEY"\n\
38
+ BASE_URL_VAR="$CLEAN_BASE"\n\
39
+ MODEL_VAR="$MODEL"\n\
40
+ PRIMARY_MODEL="openai/$MODEL_VAR"\n\
41
+ API_TYPE="openai-completions"\n\
42
+ fi\n\
43
+ \n\
44
+ cat > /root/.openclaw/openclaw.json <<EOF\n\
45
+ {\n\
46
+ "models": {\n\
47
+ "providers": {\n\
48
+ "$PROVIDER": {\n\
49
+ "baseUrl": "$BASE_URL_VAR",\n\
50
+ "apiKey": "$API_KEY_VAR",\n\
51
+ "api": "$API_TYPE",\n\
52
+ "models": [{ "id": "$MODEL_VAR", "name": "$MODEL_VAR", "contextWindow": 128000 }]\n\
53
+ }\n\
54
+ }\n\
55
+ },\n\
56
+ "agents": { "defaults": { "model": { "primary": "$PRIMARY_MODEL" } } },\n\
57
+ "gateway": {\n\
58
+ "mode": "local",\n\
59
+ "bind": "lan",\n\
60
+ "port": $PORT,\n\
61
+ "trustedProxies": ["0.0.0.0/0", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],\n\
62
+ "auth": { "mode": "token", "token": "$OPENCLAW_GATEWAY_PASSWORD" },\n\
63
+ "controlUi": { "allowInsecureAuth": true, "allowedOrigins": ["*"] }\n\
64
+ },\n\
65
+ "plugins": {\n\
66
+ "allow": ["openclaw-weixin"]\n\
67
+ },\n\
68
+ "channels": {\n\
69
+ "openclaw-weixin": {\n\
70
+ "enabled": true,\n\
71
+ "dataDir": "/root/.openclaw/wechat-data",\n\
72
+ "autoLogin": true\n\
73
+ }\n\
74
+ }\n\
75
+ }\n\
76
+ EOF\n\
77
+ \n\
78
+ echo "=== openclaw.json content ==="\n\
79
+ cat /root/.openclaw/openclaw.json\n\
80
+ echo "=== end ==="\n\
81
+ \n\
82
+ openclaw doctor --fix\n\
83
+ \n\
84
+ # 启动网关(前台运行,保持容器活跃)\n\
85
+ exec openclaw gateway run --port $PORT\n\
86
+ ' > /usr/local/bin/start-openclaw && chmod +x /usr/local/bin/start-openclaw
87
+
88
+ EXPOSE 7860
89
+ CMD ["/usr/local/bin/start-openclaw"]
README.md CHANGED
@@ -1,12 +1,9 @@
1
  ---
2
  title: Openclaw
3
- emoji: 🌍
4
- colorFrom: blue
5
- colorTo: yellow
6
  sdk: docker
 
7
  pinned: false
8
- license: mit
9
- short_description: openclaw
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
  title: Openclaw
3
+ emoji: 🦞
4
+ colorFrom: pink
5
+ colorTo: red
6
  sdk: docker
7
+ port: 18789
8
  pinned: false
9
+ ---
 
 
 
 
start-openclaw ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ rm -f /root/.openclaw/openclaw.json
5
+
6
+ mkdir -p /root/.openclaw/sessions
7
+ mkdir -p /root/.openclaw/workspace
8
+
9
+ # 根据 Secrets 自动选择 provider
10
+ if [ -n "$GEMINI_API_KEY" ]; then
11
+ PROVIDER="google"
12
+ API_KEY_VAR="$GEMINI_API_KEY"
13
+ BASE_URL_VAR="https://generativelanguage.googleapis.com/v1beta"
14
+ MODEL_VAR="$MODEL"
15
+ PRIMARY_MODEL="google/$MODEL_VAR"
16
+ API_TYPE="google-generative-ai"
17
+ else
18
+ PROVIDER="openai"
19
+ API_KEY_VAR="$OPENAI_API_KEY"
20
+ CLEAN_BASE=$(echo "$OPENAI_API_BASE" | sed "s|/chat/completions||g" | sed "s|/v1/|/v1|g" | sed "s|/v1$|/v1|g")
21
+ BASE_URL_VAR="$CLEAN_BASE"
22
+ MODEL_VAR="$MODEL"
23
+ PRIMARY_MODEL="openai/$MODEL_VAR"
24
+ API_TYPE="openai-completions"
25
+ fi
26
+
27
+ cat > /root/.openclaw/openclaw.json <<EOF
28
+ {
29
+ "models": {
30
+ "providers": {
31
+ "$PROVIDER": {
32
+ "baseUrl": "$BASE_URL_VAR",
33
+ "apiKey": "$API_KEY_VAR",
34
+ "api": "$API_TYPE",
35
+ "models": [{ "id": "$MODEL_VAR", "name": "$MODEL_VAR", "contextWindow": 128000 }]
36
+ }
37
+ }
38
+ },
39
+ "agents": {
40
+ "defaults": {
41
+ "model": {
42
+ "primary": "$PRIMARY_MODEL"
43
+ }
44
+ }
45
+ },
46
+ "gateway": {
47
+ "mode": "local",
48
+ "bind": "lan",
49
+ "port": $PORT,
50
+ "trustedProxies": ["0.0.0.0/0", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
51
+ "auth": {
52
+ "mode": "token",
53
+ "token": "$OPENCLAW_GATEWAY_PASSWORD"
54
+ },
55
+ "controlUi": {
56
+ "allowInsecureAuth": true,
57
+ "allowedOrigins": ["*"]
58
+ }
59
+ },
60
+ "channels": {
61
+ "telegram": {
62
+ "enabled": true,
63
+ "botToken": "$TELEGRAM_BOT_TOKEN"
64
+ }
65
+ }
66
+ }
67
+ EOF
68
+
69
+ echo "=== openclaw.json content ==="
70
+ cat /root/.openclaw/openclaw.json
71
+ echo "=== end ==="
72
+
73
+ # 启动网关(后台运行)
74
+ openclaw gateway run --port $PORT &
75
+ GATEWAY_PID=$!
76
+
77
+ # 等待网关完全启动
78
+ sleep 8
79
+
80
+ # 自动批准 Telegram 配对(支持表格和旧格式)
81
+ echo "Starting Telegram auto-pairing..."
82
+ for i in {1..10}; do
83
+ PAIR_OUTPUT=$(openclaw pairing list 2>/dev/null || true)
84
+ echo "Attempt $i: pairing list output:"
85
+ echo "$PAIR_OUTPUT"
86
+
87
+ CODE=""
88
+ CODE=$(echo "$PAIR_OUTPUT" | grep -oP 'Pairing code: \K[A-Z0-9]{7,}' | head -1)
89
+ if [ -z "$CODE" ]; then
90
+ CODE=$(echo "$PAIR_OUTPUT" | awk '/^│ Code/ {getline; split($0, a, "│"); gsub(/^ +| +$/, "", a[2]); if (a[2] ~ /^[A-Z0-9]{7,}$/) print a[2]}' | head -1)
91
+ fi
92
+ if [ -z "$CODE" ]; then
93
+ CODE=$(echo "$PAIR_OUTPUT" | grep -oE '[A-Z0-9]{7,}' | grep -v "PAIRING" | grep -v "REQUEST" | head -1)
94
+ fi
95
+
96
+ if [ -n "$CODE" ]; then
97
+ echo "Found pairing code: $CODE"
98
+ openclaw pairing approve telegram "$CODE"
99
+ echo "Approval sent. Bot should now respond."
100
+ break
101
+ else
102
+ echo "No pending pairing code found (attempt $i/10). Waiting 5 seconds..."
103
+ sleep 5
104
+ fi
105
+ done
106
+
107
+ wait $GATEWAY_PID
sync.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys, tarfile
2
+ from huggingface_hub import HfApi, hf_hub_download
3
+ from datetime import datetime, timedelta
4
+
5
+ api = HfApi()
6
+ repo_id = os.getenv("HF_DATASET")
7
+ token = os.getenv("HF_TOKEN")
8
+
9
+ def restore():
10
+ try:
11
+ print(f"--- [SYNC] 启动恢复流程, 目标仓库: {repo_id} ---")
12
+ if not repo_id or not token:
13
+ print("--- [SYNC] 跳过恢复: 未配置 HF_DATASET 或 HF_TOKEN ---")
14
+ return False
15
+ files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)
16
+ now = datetime.now()
17
+ for i in range(5):
18
+ day = (now - timedelta(days=i)).strftime("%Y-%m-%d")
19
+ name = f"backup_{day}.tar.gz"
20
+ if name in files:
21
+ print(f"--- [SYNC] 发现备份文件: {name}, 正在下载... ---")
22
+ path = hf_hub_download(repo_id=repo_id, filename=name, repo_type="dataset", token=token)
23
+ with tarfile.open(path, "r:gz") as tar:
24
+ tar.extractall(path="/root/.openclaw/")
25
+ print(f"--- [SYNC] 恢复成功! 数据已覆盖至 /root/.openclaw/ ---")
26
+ return True
27
+ print("--- [SYNC] 未找到最近 5 天的备份包 ---")
28
+ except Exception as e:
29
+ print(f"--- [SYNC] 恢复异常: {e} ---")
30
+
31
+ def backup():
32
+ try:
33
+ day = datetime.now().strftime("%Y-%m-%d")
34
+ name = f"backup_{day}.tar.gz"
35
+ print(f"--- [SYNC] 正在执行全量备份: {name} ---")
36
+ with tarfile.open(name, "w:gz") as tar:
37
+ for target in ["sessions", "workspace", "agents", "memory", "openclaw.json"]:
38
+ full_path = f"/root/.openclaw/{target}"
39
+ if os.path.exists(full_path):
40
+ tar.add(full_path, arcname=target)
41
+ api.upload_file(path_or_fileobj=name, path_in_repo=name, repo_id=repo_id, repo_type="dataset", token=token)
42
+ print(f"--- [SYNC] 备份上传成功! ---")
43
+ except Exception as e:
44
+ print(f"--- [SYNC] 备份失败: {e} ---")
45
+
46
+ if __name__ == "__main__":
47
+ if len(sys.argv) > 1 and sys.argv[1] == "backup":
48
+ backup()
49
+ else:
50
+ restore()