|
|
|
|
|
import os |
|
|
import subprocess |
|
|
import threading |
|
|
import time |
|
|
from flask import Flask, jsonify, redirect |
|
|
import signal |
|
|
import sys |
|
|
|
|
|
app = Flask(__name__) |
|
|
|
|
|
|
|
|
code_server_process = None |
|
|
|
|
|
def check_code_server(): |
|
|
"""Check if code-server is installed""" |
|
|
try: |
|
|
result = subprocess.run( |
|
|
["code-server", "--version"], |
|
|
check=True, |
|
|
capture_output=True, |
|
|
text=True |
|
|
) |
|
|
print(f"Code-server version: {result.stdout.strip()}") |
|
|
return True |
|
|
except (subprocess.CalledProcessError, FileNotFoundError) as e: |
|
|
print(f"Code-server not found: {e}") |
|
|
return False |
|
|
|
|
|
def start_code_server(): |
|
|
"""Start code-server in background""" |
|
|
global code_server_process |
|
|
try: |
|
|
|
|
|
config_dir = os.path.expanduser("~/.config/code-server") |
|
|
os.makedirs(config_dir, exist_ok=True) |
|
|
|
|
|
|
|
|
password = os.getenv("CODE_SERVER_PASSWORD", "huggingface123") |
|
|
|
|
|
|
|
|
cmd = [ |
|
|
"code-server", |
|
|
"--bind-addr", "0.0.0.0:8080", |
|
|
"--auth", "password", |
|
|
"--password", password, |
|
|
"--disable-telemetry", |
|
|
"--disable-update-check" |
|
|
] |
|
|
|
|
|
print("Starting code-server...") |
|
|
code_server_process = subprocess.Popen( |
|
|
cmd, |
|
|
stdout=subprocess.PIPE, |
|
|
stderr=subprocess.PIPE, |
|
|
text=True |
|
|
) |
|
|
|
|
|
|
|
|
time.sleep(5) |
|
|
|
|
|
if code_server_process.poll() is None: |
|
|
print("Code-server started successfully!") |
|
|
print(f"Password: {password}") |
|
|
return True |
|
|
else: |
|
|
print("Code-server failed to start") |
|
|
return False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Error starting code-server: {e}") |
|
|
return False |
|
|
|
|
|
def setup_workspace(): |
|
|
"""Setup initial workspace""" |
|
|
try: |
|
|
|
|
|
workspace_dir = "/tmp/workspace" |
|
|
os.makedirs(workspace_dir, exist_ok=True) |
|
|
|
|
|
|
|
|
sample_file = os.path.join(workspace_dir, "README.md") |
|
|
with open(sample_file, "w") as f: |
|
|
f.write("""# Code-Server on Hugging Face Spaces |
|
|
|
|
|
Welcome to your code-server environment! |
|
|
|
|
|
## Features: |
|
|
- Full VS Code experience in browser |
|
|
- Python environment ready |
|
|
- Terminal access |
|
|
- File editing capabilities |
|
|
|
|
|
## Getting Started: |
|
|
1. Open terminal (Ctrl+Shift+`) |
|
|
2. Install packages: `pip install package-name` |
|
|
3. Start coding! |
|
|
|
|
|
## Note: |
|
|
- Files are temporary and will be lost on restart |
|
|
- For persistent storage, use external git repos |
|
|
""") |
|
|
|
|
|
|
|
|
sample_py = os.path.join(workspace_dir, "sample.py") |
|
|
with open(sample_py, "w") as f: |
|
|
f.write("""#!/usr/bin/env python3 |
|
|
# Sample Python file |
|
|
|
|
|
def hello_world(): |
|
|
print("Hello from Code-Server on Hugging Face!") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
hello_world() |
|
|
""") |
|
|
|
|
|
print("Workspace setup complete!") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Error setting up workspace: {e}") |
|
|
return False |
|
|
|
|
|
@app.route('/health') |
|
|
def health_check(): |
|
|
"""Health check endpoint""" |
|
|
global code_server_process |
|
|
|
|
|
status = { |
|
|
"status": "healthy", |
|
|
"timestamp": time.time(), |
|
|
"code_server_running": False |
|
|
} |
|
|
|
|
|
if code_server_process: |
|
|
if code_server_process.poll() is None: |
|
|
status["code_server_running"] = True |
|
|
else: |
|
|
status["code_server_running"] = False |
|
|
status["status"] = "code_server_down" |
|
|
|
|
|
return jsonify(status) |
|
|
|
|
|
@app.route('/') |
|
|
def index(): |
|
|
"""Redirect to code-server""" |
|
|
return redirect('/code-server/', code=302) |
|
|
|
|
|
@app.route('/code-server/') |
|
|
def code_server_proxy(): |
|
|
"""Info about code-server access""" |
|
|
return """ |
|
|
<html> |
|
|
<head><title>Code-Server Access</title></head> |
|
|
<body> |
|
|
<h1>Code-Server on Hugging Face Spaces</h1> |
|
|
<p>Code-server should be running on port 8080</p> |
|
|
<p>If you're seeing this, the proxy might not be working correctly.</p> |
|
|
<p>Try accessing directly through the Hugging Face Spaces interface.</p> |
|
|
<p><a href="/health">Check Health Status</a></p> |
|
|
</body> |
|
|
</html> |
|
|
""" |
|
|
|
|
|
def signal_handler(sig, frame): |
|
|
"""Handle shutdown gracefully""" |
|
|
global code_server_process |
|
|
print("Shutting down...") |
|
|
|
|
|
if code_server_process: |
|
|
code_server_process.terminate() |
|
|
code_server_process.wait() |
|
|
|
|
|
sys.exit(0) |
|
|
|
|
|
def initialize_environment(): |
|
|
"""Initialize the complete environment""" |
|
|
print("Initializing environment...") |
|
|
|
|
|
|
|
|
if not check_code_server(): |
|
|
print("Code-server is not installed!") |
|
|
return False |
|
|
|
|
|
|
|
|
if not setup_workspace(): |
|
|
print("Failed to setup workspace") |
|
|
return False |
|
|
|
|
|
|
|
|
def start_server(): |
|
|
start_code_server() |
|
|
|
|
|
server_thread = threading.Thread(target=start_server, daemon=True) |
|
|
server_thread.start() |
|
|
|
|
|
return True |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
signal.signal(signal.SIGINT, signal_handler) |
|
|
signal.signal(signal.SIGTERM, signal_handler) |
|
|
|
|
|
|
|
|
if initialize_environment(): |
|
|
print("Environment initialized successfully!") |
|
|
|
|
|
|
|
|
port = int(os.getenv("PORT", 7860)) |
|
|
app.run(host="0.0.0.0", port=port, debug=False) |
|
|
else: |
|
|
print("Failed to initialize environment") |
|
|
sys.exit(1) |