Spaces:
Paused
Paused
Download setup-hf-config.mjs from Tonic/hugging-claw: direct link, hf CLI and curl.
- Browser
- Download file 4.99 kB
-
https://huggingface.co/spaces/Tonic/hugging-claw/resolve/main/setup-hf-config.mjs
- Command line
-
hf download hf://spaces/Tonic/hugging-claw/setup-hf-config.mjs
-
curl -L -o setup-hf-config.mjs https://huggingface.co/spaces/Tonic/hugging-claw/resolve/main/setup-hf-config.mjs
4.99 kB
| /** | |
| * One-time setup for OpenClaw on Hugging Face Spaces. | |
| * Runs at container startup; writes or merges openclaw.json from env (Secrets/Variables): | |
| * - agents.defaults.model.primary from OPENCLAW_HF_DEFAULT_MODEL (default: DeepSeek-R1). | |
| * - gateway.auth: OPENCLAW_GATEWAY_TOKEN (token) or OPENCLAW_GATEWAY_PASSWORD (password); token wins if both set. | |
| * - gateway.controlUi.dangerouslyDisableDeviceAuth when auth is set (no device pairing in Spaces). | |
| * - gateway.trustedProxies from OPENCLAW_GATEWAY_TRUSTED_PROXIES, or default HF proxy IPs so the UI works without extra config. | |
| * - gateway.controlUi.allowedOrigins from OPENCLAW_CONTROL_UI_ALLOWED_ORIGINS (comma-separated origins). | |
| * HF_TOKEN is read by the gateway at runtime; this script only writes the above into config. | |
| */ | |
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| const home = process.env.OPENCLAW_HOME || process.env.HOME || "/home/user"; | |
| const stateDir = path.join(home, ".openclaw"); | |
| const configPath = path.join(stateDir, "openclaw.json"); | |
| // Token: env var, or read from file if OPENCLAW_GATEWAY_TOKEN_FILE is set (for platforms that mount secrets as files) | |
| function readGatewayToken() { | |
| const fromEnv = process.env.OPENCLAW_GATEWAY_TOKEN?.trim(); | |
| if (fromEnv) return fromEnv; | |
| const filePath = process.env.OPENCLAW_GATEWAY_TOKEN_FILE?.trim(); | |
| if (filePath && fs.existsSync(filePath)) { | |
| try { | |
| return fs.readFileSync(filePath, "utf-8").trim(); | |
| } catch { | |
| return ""; | |
| } | |
| } | |
| return ""; | |
| } | |
| const defaultModel = | |
| process.env.OPENCLAW_HF_DEFAULT_MODEL?.trim() || "huggingface/deepseek-ai/DeepSeek-R1"; | |
| const gatewayToken = readGatewayToken(); | |
| const gatewayPassword = process.env.OPENCLAW_GATEWAY_PASSWORD?.trim(); | |
| // Trusted proxies: from env, or default HF Space proxy IPs so the Control UI works without setting OPENCLAW_GATEWAY_TRUSTED_PROXIES | |
| const DEFAULT_HF_TRUSTED_PROXY_IPS = [ | |
| "10.16.4.123", | |
| "10.16.34.155", | |
| "10.20.1.9", | |
| "10.20.1.222", | |
| "10.20.26.157", | |
| "10.20.31.87", | |
| ]; | |
| const trustedProxiesRaw = process.env.OPENCLAW_GATEWAY_TRUSTED_PROXIES?.trim(); | |
| const trustedProxies = | |
| trustedProxiesRaw && trustedProxiesRaw.length > 0 | |
| ? trustedProxiesRaw.split(",").map((s) => s.trim()).filter(Boolean) | |
| : DEFAULT_HF_TRUSTED_PROXY_IPS; | |
| // Comma-separated origins allowed for Control UI/WebSocket (e.g. https://your-space.hf.space) | |
| const allowedOriginsRaw = process.env.OPENCLAW_CONTROL_UI_ALLOWED_ORIGINS?.trim(); | |
| const allowedOrigins = allowedOriginsRaw | |
| ? allowedOriginsRaw.split(",").map((s) => s.trim()).filter(Boolean) | |
| : []; | |
| let config = {}; | |
| if (fs.existsSync(configPath)) { | |
| try { | |
| config = JSON.parse(fs.readFileSync(configPath, "utf-8")); | |
| } catch { | |
| // keep config empty | |
| } | |
| } | |
| if (!config.agents) config.agents = {}; | |
| if (!config.agents.defaults) config.agents.defaults = {}; | |
| if (!config.agents.defaults.model) config.agents.defaults.model = {}; | |
| config.agents.defaults.model.primary = defaultModel; | |
| // Auth: token wins if both set; otherwise password | |
| const useTokenAuth = Boolean(gatewayToken); | |
| const usePasswordAuth = Boolean(gatewayPassword) && !useTokenAuth; | |
| if (useTokenAuth || usePasswordAuth) { | |
| if (!config.gateway) config.gateway = {}; | |
| if (!config.gateway.auth) config.gateway.auth = {}; | |
| if (useTokenAuth) { | |
| config.gateway.auth.mode = "token"; | |
| config.gateway.auth.token = gatewayToken; | |
| } else { | |
| config.gateway.auth.mode = "password"; | |
| config.gateway.auth.password = gatewayPassword; | |
| } | |
| } | |
| // So Control UI can connect with token/password only (no device pairing); Spaces have no CLI for approve. | |
| if (useTokenAuth || usePasswordAuth) { | |
| if (!config.gateway) config.gateway = {}; | |
| if (!config.gateway.controlUi) config.gateway.controlUi = {}; | |
| config.gateway.controlUi.dangerouslyDisableDeviceAuth = true; | |
| } | |
| // Always set trustedProxies (we have a default for HF so the Control UI works behind the HF proxy) | |
| if (!config.gateway) config.gateway = {}; | |
| config.gateway.trustedProxies = trustedProxies; | |
| if (allowedOrigins.length > 0) { | |
| if (!config.gateway) config.gateway = {}; | |
| if (!config.gateway.controlUi) config.gateway.controlUi = {}; | |
| config.gateway.controlUi.allowedOrigins = allowedOrigins; | |
| } | |
| fs.mkdirSync(stateDir, { recursive: true }); | |
| fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8"); | |
| // Startup log: confirm env was applied (check token_present=1 and auth=token so the UI can connect) | |
| const authKind = useTokenAuth ? "token" : usePasswordAuth ? "password" : "none"; | |
| const parts = [ | |
| `token_present=${useTokenAuth ? "1" : "0"}`, | |
| `password_present=${usePasswordAuth ? "1" : "0"}`, | |
| `auth=${authKind}`, | |
| `trustedProxies=${trustedProxies.length}`, | |
| `allowedOrigins=${allowedOrigins.length}`, | |
| ]; | |
| console.log(`[openclaw-hf-setup] ${parts.join(" ")} -> ${configPath}`); | |
| if (authKind === "none") { | |
| console.warn( | |
| "[openclaw-hf-setup] No auth set. Add OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD in Space Secrets, then restart.", | |
| ); | |
| } | |