Spaces:
Running
Running
| # Ensure HF CLI is in PATH | |
| export PATH="$HOME/.local/bin:$PATH" | |
| # Set HF Token from Space Secrets | |
| export HF_TOKEN="${HF_TOKEN}" | |
| # Variables | |
| BUCKET='hf://buckets/jerecom/Opencod-storage' | |
| SOURCE='/home' | |
| # Configure Git | |
| git config --global user.email 'badal@example.com' | |
| git config --global user.name 'Badal' | |
| # Set OpenCode path | |
| OP_PATH=$(find / -name opencode -type f -printf '%h' -quit 2>/dev/null) | |
| export PATH="$OP_PATH:$PATH" | |
| # ============================================ | |
| # STEP 0: BUCKET CLEANUP (Delete .cache & .npm from bucket) | |
| # ============================================ | |
| echo '=== [STEP 0] CLEANING BUCKET (Removing .cache and .npm) ===' | |
| hf buckets rm "$BUCKET/.cache" --recursive -y 2>/dev/null && echo '=== [STEP 0] .cache removed from bucket ===' || echo '=== [STEP 0] .cache not found in bucket (skipping) ===' | |
| hf buckets rm "$BUCKET/.npm" --recursive -y 2>/dev/null && echo '=== [STEP 0] .npm removed from bucket ===' || echo '=== [STEP 0] .npm not found in bucket (skipping) ===' | |
| echo '=== [STEP 0] BUCKET CLEANUP DONE ===' | |
| # ============================================ | |
| # STEP 1: RESTORE (Try, but continue if bucket empty) | |
| # ============================================ | |
| echo '=== [STEP 1] RESTORING DATA FROM BUCKET ===' | |
| if hf sync "$BUCKET" "$SOURCE" --delete 2>/dev/null; then | |
| echo '=== [STEP 1] RESTORE COMPLETE ===' | |
| else | |
| echo '=== [STEP 1] Restore skipped (bucket empty or failed - continuing anyway) ===' | |
| fi | |
| # Auto-create /home/user if not exists | |
| if [ ! -d "/home/user" ]; then | |
| echo '=== Creating /home/user folder ===' | |
| mkdir -p /home/user | |
| fi | |
| # ============================================ | |
| # STEP 2: START OPENCODE (with RAM watchdog) | |
| # ============================================ | |
| # RAM limit: 14GB in KB | |
| RAM_LIMIT_KB=$((14 * 1024 * 1024)) | |
| start_opencode() { | |
| echo '=== [STEP 2] STARTING OPENCODE ===' | |
| export OPENCODE_SERVER_USERNAME=${OPENCODE_SERVER_USERNAME} | |
| export OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD} | |
| opencode web --port 7860 --hostname 0.0.0.0 > /tmp/opencode.log 2>&1 & | |
| OPENCODE_PID=$! | |
| echo "=== [STEP 2] OPENCODE STARTED (PID: $OPENCODE_PID) ===" | |
| } | |
| ram_watchdog() { | |
| while true; do | |
| if [ -n "$OPENCODE_PID" ] && kill -0 "$OPENCODE_PID" 2>/dev/null; then | |
| # OpenCode + uske saare child processes ki total RAM (KB) | |
| USED_KB=$(ps --no-headers -o rss --ppid "$OPENCODE_PID" 2>/dev/null | awk '{sum+=$1} END {print sum+0}') | |
| SELF_KB=$(ps --no-headers -o rss -p "$OPENCODE_PID" 2>/dev/null | awk '{print $1+0}') | |
| TOTAL_KB=$((USED_KB + SELF_KB)) | |
| #echo "=== [RAM] OpenCode using: $((TOTAL_KB / 1024))MB / 14336MB ===" | |
| if [ "$TOTAL_KB" -ge "$RAM_LIMIT_KB" ]; then | |
| echo "=== [RAM] LIMIT EXCEEDED! Killing OpenCode (${TOTAL_KB}KB >= ${RAM_LIMIT_KB}KB) ===" | |
| kill -9 "$OPENCODE_PID" 2>/dev/null | |
| sleep 3 | |
| echo '=== [RAM] Restarting OpenCode... ===' | |
| start_opencode | |
| fi | |
| else | |
| # OpenCode kisi aur wajah se mar gaya — restart | |
| echo '=== [RAM] OpenCode not running! Restarting... ===' | |
| start_opencode | |
| fi | |
| done | |
| } | |
| start_opencode | |
| sleep 10 | |
| # RAM watchdog background mein chalao | |
| ram_watchdog & | |
| # ============================================ | |
| # STEP 3: INOTIFY TRIGGER + 30s DEBOUNCE SYNC | |
| # ============================================ | |
| echo '=== [STEP 3] STARTING SMART SYNC (inotify + 30s debounce) ===' | |
| do_sync() { | |
| echo "=== [STEP 3] Syncing to bucket... ===" | |
| hf sync "$SOURCE" "$BUCKET" --delete \ | |
| --exclude "*.mdb" \ | |
| --exclude "*.log" \ | |
| --exclude ".cache" \ | |
| --exclude ".npm" \ | |
| --exclude ".check_for_update_done" \ | |
| --exclude "rg" | |
| echo "=== [STEP 3] Sync done! ===" | |
| } | |
| LAST_SYNC=0 | |
| while true; do | |
| # Check if OpenCode is still running | |
| if ! pgrep -f 'opencode' > /dev/null; then | |
| echo 'CRITICAL: OpenCode process died! Exiting container...' | |
| exit 1 | |
| fi | |
| # Wait for ANY change — modify, create, delete, move, rename, attrib | |
| inotifywait -r -e modify,create,delete,move,attrib \ | |
| --exclude '.*\.mdb$' \ | |
| --exclude '.*\.log$' \ | |
| --exclude '.*\.check_for_update_done$' \ | |
| --exclude '.*/rg$' \ | |
| -q "$SOURCE" | |
| # Debounce: agar last sync 30s pehle hua ho tabhi sync karo | |
| NOW=$(date +%s) | |
| DIFF=$((NOW - LAST_SYNC)) | |
| if [ "$DIFF" -ge 30 ]; then | |
| do_sync | |
| LAST_SYNC=$(date +%s) | |
| else | |
| echo "=== [STEP 3] Change detected but debounce active (${DIFF}s < 30s), waiting... ===" | |
| fi | |
| done | |