8900 commited on
Commit
196d2aa
·
verified ·
1 Parent(s): 837476f

Update entrypoint.sh

Browse files
Files changed (1) hide show
  1. entrypoint.sh +161 -56
entrypoint.sh CHANGED
@@ -1,56 +1,161 @@
1
- #!/bin/sh
2
-
3
- # resolve OPENCLAW_HOME
4
- if mkdir -p /data/.openclaw 2>/dev/null; then
5
- export OPENCLAW_HOME=/data
6
- else
7
- export OPENCLAW_HOME=/home/user
8
- mkdir -p /home/user/.openclaw
9
- fi
10
-
11
- echo "[entrypoint] OPENCLAW_HOME=$OPENCLAW_HOME"
12
-
13
- # dynamically export all provider keys so openclaw gateway can read them
14
- # matches: anything ending in _API_KEY, _SECRET_KEY, _ACCESS_TOKEN, _BOT_TOKEN, _AUTH_TOKEN, _APP_KEY, _TOKEN
15
- # excludes: OPENCLAW_SPACE_SYSTEM_NODE_HF_TOKEN_vars
16
- for VAR in $(env | cut -d= -f1); do
17
- case "$VAR" in
18
- OPENCLAW_*|SPACE_*|SYSTEM_*|NODE_*|HF_SPACE*) continue ;;
19
- esac
20
- case "$VAR" in
21
- *API_KEY|*SECRET_KEY|*ACCESS_TOKEN|*BOT_TOKEN|*AUTH_TOKEN|*APP_KEY|*_TOKEN)
22
- eval VAL=\$VAR
23
- if [ -n "$VAL" ]; then
24
- export "$VAR"
25
- echo "[entrypoint] exported: $VAR"
26
- fi
27
- ;;
28
- esac
29
- done
30
-
31
- # also always export HF_TOKEN for dataset sync
32
- export HF_TOKEN="${HF_TOKEN:-}"
33
-
34
- # restore from HF Dataset (30s timeout, non-fatal)
35
- if [ -n "$HF_TOKEN" ] && [ -n "$HF_DATASET_ID" ]; then
36
- echo "[entrypoint] Restoring from dataset ${HF_DATASET_ID}..."
37
- timeout 30 sh /app/hf-sync.sh restore || echo "[entrypoint] Restore skipped (no dataset or no token)"
38
- fi
39
-
40
- # write openclaw config
41
- node /app/spaces/huggingface/setup-hf-config.mjs || true
42
-
43
- # run security check (non-fatal)
44
- if [ -f /app/security-check.sh ]; then
45
- sh /app/security-check.sh || true
46
- fi
47
-
48
- echo "[entrypoint] starting gateway..."
49
-
50
- # start background sync loop
51
- if [ -n "$HF_TOKEN" ] && [ -n "$HF_DATASET_ID" ]; then
52
- sh /app/hf-sync.sh loop &
53
- echo "[entrypoint] sync loop started (interval=${HF_SYNC_INTERVAL:-3600}s)"
54
- fi
55
-
56
- exec node /app/openclaw.mjs gateway --allow-unconfigured --bind lan --port 7860
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import https from "node:https";
4
+
5
+ var HOME = process.env.OPENCLAW_HOME || process.env.HOME || "/home/user";
6
+ var STATE_DIR = path.join(HOME, ".openclaw");
7
+ var CONFIG_PATH = path.join(STATE_DIR, "openclaw.json");
8
+
9
+ console.log("[setup] Starting... HOME=" + HOME);
10
+
11
+ function parseList(val) {
12
+ if (!val || !val.trim()) return [];
13
+ return val.split(",").map(function(s) { return s.trim(); }).filter(Boolean);
14
+ }
15
+
16
+ // ---- auth ----
17
+ var gatewayToken = (process.env.OPENCLAW_GATEWAY_TOKEN || "").trim();
18
+ var gatewayPassword = (process.env.OPENCLAW_GATEWAY_PASSWORD || "").trim();
19
+
20
+ if (!gatewayToken && !gatewayPassword) {
21
+ console.error("[setup] ERROR: set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD");
22
+ process.exit(1);
23
+ }
24
+
25
+ // ---- default model ----
26
+ var defaultModel = (process.env.OPENCLAW_HF_DEFAULT_MODEL || "").trim() || "google/gemini-2.0-flash";
27
+
28
+ // ---- dynamic provider key detection ----
29
+ // OpenClaw official mechanism: reads provider keys from process env vars.
30
+ // We also write them into env.vars so OpenClaw injects them into its runtime.
31
+ // Exclude internal/system vars, include only provider-shaped keys.
32
+ var EXCLUDE_PREFIXES = [
33
+ "OPENCLAW_", "SPACE_", "SYSTEM_", "HF_SPACE",
34
+ "NODE_", "PATH", "HOME", "USER", "PWD", "LANG", "LC_"
35
+ ];
36
+ var INCLUDE_SUFFIXES = [
37
+ "_API_KEY", "_SECRET_KEY", "_ACCESS_TOKEN",
38
+ "_BOT_TOKEN", "_AUTH_TOKEN", "_APP_KEY", "_TOKEN"
39
+ ];
40
+
41
+ function isProviderKey(k) {
42
+ for (var i = 0; i < EXCLUDE_PREFIXES.length; i++) {
43
+ if (k.indexOf(EXCLUDE_PREFIXES[i]) === 0) return false;
44
+ }
45
+ for (var j = 0; j < INCLUDE_SUFFIXES.length; j++) {
46
+ var s = INCLUDE_SUFFIXES[j];
47
+ if (k.length > s.length && k.indexOf(s) === k.length - s.length) return true;
48
+ }
49
+ return false;
50
+ }
51
+
52
+ var detectedKeys = Object.keys(process.env)
53
+ .filter(function(k) { return isProviderKey(k) && (process.env[k] || "").trim(); })
54
+ .sort();
55
+
56
+ console.log("[setup] Detected provider keys (" + detectedKeys.length + "):");
57
+ detectedKeys.forEach(function(k) { console.log(" + " + k); });
58
+
59
+ // ---- proxies ----
60
+ var envProxies = parseList(process.env.OPENCLAW_GATEWAY_TRUSTED_PROXIES);
61
+ var trustedProxies = envProxies.length > 0 ? envProxies : [
62
+ "10.16.4.123", "10.16.7.92", "10.16.18.232",
63
+ "10.16.34.155", "10.16.43.133", "10.16.1.206",
64
+ "10.20.1.9", "10.20.1.222",
65
+ "10.20.26.157", "10.20.31.87",
66
+ "10.20.0.1", "172.17.0.1"
67
+ ];
68
+
69
+ // ---- build config ----
70
+ var config = {
71
+ gateway: {
72
+ auth: gatewayToken
73
+ ? { mode: "token", token: gatewayToken }
74
+ : { mode: "password", password: gatewayPassword },
75
+ controlUi: {
76
+ allowInsecureAuth: true,
77
+ dangerouslyAllowHostHeaderOriginFallback: true
78
+ },
79
+ trustedProxies: trustedProxies
80
+ },
81
+ agents: {
82
+ defaults: {
83
+ model: defaultModel
84
+ }
85
+ },
86
+ // Write detected keys into env.vars so OpenClaw injects them into its runtime.
87
+ // This is the official OpenClaw mechanism for env-based provider auth.
88
+ env: { vars: {} }
89
+ };
90
+
91
+ detectedKeys.forEach(function(k) {
92
+ config.env.vars[k] = (process.env[k] || "").trim();
93
+ });
94
+
95
+ // ---- Telegram - auto detect best reachable node ----
96
+ async function detectTelegramNode(nodes, token) {
97
+ for (var i = 0; i < nodes.length; i++) {
98
+ var node = nodes[i];
99
+ try {
100
+ await new Promise(function(resolve, reject) {
101
+ var req = https.get(node + "/bot" + token + "/getMe", function(res) {
102
+ if (res.statusCode === 200) resolve(true);
103
+ else reject(new Error("HTTP " + res.statusCode));
104
+ });
105
+ req.on("error", reject);
106
+ req.setTimeout(4000, function() { req.destroy(); reject(new Error("Timeout")); });
107
+ });
108
+ console.log("[setup] Telegram node reachable: " + node);
109
+ // Strip trailing slash
110
+ return node.replace(/\/$/, "");
111
+ } catch (e) {
112
+ console.log("[setup] Telegram node unreachable: " + node + " (" + e.message + ")");
113
+ }
114
+ }
115
+ return null;
116
+ }
117
+
118
+ var TELEGRAM_NODES = [
119
+ "https://api.telegram.org",
120
+ "https://tg-api.vercel.app",
121
+ "https://telegram-bot-api.vercel.app"
122
+ ];
123
+
124
+ async function setupTelegram() {
125
+ var token = (process.env.TELEGRAM_BOT_TOKEN || "").trim();
126
+ if (!token) { console.log("[setup] Telegram: disabled"); return; }
127
+ var apiRoot = await detectTelegramNode(TELEGRAM_NODES, token);
128
+ var finalRoot = apiRoot || TELEGRAM_NODES[0];
129
+ config.channels = {
130
+ telegram: {
131
+ enabled: true,
132
+ accounts: { main: { botToken: token, apiRoot: finalRoot } }
133
+ }
134
+ };
135
+ console.log("[setup] Telegram: enabled, apiRoot=" + finalRoot);
136
+ }
137
+
138
+ // ---- main ----
139
+ async function main() {
140
+ await setupTelegram();
141
+
142
+ try {
143
+ fs.mkdirSync(STATE_DIR, { recursive: true });
144
+ if (fs.existsSync(CONFIG_PATH)) {
145
+ fs.copyFileSync(CONFIG_PATH, CONFIG_PATH + ".bak");
146
+ }
147
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
148
+ } catch (e) {
149
+ console.error("[setup] Write failed: " + e.message);
150
+ process.exit(1);
151
+ }
152
+
153
+ console.log("[setup] Done. auth=" + (gatewayToken ? "token" : "password") +
154
+ " model=" + defaultModel + " proxies=" + trustedProxies.length +
155
+ " env.vars=" + detectedKeys.length);
156
+ }
157
+
158
+ main().then(() => process.exit(0)).catch(function(e) {
159
+ console.error("[setup] Fatal: " + e.message);
160
+ process.exit(1);
161
+ });