FROM ghcr.io/openclaw/openclaw:latest USER root # Copy Space repo files into container COPY openclaw.json /app/openclaw-template.json COPY setup-hf-config.mjs /app/spaces/huggingface/setup-hf-config.mjs COPY entrypoint.sh /app/entrypoint.sh COPY security-check.sh /app/security-check.sh # PATCH: suppress meta.lastTouchedAt from triggering gateway restarts # Issue: https://github.com/openclaw/openclaw/issues/11744 # Every config write updates meta.lastTouchedAt which is not in # BASE_RELOAD_RULES, causing a full gateway restart on every save. # Fix: inject {prefix:"meta",kind:"none"} into BASE_RELOAD_RULES. RUN node -e " \ const fs = require('fs'); \ const { execSync } = require('child_process'); \ function findBundles() { \ try { \ const out = execSync('find /app -name \"gateway-cli*.js\" -not -path \"*/node_modules/*\" 2>/dev/null').toString().trim(); \ return out ? out.split('\n').filter(Boolean) : []; \ } catch(e) { return []; } \ } \ const bundles = findBundles(); \ if (bundles.length === 0) { console.log('[patch] No bundle found'); process.exit(0); } \ let patched = 0; \ bundles.forEach(function(file) { \ let src = fs.readFileSync(file, 'utf-8'); \ if (src.includes('prefix:\"meta\"') || src.includes(\"prefix:'meta'\")) { \ console.log('[patch] Already patched: ' + file); return; \ } \ const patterns = [ \ ['{prefix:\"channels\",kind:', '{prefix:\"meta\",kind:\"none\"},{prefix:\"channels\",kind:'], \ ['{prefix:\"update\",kind:', '{prefix:\"meta\",kind:\"none\"},{prefix:\"update\",kind:'], \ ['{prefix:\"agents\",kind:', '{prefix:\"meta\",kind:\"none\"},{prefix:\"agents\",kind:'] \ ]; \ let applied = false; \ for (let i = 0; i < patterns.length; i++) { \ if (src.includes(patterns[i][0])) { \ src = src.replace(patterns[i][0], patterns[i][1]); \ applied = true; break; \ } \ } \ if (applied) { \ fs.writeFileSync(file, src, 'utf-8'); \ console.log('[patch] Patched: ' + file); \ patched++; \ } else { \ console.log('[patch] Pattern not found in: ' + file); \ } \ }); \ console.log('[patch] Done. ' + patched + '/' + bundles.length + ' file(s) patched'); \ " || echo "[patch] Non-fatal: patch step failed" # Ensure /data is world-writable so HF Storage Bucket mount is accessible RUN chmod +x /app/entrypoint.sh /app/security-check.sh && \ mkdir -p /data && chmod 777 /data && \ mkdir -p /home/user && chmod 777 /home/user USER root EXPOSE 7860 ENTRYPOINT ["/app/entrypoint.sh"]