Spaces:
Sleeping
Sleeping
| set -e | |
| # Entrypoint for HuggingClaw - Cain | |
| # Ensure frontend directory exists (defensive: created at build time, but verify at runtime) | |
| mkdir -p /app/frontend | |
| mkdir -p /data/frontend | |
| # Ensure /data is writable and exists | |
| mkdir -p /data | |
| chmod 777 /data 2>/dev/null || true | |
| echo "==========================================" | |
| echo "Cain Starting..." | |
| echo "==========================================" | |
| echo "Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")" | |
| echo "PORT: ${PORT:-7860}" | |
| echo "Working Directory: $(pwd)" | |
| echo "Python Version: $(python --version)" | |
| echo "Data directory: $(ls -la /data 2>&1 | head -5)" | |
| echo "==========================================" | |
| # Change to app directory | |
| cd /app | |
| # Set data directory to dataset mount point | |
| export OPENCLAW_DATA_DIR=/data | |
| # Verify app.py exists | |
| if [ ! -f "/app/app.py" ]; then | |
| echo "ERROR: app.py not found in /app" | |
| exit 1 | |
| fi | |
| echo "✓ app.py found" | |
| # List key files for debugging | |
| echo "" | |
| echo "Files in /app:" | |
| ls -la /app/*.py 2>/dev/null || echo " (no .py files in /app root)" | |
| # Create logs directory | |
| mkdir -p /app/logs | |
| # Ensure cain_status.json directory exists | |
| mkdir -p /data | |
| # CRITICAL: Clear stale error field from cain_status.json before startup | |
| # This prevents "unknown" errors from persisting across container restarts | |
| # Clean ALL possible status file locations to ensure consistency | |
| echo "Cleaning stale error field from status files..." | |
| python3 -c " | |
| import json | |
| from pathlib import Path | |
| status_files = [ | |
| Path('/data/cain_status.json'), # Primary (OPENCLAW_DATA_DIR) | |
| Path('/app/openclaw/.openclaw/agents/cain_status.json'), # Nested structure | |
| Path('/app/.openclaw/agents/cain_status.json'), # Legacy flat structure | |
| Path('/app/cain_status.json'), # App root | |
| Path('/app/data/cain_status.json'), # App data subdirectory | |
| Path('/app/memory/cain_status.json'), # Memory directory (CRITICAL: was missing!) | |
| Path('/data/memory/cain_status.json'), # Data memory directory | |
| ] | |
| cleaned = 0 | |
| for status_file in status_files: | |
| try: | |
| if status_file.exists(): | |
| with open(status_file, 'r') as f: | |
| data = json.load(f) | |
| error = data.get('error') | |
| # Fix: if error is string 'unknown' or contains 'unknown', set to null | |
| if isinstance(error, str) and error.strip().lower() in ('unknown', 'none', 'null', ''): | |
| data['error'] = None | |
| data['_cleaned_at'] = 'entrypoint' | |
| with open(status_file, 'w') as f: | |
| json.dump(data, f, indent=2) | |
| cleaned += 1 | |
| print(f' Cleaned: {status_file}') | |
| elif error is None: | |
| print(f' OK: {status_file} (error already null)') | |
| except Exception as e: | |
| print(f' Could not clean {status_file}: {e}') | |
| print(f'Cleaned {cleaned} status file(s)') | |
| " 2>/dev/null || echo "(Could not clean status files - continuing)" | |
| echo "" | |
| echo "" | |
| echo "==========================================" | |
| echo "Starting uvicorn..." | |
| echo "==========================================" | |
| # Run uvicorn directly in foreground (no forking, no piping) | |
| exec uvicorn app:app --host 0.0.0.0 --port "${PORT:-7860}" | |