import os import shlex import subprocess from typing import Tuple from flask import Flask, render_template_string, request app = Flask(__name__) ALLOWED_COMMANDS = { "status": ["openclaw", "status"], "onboard": ["openclaw", "onboard"], "gateway": ["openclaw", "gateway"], "tui": ["openclaw", "tui"], "dashboard": ["openclaw", "dashboard"], } HTML = """
openclaw commands inside this Hugging Face Docker Space.
{{ executed }}
{{ returncode }}
{{ output }}
{% endif %}
"""
def normalize_custom_command(text: str):
text = (text or "").strip()
if not text:
return None
try:
parts = shlex.split(text)
except ValueError:
return None
for allowed in ALLOWED_COMMANDS.values():
if parts == allowed:
return allowed
return None
def run_command(cmd: list[str]) -> Tuple[str, int]:
env = os.environ.copy()
env["PYTHONUNBUFFERED"] = "1"
try:
result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
timeout=120,
env=env,
cwd="/app",
)
return result.stdout, result.returncode
except FileNotFoundError:
return "Error: `openclaw` is not installed in the container.", 127
except subprocess.TimeoutExpired:
return "Error: command timed out after 120 seconds.", 124
except Exception as e:
return f"Unexpected error: {e}", 1
@app.route("/", methods=["GET", "POST"])
def index():
executed = ""
output = ""
returncode = ""
if request.method == "POST":
selected = request.form.get("command", "").strip()
custom = request.form.get("custom_command", "").strip()
cmd = None
if selected in ALLOWED_COMMANDS:
cmd = ALLOWED_COMMANDS[selected]
elif custom:
cmd = normalize_custom_command(custom)
if cmd is None:
executed = custom or selected or "(none)"
output = (
"Rejected command.\n\n"
"Allowed commands are:\n"
+ "\n".join(" ".join(v) for v in ALLOWED_COMMANDS.values())
)
returncode = 400
else:
executed = " ".join(cmd)
output, returncode = run_command(cmd)
return render_template_string(
HTML,
commands=ALLOWED_COMMANDS.keys(),
executed=executed,
output=output,
returncode=returncode,
)
if __name__ == "__main__":
port = int(os.environ.get("PORT", "7860"))
app.run(host="0.0.0.0", port=port, debug=False)