sharween commited on
Commit
0c180d6
·
verified ·
1 Parent(s): f5a25e4

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +39 -0
  2. openclaw.json +107 -0
  3. start-openclaw.sh +21 -0
  4. sync.py +64 -0
Dockerfile ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:22-slim
2
+
3
+ # 1. 基础依赖
4
+ RUN apt-get update && apt-get install -y --no-install-recommends \
5
+ git openssh-client build-essential python3 python3-pip \
6
+ g++ make ca-certificates curl gettext \
7
+ # Playwright/Chrome 依赖
8
+ libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
9
+ libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 \
10
+ libxrandr2 libgbm1 libasound2 libpango-1.0-0 libcairo2 \
11
+ # FFmpeg 用于音频处理
12
+ ffmpeg \
13
+ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
14
+
15
+ # 安装 Playwright 和 Chromium(Playwright 会自动下载匹配的 Chromium)
16
+ RUN npx playwright install chromium --with-deps && \
17
+ mv /root/.cache/ms-playwright/chromium-* /root/.cache/ms-playwright/chromium
18
+
19
+ # 安装 huggingface_hub (系统不允许直接 pip 装到系统 Python,--break-system-packages强制绕过限制)
20
+ RUN pip3 install --no-cache-dir huggingface_hub --break-system-packages
21
+ # 安装 whisper 和 edge-tts
22
+ RUN pip3 install --no-cache-dir faster-whisper edge-tts --break-system-packages
23
+
24
+ # 2. 安装 OpenClaw
25
+ RUN npm install -g openclaw@latest --unsafe-perm
26
+
27
+
28
+ # 3. 设置工作目录并拷贝脚本
29
+ WORKDIR /app
30
+ COPY sync.py .
31
+ COPY start-openclaw.sh .
32
+ COPY openclaw.json .
33
+ RUN chmod +x start-openclaw.sh
34
+
35
+ # 4. 环境变量
36
+ ENV PORT=7860 HOME=/root
37
+
38
+ EXPOSE 7860
39
+ CMD ["./start-openclaw.sh"]
openclaw.json ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "models": {
3
+ "providers": {
4
+ "nvidia": {
5
+ "baseUrl": "https://integrate.api.nvidia.com/v1",
6
+ "apiKey": "${NVIDIA_API_KEY}",
7
+ "api": "openai-completions",
8
+ "models": [
9
+ { "id": "qwen/qwen3.5-397b-a17b", "name": "qwen/qwen3.5-397b-a17b", "input": ["text", "image"], "contextWindow": 128000, "maxTokens": 8192 },
10
+ { "id": "stepfun-ai/step-3.5-flash", "name": "stepfun-ai/step-3.5-flash", "input": ["text", "image"], "contextWindow": 256000, "maxTokens": 8192 },
11
+ { "id": "moonshotai/kimi-k2.5", "name": "moonshotai/kimi-k2.5", "input": ["text", "image"], "contextWindow": 256000, "maxTokens": 8192 },
12
+ { "id": "z-ai/glm4.7", "name": "z-ai/glm4.7", "input": ["text", "image"], "contextWindow": 128000, "maxTokens": 8192 },
13
+ { "id": "z-ai/glm5", "name": "z-ai/glm5", "input": ["text", "image"], "contextWindow": 128000, "maxTokens": 8192 },
14
+ { "id": "minimaxai/minimax-m2.5", "name": "minimaxai/minimax-m2.5", "input": ["text", "image"], "contextWindow": 192000, "maxTokens": 8192 }
15
+ ]
16
+ },
17
+ "qiniu": {
18
+ "baseUrl": "https://api.qnaigc.com/v1",
19
+ "apiKey": "${QINIU_API_KEY}",
20
+ "api": "openai-completions",
21
+ "models": [
22
+ { "id": "minimax/minimax-m2.5", "name": "minimax/minimax-m2.5", "input": ["text", "image"], "contextWindow": 128000, "maxTokens": 8192 }
23
+ ]
24
+ },
25
+ "silicon": {
26
+ "baseUrl": "https://api.siliconflow.cn/v1",
27
+ "apiKey": "${SF_API_KEY}",
28
+ "api": "openai-completions",
29
+ "models": [
30
+ { "id": "Pro/MiniMaxAI/MiniMax-M2.5", "name": "Pro/MiniMaxAI/MiniMax-M2.5", "input": ["text", "image"], "contextWindow": 128000, "maxTokens": 8192 }
31
+ ]
32
+ }
33
+ }
34
+ },
35
+ "agents": { "defaults": { "model": { "primary": "${MODEL}" } } },
36
+ "channels": {
37
+ "feishu": {
38
+ "enabled": true,
39
+ "groupChat": "enabled",
40
+ "requireMention": true,
41
+ "accounts": {
42
+ "default": {
43
+ "dmPolicy": "all"
44
+ },
45
+ "main": {
46
+ "appId": "${FEISHU_APP_ID}",
47
+ "appSecret": "${FEISHU_APP_SECRET}"
48
+ }
49
+ }
50
+ }
51
+ },
52
+ "gateway": {
53
+ "mode": "local", "bind": "lan", "port": 7860,
54
+ "trustedProxies": ["0.0.0.0/0"],
55
+ "auth": { "mode": "token", "token": "${OPENCLAW_GATEWAY_PASSWORD}" },
56
+ "controlUi": {
57
+ "allowInsecureAuth": true,
58
+ "dangerouslyDisableDeviceAuth": true,
59
+ "allowedOrigins": ["*"],
60
+ "dangerouslyAllowHostHeaderOriginFallback": true
61
+ },
62
+ "nodes": {
63
+ "browser": {
64
+ "mode": "auto"
65
+ }
66
+ }
67
+ },
68
+ "tools": {
69
+ "profile": "full",
70
+ "web": {
71
+ "search": {
72
+ "enabled": true,
73
+ "provider": "brave",
74
+ "apiKey": "${BRAVE_KEY}",
75
+ "maxResults": 5
76
+ },
77
+ "fetch": {
78
+ "enabled": true
79
+ }
80
+ },
81
+ "agentToAgent": {
82
+ "enabled": true
83
+ }
84
+ },
85
+ "browser": {
86
+ "enabled": true,
87
+ "headless": true,
88
+ "noSandbox": true,
89
+ "defaultProfile": "openclaw",
90
+ "executablePath": "/root/.cache/ms-playwright/chromium/chrome-linux64/chrome"
91
+ },
92
+ "commands": {
93
+ "native": "auto",
94
+ "nativeSkills": "auto",
95
+ "restart": true,
96
+ "ownerDisplay": "raw"
97
+ },
98
+ "session": {
99
+ "maintenance": {
100
+ "mode": "enforce",
101
+ "resetArchiveRetention": "1d"
102
+ }
103
+ },
104
+ "plugins": {
105
+ "entries": {}
106
+ }
107
+ }
start-openclaw.sh ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -ex # 打开调试输出
3
+
4
+ # 1. 补全目录
5
+ mkdir -p /root/.openclaw/
6
+
7
+ # 2. 执行恢复
8
+ python3 /app/sync.py restore
9
+
10
+ # 清理旧的 Chrome 锁文件(防止容器重启后 Chrome 无法启动)
11
+ rm -rf /root/.openclaw/browser/*/user-data/Singleton* /tmp/org.chromium.Chromium.* 2>/dev/null || true
12
+
13
+ # 3. 复制配置文件并替换环境变量
14
+ envsubst < /app/openclaw.json > /root/.openclaw/openclaw.json
15
+
16
+ # 4. 启动定时备份 (每 6 小时)
17
+ (while true; do sleep 21600; python3 /app/sync.py backup; done) &
18
+
19
+ # 5. 后台运行
20
+ openclaw gateway run --port $PORT &
21
+ wait
sync.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import tarfile
4
+ from huggingface_hub import HfApi, hf_hub_download
5
+
6
+ api = HfApi()
7
+ repo_id = os.getenv("HF_DATASET")
8
+ token = os.getenv("HF_TOKEN")
9
+ FILENAME = "openclaw_space.tar.gz"
10
+ BACKUP_ROOT = "/root/.openclaw"
11
+
12
+ def restore():
13
+ try:
14
+ if not repo_id or not token:
15
+ print("Skip Restore: HF_DATASET or HF_TOKEN not set")
16
+ return
17
+
18
+ # 直接下载最新文件
19
+ print(f"Downloading {FILENAME} from {repo_id}...")
20
+ path = hf_hub_download(repo_id=repo_id, filename=FILENAME, repo_type="dataset", token=token)
21
+ os.makedirs(BACKUP_ROOT, exist_ok=True)
22
+ with tarfile.open(path, "r:gz") as tar:
23
+ tar.extractall(path=BACKUP_ROOT)
24
+ print(f"Success: Restored from {FILENAME}")
25
+ return True
26
+ except Exception as e:
27
+ # 如果是第一次运行,仓库里没文件,报错是正常的
28
+ print(f"Restore Note: No existing backup found or error: {e}")
29
+
30
+ def backup():
31
+ try:
32
+ if not repo_id or not token:
33
+ print("Skip Backup: HF_DATASET or HF_TOKEN not set")
34
+ return
35
+
36
+ temp_tar_path = f"/tmp/{FILENAME}"
37
+ with tarfile.open(temp_tar_path, "w:gz") as tar:
38
+ # 打包整个 .openclaw 文件夹
39
+ if os.path.exists(BACKUP_ROOT):
40
+ # arcname="" 确保解压后直接是文件夹内容,不会多一层目录
41
+ tar.add(BACKUP_ROOT, arcname=".")
42
+ else:
43
+ print(f"Warning: {BACKUP_ROOT} does not exist")
44
+ return
45
+
46
+ # 上传并覆盖
47
+ api.upload_file(
48
+ path_or_fileobj=temp_tar_path,
49
+ path_in_repo=FILENAME,
50
+ repo_id=repo_id,
51
+ repo_type="dataset",
52
+ token=token
53
+ )
54
+ print(f"Backup {FILENAME} Success (Overwritten).")
55
+ # 清理临时文件
56
+ os.remove(temp_tar_path)
57
+ except Exception as e:
58
+ print(f"Backup Error: {e}")
59
+
60
+ if __name__ == "__main__":
61
+ if len(sys.argv) > 1 and sys.argv[1] == "backup":
62
+ backup()
63
+ else:
64
+ restore()