File size: 5,310 Bytes
0a24085
01a571d
dd094e5
 
 
 
 
 
 
 
 
 
 
 
 
 
01a571d
 
 
dd094e5
 
 
 
 
01a571d
 
dd094e5
 
01a571d
dd094e5
 
 
 
 
 
 
 
 
01a571d
afe3e7c
 
dd094e5
01a571d
dd094e5
 
 
7684a29
8924dbd
 
 
 
 
 
 
 
dd094e5
8924dbd
 
 
7684a29
 
6af251e
ad67ccc
dd094e5
 
 
08da1b7
 
dd094e5
01a571d
dd094e5
 
 
ad67ccc
8924dbd
ad67ccc
 
dd094e5
 
 
c0df9f7
8924dbd
 
dd094e5
8924dbd
 
 
 
 
 
c0df9f7
dd094e5
 
 
c0df9f7
dd094e5
8924dbd
 
 
 
 
dd094e5
8924dbd
dd094e5
 
 
 
 
 
 
 
 
 
01a571d
c0df9f7
8924dbd
 
c0df9f7
bdea495
dd094e5
 
d30ca03
 
 
 
 
 
 
 
 
dd094e5
 
01a571d
c0df9f7
dd094e5
 
8924dbd
 
 
 
dd094e5
 
 
 
 
 
fd83f78
dd094e5
 
 
fd83f78
dd094e5
 
 
fd83f78
 
 
dd094e5
 
 
 
 
fd83f78
dd094e5
01a571d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/sh
# OpenClaw HF Spaces - Production Entrypoint
# Storage: HF Storage Bucket at /data (100 GB persistent)

# ----------------------------------------------------------------
# Logging
# ----------------------------------------------------------------
ts() { date -u +"%H:%M:%S"; }
log()  { echo "[$(ts)] [entrypoint] $*"; }
warn() { echo "[$(ts)] [entrypoint] WARN: $*"; }

# ----------------------------------------------------------------
# Storage: resolve OPENCLAW_HOME
# Prefer /data (HF Storage Bucket). Fall back to /home/user.
# Retry up to 5s in case the bucket mount is slightly delayed.
# ----------------------------------------------------------------
OPENCLAW_HOME=/home/user
mkdir -p /home/user/.openclaw

RETRIES=5
i=0
while [ $i -lt $RETRIES ]; do
  if [ -d /data ] && touch /data/.write-test 2>/dev/null; then
    rm -f /data/.write-test
    OPENCLAW_HOME=/data
    mkdir -p /data/.openclaw
    log "Storage bucket /data is writable - using persistent storage"
    break
  fi
  i=$((i+1))
  if [ $i -lt $RETRIES ]; then
    log "Waiting for /data mount... ($i/$RETRIES)"
    sleep 1
  fi
done

if [ "$OPENCLAW_HOME" = "/home/user" ]; then
  warn "/data not writable after ${RETRIES}s - using ephemeral /home/user"
fi

export OPENCLAW_HOME
log "OPENCLAW_HOME=$OPENCLAW_HOME"

# ----------------------------------------------------------------
# Export provider API keys from Secrets
# ----------------------------------------------------------------
for VAR in $(env | cut -d= -f1); do
  case "$VAR" in
    OPENCLAW_*|SPACE_*|SYSTEM_*|HF_*|NODE_*|npm_*) continue ;;
  esac
  case "$VAR" in
    *_API_KEY|*_SECRET_KEY|*_ACCESS_TOKEN|*_BOT_TOKEN|*_AUTH_TOKEN|*_APP_KEY)
      VAL=$(printenv "$VAR" 2>/dev/null || true)
      if [ -n "$VAL" ]; then
        export "$VAR"
        log "exported: $VAR"
      fi
      ;;
  esac
done

export HF_TOKEN="${HF_TOKEN:-}"

# ----------------------------------------------------------------
# One-time setup (config write, webhook registration, seed files)
# ----------------------------------------------------------------
log "Running setup..."
node /app/spaces/huggingface/setup-hf-config.mjs || true
log "Setup done."

# ----------------------------------------------------------------
# Security audit (non-fatal)
# ----------------------------------------------------------------
if [ -f /app/security-check.sh ]; then
  sh /app/security-check.sh || true
fi

# ----------------------------------------------------------------
# Auto-approve pending device pairings (background)
# ----------------------------------------------------------------
(
  DEVICES_DIR="$OPENCLAW_HOME/.openclaw/devices"
  mkdir -p "$DEVICES_DIR"
  log "Device auto-pairing watcher started"
  while true; do
    sleep 8
    PENDING="$DEVICES_DIR/pending.json"
    PAIRED="$DEVICES_DIR/paired.json"
    if [ -f "$PENDING" ]; then
      node - << 'JSEOF'
const fs = require('fs');
const dir  = process.env.OPENCLAW_HOME + '/.openclaw/devices';
const pend = dir + '/pending.json';
const pair = dir + '/paired.json';
try {
  const raw = fs.readFileSync(pend, 'utf-8').trim();
  if (!raw || raw === '[]' || raw === '{}') process.exit(0);
  let pending = JSON.parse(raw);
  if (!Array.isArray(pending)) pending = Object.values(pending);
  if (pending.length === 0) process.exit(0);
  let paired = [];
  try { paired = JSON.parse(fs.readFileSync(pair, 'utf-8')); } catch(e) {}
  if (!Array.isArray(paired)) paired = [];
  const ids = new Set(paired.map(function(d){ return d.id||d.deviceId||d.name; }));
  const todo = pending.filter(function(d){ return !ids.has(d.id||d.deviceId||d.name); });
  if (todo.length === 0) process.exit(0);
  const now = new Date().toISOString();
  paired = paired.concat(todo.map(function(d){
    return Object.assign({}, d, { approved: true, approvedAt: now });
  }));
  fs.writeFileSync(pair, JSON.stringify(paired, null, 2));
  fs.writeFileSync(pend, '[]');
  console.log('[auto-pair] Approved ' + todo.length + ' device(s)');
} catch(e) { /* ignore */ }
JSEOF
    fi
  done
) &

# ----------------------------------------------------------------
# Gateway loop
#
# OpenClaw restart behaviour:
#   - On config save it spawns a child process (new gateway) then
#     the parent exits with code 0.
#   - The child inherits the port 7860 lock.
#   - We must NOT restart until the child also exits (port is free).
#
# Normal crash: port is immediately free, loop restarts quickly.
# Config-save restart: port stays held by child; we wait up to 90s.
# ----------------------------------------------------------------
log "Starting gateway loop..."

while true; do
  log "Gateway starting..."

  node /app/openclaw.mjs gateway \
    --allow-unconfigured \
    --bind lan \
    --port 7860
  CODE=$?

  log "Gateway exited (code $CODE)"

  # Wait for port 7860 to be released before starting a new instance
  WAITED=0
  while nc -z 127.0.0.1 7860 2>/dev/null; do
    if [ $WAITED -eq 0 ]; then
      log "Port 7860 still held (spawned child running) - waiting..."
    fi
    sleep 2
    WAITED=$((WAITED + 2))
    if [ $WAITED -ge 90 ]; then
      warn "Port 7860 still in use after 90s - forcing restart"
      break
    fi
  done

  if [ $WAITED -gt 0 ]; then
    log "Port free after ${WAITED}s"
  fi

  sleep 1
  log "Restarting gateway..."
done