8900 commited on
Commit
b358479
Β·
verified Β·
1 Parent(s): c187893

Update setup-hf-config.mjs

Browse files
Files changed (1) hide show
  1. setup-hf-config.mjs +180 -109
setup-hf-config.mjs CHANGED
@@ -1,143 +1,214 @@
1
- import fs from "node:fs";
2
  import path from "node:path";
3
- import http from "node:http";
4
  import https from "node:https";
5
- import { execSync } from "node:child_process";
6
 
7
  // ============================================================
8
- // Config
 
9
  // ============================================================
10
 
11
- var OPENCLAW_DIR = path.join(
12
- process.env.OPENCLAW_HOME || process.env.HOME || "/home/user",
13
- ".openclaw"
14
- );
15
- var BOT_TOKEN = (process.env.TELEGRAM_BOT_TOKEN || "").trim();
16
- var HF_TOKEN = (process.env.HF_TOKEN || "").trim();
17
- var DATASET_ID = (process.env.HF_DATASET_ID || "").trim();
18
- var ADMIN_CHAT_ID = (process.env.SYNC_ADMIN_CHAT_ID || "").trim();
19
- var LOOP_INTERVAL = 30 * 1000;
20
- var PROXY_PORT = 7861;
21
-
22
- var REPO_DIR = "/tmp/hf-sync-repo";
23
- var STATE_FILE = path.join(OPENCLAW_DIR, ".sync-state.json");
24
-
25
- var ALWAYS_EXCLUDE = [".sync-state.json", ".git", "openclaw.json.bak"];
26
- var LOG_PATTERNS = [".log", ".log.", ".tmp", ".bak"];
27
-
28
- var SYNC_COMMANDS = [
29
- "/sync_all", "/sync_settings", "/sync_memory",
30
- "/pull_all", "/pull_settings", "/pull_memory",
31
- "/pause_all", "/pause_settings", "/pause_memory",
32
- "/pause_pull_settings", "/pause_pull_memory",
33
- "/resume_all", "/resume_settings", "/resume_memory",
34
- "/progress"
35
- ];
36
 
37
- // ============================================================
38
- // Task registry
39
- // ============================================================
40
 
41
- var tasks = {
42
- settings_upload: { active: false, timer: null, lastMsg: "idle" },
43
- settings_pull: { active: false, timer: null, lastMsg: "idle" },
44
- memory_upload: { active: false, timer: null, lastMsg: "idle" },
45
- memory_pull: { active: false, timer: null, lastMsg: "idle" }
46
- };
47
 
48
- function setTaskMsg(key, msg) {
49
- tasks[key].lastMsg = msg;
50
- console.log("[sync:" + key + "] " + msg);
51
  }
52
 
53
- // ============================================================
54
- // State
55
- // ============================================================
56
 
57
- function loadState() {
58
- try {
59
- if (fs.existsSync(STATE_FILE)) {
60
- return JSON.parse(fs.readFileSync(STATE_FILE, "utf-8"));
 
 
 
 
61
  }
62
- } catch (e) {}
63
- return {
64
- settings: { lastUpload: null, lastPull: null },
65
- memory: { lastUpload: null, lastPull: null }
66
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
- function saveState(state) {
70
- try {
71
- fs.mkdirSync(OPENCLAW_DIR, { recursive: true });
72
- fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), "utf-8");
73
- } catch (e) {}
 
 
 
74
  }
 
75
 
76
- function nowTs() {
77
- return new Date().toISOString().replace("T", " ").substring(0, 19);
 
78
  }
79
 
80
- // ============================================================
81
- // Progress bar
82
- // ============================================================
 
 
 
 
 
 
 
 
 
 
83
 
84
- function bar(done, total) {
85
- var width = 10;
86
- var filled = total > 0 ? Math.round((done / total) * width) : 0;
87
- var pct = total > 0 ? Math.round((done / total) * 100) : 0;
88
- var b = "";
89
- for (var i = 0; i < width; i++) b += i < filled ? "=" : "-";
90
- return "[" + b + "] " + pct + "% (" + done + "/" + total + ")";
 
 
 
 
 
 
 
 
 
 
 
91
  }
 
 
 
 
 
92
 
93
- // ============================================================
94
- // Git helpers
95
- // ============================================================
96
-
97
- function repoUrl() {
98
- return "https://user:" + HF_TOKEN +
99
- "@huggingface.co/datasets/" + DATASET_ID;
100
  }
101
 
102
- function git(args, cwd) {
103
- return execSync("git " + args, {
104
- cwd: cwd || REPO_DIR,
105
- stdio: "pipe",
106
- timeout: 60000,
107
- env: Object.assign({}, process.env, { GIT_TERMINAL_PROMPT: "0" })
108
- }).toString().trim();
 
 
 
 
 
 
 
 
109
  }
110
 
111
- function ensureRepo() {
112
- if (fs.existsSync(path.join(REPO_DIR, ".git"))) return;
113
- execSync("rm -rf " + REPO_DIR, { stdio: "pipe" });
 
 
 
 
 
 
114
  try {
115
- git("clone --depth 1 " + repoUrl() + " " + REPO_DIR, "/tmp");
 
 
116
  } catch (e) {
117
- fs.mkdirSync(REPO_DIR, { recursive: true });
118
- git("init", REPO_DIR);
119
- git("remote add origin " + repoUrl(), REPO_DIR);
120
  }
121
- try {
122
- git("config user.email openclaw@hf.space");
123
- git("config user.name OpenClaw-Sync");
124
- } catch (e) {}
125
  }
126
 
127
- function pullLatest() {
128
- try { git("pull --quiet --no-rebase origin main"); }
129
- catch (e) {
130
- try { git("pull --quiet --no-rebase origin master"); } catch (e2) {}
 
 
 
 
 
 
 
 
 
 
131
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
133
 
134
- function commitAndPush(msg) {
135
- git("add -A");
136
- var changed = git("diff --cached --name-only");
137
- if (!changed) return 0;
138
- var count = changed.split("\n").filter(Boolean).length;
139
- git('commit -m "' + msg + '"');
140
- try { git("push --quiet origin HEAD:main"); }
141
- catch (e) { git("push --quiet origin HEAD:master"); }
142
- return count;
143
- }
 
1
+ import fs from "node:fs";
2
  import path from "node:path";
 
3
  import https from "node:https";
 
4
 
5
  // ============================================================
6
+ // OpenClaw HF Spaces - Production Config Writer
7
+ // Reads env vars, writes openclaw.json, auto-detects providers
8
  // ============================================================
9
 
10
+ var HOME = process.env.OPENCLAW_HOME || process.env.HOME || "/home/user";
11
+ var STATE_DIR = path.join(HOME, ".openclaw");
12
+ var CONFIG_PATH = path.join(STATE_DIR, "openclaw.json");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ console.log("[setup] Starting... HOME=" + HOME);
 
 
15
 
16
+ // –– helpers ———————————————–
 
 
 
 
 
17
 
18
+ function parseList(val) {
19
+ if (!val || !val.trim()) return [];
20
+ return val.split(",").map(function(s) { return s.trim(); }).filter(Boolean);
21
  }
22
 
23
+ function envStr(key) {
24
+ return (process.env[key] || "").trim();
25
+ }
26
 
27
+ // –– auth –––––––––––––––––––––––––
28
+
29
+ var gatewayToken = envStr("OPENCLAW_GATEWAY_TOKEN");
30
+ var gatewayPassword = envStr("OPENCLAW_GATEWAY_PASSWORD");
31
+
32
+ if (!gatewayToken && !gatewayPassword) {
33
+ console.error("[setup] FATAL: set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD in Secrets");
34
+ process.exit(1);
35
  }
36
+
37
+ // –– default model —————————————–
38
+ // Override via OPENCLAW_HF_DEFAULT_MODEL secret
39
+
40
+ var defaultModel = envStr("OPENCLAW_HF_DEFAULT_MODEL") || "google/gemini-2.0-flash";
41
+
42
+ // –– dynamic provider key detection β€”β€”β€”β€”β€”β€”β€”β€”
43
+ // Rule: include if ends with one of INCLUDE_SUFFIXES
44
+ // exclude if starts with one of EXCLUDE_PREFIXES
45
+ // OpenClaw reads API keys from process env AND from env.vars in config.
46
+ // We write them into env.vars so they survive across runtimes.
47
+
48
+ var EXCLUDE_PREFIXES = [
49
+ "OPENCLAW_", "SPACE_", "SYSTEM_", "HF_",
50
+ "NODE_", "PATH", "HOME", "USER", "PWD", "LANG", "LC_",
51
+ "npm_", "HOSTNAME", "SHELL", "TERM", "SHLVL"
52
+ ];
53
+
54
+ var INCLUDE_SUFFIXES = [
55
+ "_API_KEY", "_SECRET_KEY", "_ACCESS_TOKEN",
56
+ "_BOT_TOKEN", "_AUTH_TOKEN", "_APP_KEY"
57
+ ];
58
+
59
+ function isProviderKey(k) {
60
+ var i;
61
+ for (i = 0; i < EXCLUDE_PREFIXES.length; i++) {
62
+ if (k.indexOf(EXCLUDE_PREFIXES[i]) === 0) return false;
63
+ }
64
+ for (i = 0; i < INCLUDE_SUFFIXES.length; i++) {
65
+ var s = INCLUDE_SUFFIXES[i];
66
+ if (k.length > s.length && k.indexOf(s) === k.length - s.length) return true;
67
+ }
68
+ return false;
69
  }
70
 
71
+ var allKeys = Object.keys(process.env);
72
+ var providerKeys = [];
73
+ var i;
74
+ for (i = 0; i < allKeys.length; i++) {
75
+ var k = allKeys[i];
76
+ if (isProviderKey(k) && (process.env[k] || "").trim()) {
77
+ providerKeys.push(k);
78
+ }
79
  }
80
+ providerKeys.sort();
81
 
82
+ console.log("[setup] Detected provider keys (" + providerKeys.length + "):");
83
+ for (i = 0; i < providerKeys.length; i++) {
84
+ console.log(" + " + providerKeys[i]);
85
  }
86
 
87
+ // –– trusted proxies β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
88
+
89
+ var envProxies = parseList(envStr("OPENCLAW_GATEWAY_TRUSTED_PROXIES"));
90
+ var trustedProxies = envProxies.length > 0 ? envProxies : [
91
+ "10.16.0.0/12",
92
+ "10.20.0.0/12",
93
+ "10.16.4.123", "10.16.7.92", "10.16.18.232",
94
+ "10.16.34.155", "10.16.43.133", "10.16.1.206",
95
+ "10.16.37.110", "10.16.43.246",
96
+ "10.20.1.9", "10.20.1.222",
97
+ "10.20.26.157", "10.20.31.87",
98
+ "10.20.0.1", "172.17.0.1"
99
+ ];
100
 
101
+ // –– build base config ———————————––
102
+
103
+ var config = {
104
+ gateway: {
105
+ auth: gatewayToken
106
+ ? { mode: "token", token: gatewayToken }
107
+ : { mode: "password", password: gatewayPassword },
108
+ controlUi: {
109
+ allowInsecureAuth: true,
110
+ allowedOrigins: ["*"],
111
+ dangerouslyDisableDeviceAuth: true,
112
+ dangerouslyAllowHostHeaderOriginFallback: true
113
+ },
114
+ trustedProxies: trustedProxies
115
+ },
116
+ agents: {
117
+ defaults: {
118
+ model: defaultModel
119
  }
120
+ },
121
+ env: {
122
+ vars: {}
123
+ }
124
+ };
125
 
126
+ // Write all provider keys into env.vars
127
+ // OpenClaw injects env.vars into its runtime environment
128
+ for (i = 0; i < providerKeys.length; i++) {
129
+ var pk = providerKeys[i];
130
+ config.env.vars[pk] = (process.env[pk] || "").trim();
 
 
131
  }
132
 
133
+ // –– Telegram: auto-detect best reachable node ———––
134
+
135
+ function tryTelegramNode(node, token, timeoutMs) {
136
+ return new Promise(function(resolve, reject) {
137
+ var url = node + "/bot" + token + "/getMe";
138
+ var req = https.get(url, function(res) {
139
+ if (res.statusCode === 200) resolve(node);
140
+ else reject(new Error("HTTP " + res.statusCode));
141
+ });
142
+ req.on("error", reject);
143
+ req.setTimeout(timeoutMs, function() {
144
+ req.destroy();
145
+ reject(new Error("Timeout"));
146
+ });
147
+ });
148
  }
149
 
150
+ var TELEGRAM_NODES = [
151
+ "https://api.telegram.org",
152
+ "https://tg-api.vercel.app",
153
+ "https://telegram-bot-api.vercel.app"
154
+ ];
155
+
156
+ async function detectTelegramNode(token) {
157
+ for (var j = 0; j < TELEGRAM_NODES.length; j++) {
158
+ var node = TELEGRAM_NODES[j];
159
  try {
160
+ await tryTelegramNode(node, token, 4000);
161
+ console.log("[setup] Telegram node reachable: " + node);
162
+ return node.replace(/\/$/, "");
163
  } catch (e) {
164
+ console.log("[setup] Telegram node unreachable: " + node + " (" + e.message + ")");
 
 
165
  }
166
+ }
167
+ return null;
 
 
168
  }
169
 
170
+ async function setupTelegram() {
171
+ var token = envStr("TELEGRAM_BOT_TOKEN");
172
+ if (!token) {
173
+ console.log("[setup] Telegram: disabled (no TELEGRAM_BOT_TOKEN)");
174
+ return;
175
+ }
176
+ var bestNode = await detectTelegramNode(token);
177
+ var finalRoot = bestNode || TELEGRAM_NODES[0];
178
+ config.channels = {
179
+ telegram: {
180
+ enabled: true,
181
+ accounts: {
182
+ main: { botToken: token, apiRoot: finalRoot }
183
+ }
184
  }
185
+ };
186
+ console.log("[setup] Telegram: enabled, apiRoot=" + finalRoot);
187
+ }
188
+
189
+ // –– main –––––––––––––––––––––––––
190
+
191
+ (async function main() {
192
+ await setupTelegram();
193
+
194
+ try {
195
+ fs.mkdirSync(STATE_DIR, { recursive: true });
196
+ if (fs.existsSync(CONFIG_PATH)) {
197
+ fs.copyFileSync(CONFIG_PATH, CONFIG_PATH + ".bak");
198
+ }
199
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
200
+ } catch (e) {
201
+ console.error("[setup] Write failed: " + e.message);
202
+ process.exit(1);
203
  }
204
 
205
+ console.log("[setup] Done.");
206
+ console.log("[setup] auth = " + (gatewayToken ? "token" : "password"));
207
+ console.log("[setup] model = " + defaultModel);
208
+ console.log("[setup] proxies = " + trustedProxies.length);
209
+ console.log("[setup] env.vars = " + providerKeys.length);
210
+ console.log("[setup] config = " + CONFIG_PATH);
211
+ })().catch(function(e) {
212
+ console.error("[setup] Fatal: " + e.message);
213
+ process.exit(1);
214
+ });