"""
LANDRUN + BROWSER-USE + CHROMIUM MERGED SYSTEM
==============================================
Kernel-level code execution sandbox with AI-powered browser automation
Features:
1. Landrun: Go-based Linux Landlock kernel security sandbox
2. Browser-Use: AI agent for intelligent browser automation
3. Chromium: Playwright browser for UI testing
4. FastAPI: Modern async web framework
Endpoints:
- POST /execute - Execute code in Landrun sandbox
- GET /preview/{id} - Get live HTML preview
- POST /browser/test - Test UI with Playwright
- POST /browser/agent - AI agent automated browsing
- POST /browser/execute_and_agent - One-shot: Execute + AI Agent
"""
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import List, Dict, Optional, Any
import subprocess
import tempfile
import os
import base64
import uuid
from datetime import datetime, timedelta
import asyncio
import json
# Playwright for direct browser control
from playwright.async_api import async_playwright
# Browser-Use for AI agent automation
try:
from browser_use import Agent
from langchain_openai import ChatOpenAI
BROWSER_USE_AVAILABLE = True
except ImportError:
BROWSER_USE_AVAILABLE = False
print("⚠️ Browser-Use not available - AI agent features disabled")
app = FastAPI(
title="Landrun + Browser-Use + Chromium",
description="Kernel-level sandbox with AI browser automation",
version="2.0.0"
)
# Enable CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Storage
PREVIEW_STORAGE = {}
PREVIEW_EXPIRY = timedelta(hours=1)
# ============================================================================
# PYDANTIC MODELS
# ============================================================================
class CodeExecutionRequest(BaseModel):
language: str = Field(..., description="Language: python, javascript, react, html")
code: str = Field(..., description="Source code to execute")
class BrowserAction(BaseModel):
type: str = Field(..., description="Action type: click, type, get_text, wait, screenshot")
selector: Optional[str] = Field(None, description="CSS selector for element")
text: Optional[str] = Field(None, description="Text to type (for type action)")
timeout: Optional[int] = Field(5000, description="Timeout in milliseconds")
class BrowserTestRequest(BaseModel):
preview_url: str = Field(..., description="Preview URL to test")
actions: List[BrowserAction] = Field(..., description="List of browser actions")
class BrowserAgentRequest(BaseModel):
task: str = Field(..., description="Natural language task for AI agent")
url: Optional[str] = Field(None, description="Starting URL (optional)")
max_steps: Optional[int] = Field(10, description="Maximum number of steps")
class ExecuteAndAgentRequest(BaseModel):
language: str = Field(..., description="Language: python, javascript, react, html")
code: str = Field(..., description="Source code to execute")
agent_task: str = Field(..., description="AI agent task to perform on preview")
max_steps: Optional[int] = Field(10, description="Maximum agent steps")
# ============================================================================
# LANDRUN CODE EXECUTION
# ============================================================================
def execute_with_landrun(language: str, code: str) -> dict:
"""Execute code using landrun kernel-level sandboxing"""
configs = {
"python": {
"ext": ".py",
"cmd": ["python3"],
"allowed_paths": ["/usr/lib/python3*", "/usr/local/lib/python3*"],
},
"javascript": {
"ext": ".js",
"cmd": ["node"],
"allowed_paths": ["/usr/lib/node_modules", "/usr/local/lib/node_modules"],
},
"html": {
"ext": ".html",
"cmd": None,
"allowed_paths": [],
},
"react": {
"ext": ".jsx",
"cmd": ["node"],
"allowed_paths": ["/usr/lib/node_modules", "/usr/local/lib/node_modules"],
}
}
config = configs.get(language.lower())
if not config:
return {"error": f"Unsupported language: {language}"}
try:
os.makedirs('/tmp/sandbox', exist_ok=True)
with tempfile.NamedTemporaryFile(mode='w', suffix=config['ext'], delete=False, dir='/tmp/sandbox') as f:
f.write(code)
temp_file = f.name
# HTML - return directly
if language.lower() == "html":
with open(temp_file, 'r') as f:
html_content = f.read()
os.unlink(temp_file)
return {
"output": "HTML rendered successfully",
"preview": base64.b64encode(html_content.encode()).decode(),
"exit_code": 0
}
# React - wrap and transpile
if language.lower() == "react":
react_wrapper = f"""
import React from 'react';
import {{ createRoot }} from 'react-dom/client';
{code}
const root = createRoot(document.getElementById('root'));
root.render();
"""
html_template = """
""".replace("{CODE}", code)
os.unlink(temp_file)
return {
"output": "React component compiled",
"preview": base64.b64encode(html_template.encode()).decode(),
"exit_code": 0
}
# Build landrun command
landrun_cmd = [
"/usr/local/bin/landrun",
"--ldd",
"--add-exec",
"--ro", "/usr",
"--ro", "/lib",
"--ro", "/lib64",
"--ro", "/etc",
"--rw", "/tmp/sandbox",
"--ro", temp_file,
"--connect-tcp", "80,443",
"--log-level", "error",
]
for path in config['allowed_paths']:
landrun_cmd.extend(["--ro", path])
landrun_cmd.append("--")
landrun_cmd.extend(config['cmd'])
landrun_cmd.append(temp_file)
result = subprocess.run(
landrun_cmd,
capture_output=True,
text=True,
timeout=10
)
os.unlink(temp_file)
return {
"output": result.stdout + result.stderr,
"exit_code": result.returncode,
"security": "Landrun kernel-level isolation active"
}
except subprocess.TimeoutExpired:
return {"error": "Execution timeout (10s)", "exit_code": -1}
except Exception as e:
return {"error": str(e), "exit_code": -1}
# ============================================================================
# PLAYWRIGHT BROWSER AUTOMATION
# ============================================================================
async def run_browser_test(preview_url: str, actions: List[BrowserAction]) -> dict:
"""Run Playwright browser test with actions"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
results = []
screenshot_initial = None
screenshot_final = None
try:
# Navigate to preview
await page.goto(preview_url, wait_until="networkidle", timeout=10000)
await page.wait_for_timeout(1000)
# Initial screenshot
screenshot_initial = base64.b64encode(await page.screenshot()).decode()
# Execute actions
for action in actions:
try:
if action.type == "click":
await page.click(action.selector, timeout=action.timeout)
results.append({"action": "click", "selector": action.selector, "status": "success"})
elif action.type == "type":
await page.fill(action.selector, action.text, timeout=action.timeout)
results.append({"action": "type", "selector": action.selector, "text": action.text, "status": "success"})
elif action.type == "get_text":
text = await page.text_content(action.selector, timeout=action.timeout)
results.append({"action": "get_text", "selector": action.selector, "text": text, "status": "success"})
elif action.type == "wait":
await page.wait_for_selector(action.selector, timeout=action.timeout)
results.append({"action": "wait", "selector": action.selector, "status": "success"})
elif action.type == "screenshot":
screenshot_final = base64.b64encode(await page.screenshot()).decode()
results.append({"action": "screenshot", "status": "success"})
await page.wait_for_timeout(500)
except Exception as e:
results.append({"action": action.type, "selector": action.selector, "status": "error", "error": str(e)})
# Final screenshot if not taken
if not screenshot_final:
screenshot_final = base64.b64encode(await page.screenshot()).decode()
finally:
await browser.close()
return {
"test_results": results,
"screenshot_initial": screenshot_initial,
"screenshot_final": screenshot_final
}
# ============================================================================
# BROWSER-USE AI AGENT
# ============================================================================
async def run_ai_agent(task: str, url: Optional[str] = None, max_steps: int = 10) -> dict:
"""Run Browser-Use AI agent with natural language task"""
if not BROWSER_USE_AVAILABLE:
return {
"status": "error",
"error": "Browser-Use not installed. Install with: pip install browser-use langchain-openai"
}
try:
# Check for OpenAI API key
if not os.getenv("OPENAI_API_KEY"):
return {
"status": "error",
"error": "OPENAI_API_KEY environment variable not set"
}
# Create AI agent
llm = ChatOpenAI(model="gpt-4o")
agent = Agent(
task=task,
llm=llm,
max_steps=max_steps
)
# Run agent
result = await agent.run()
return {
"status": "success",
"task": task,
"result": str(result),
"steps_taken": len(result.history()) if hasattr(result, 'history') else 0
}
except Exception as e:
return {
"status": "error",
"error": str(e)
}
# ============================================================================
# API ENDPOINTS
# ============================================================================
@app.post("/execute")
async def execute_code(request: CodeExecutionRequest):
"""Execute code in Landrun sandbox"""
result = execute_with_landrun(request.language, request.code)
# Store preview if available
if "preview" in result and not "error" in result:
preview_id = str(uuid.uuid4())
preview_html = base64.b64decode(result["preview"]).decode()
PREVIEW_STORAGE[preview_id] = {
"html": preview_html,
"created": datetime.now()
}
result["preview_url"] = f"/preview/{preview_id}"
del result["preview"]
return result
@app.get("/preview/{preview_id}")
async def get_preview(preview_id: str):
"""Get live HTML preview"""
if preview_id not in PREVIEW_STORAGE:
raise HTTPException(status_code=404, detail="Preview not found or expired")
# Check expiry
preview_data = PREVIEW_STORAGE[preview_id]
if datetime.now() - preview_data["created"] > PREVIEW_EXPIRY:
del PREVIEW_STORAGE[preview_id]
raise HTTPException(status_code=410, detail="Preview expired")
return HTMLResponse(content=preview_data["html"])
@app.post("/browser/test")
async def browser_test(request: BrowserTestRequest):
"""Test UI with Playwright browser automation"""
# Build full URL if relative
if request.preview_url.startswith("/preview/"):
base_url = os.getenv("SPACE_HOST", "http://localhost:7860")
full_url = f"{base_url}{request.preview_url}"
else:
full_url = request.preview_url
result = await run_browser_test(full_url, request.actions)
return {
"status": "success",
"url_tested": full_url,
**result
}
@app.post("/browser/agent")
async def browser_agent(request: BrowserAgentRequest):
"""Run AI agent for automated browsing"""
result = await run_ai_agent(
task=request.task,
url=request.url,
max_steps=request.max_steps
)
return result
@app.post("/browser/execute_and_test")
async def execute_and_test(request: CodeExecutionRequest):
"""Execute code and test with Playwright (existing endpoint for compatibility)"""
# Execute code
exec_result = execute_with_landrun(request.language, request.code)
if "error" in exec_result:
return {
"status": "error",
"execution": exec_result
}
# Store preview
if "preview" in exec_result:
preview_id = str(uuid.uuid4())
preview_html = base64.b64decode(exec_result["preview"]).decode()
PREVIEW_STORAGE[preview_id] = {
"html": preview_html,
"created": datetime.now()
}
preview_url = f"/preview/{preview_id}"
exec_result["preview_url"] = preview_url
del exec_result["preview"]
else:
return {
"status": "error",
"error": "No preview generated"
}
return {
"status": "success",
"execution": exec_result
}
@app.post("/browser/execute_and_agent")
async def execute_and_agent(request: ExecuteAndAgentRequest):
"""ONE-SHOT: Execute code + Run AI agent on preview"""
# Execute code
exec_result = execute_with_landrun(request.language, request.code)
if "error" in exec_result:
return {
"status": "error",
"execution": exec_result
}
# Store preview
if "preview" in exec_result:
preview_id = str(uuid.uuid4())
preview_html = base64.b64decode(exec_result["preview"]).decode()
PREVIEW_STORAGE[preview_id] = {
"html": preview_html,
"created": datetime.now()
}
preview_url = f"/preview/{preview_id}"
base_url = os.getenv("SPACE_HOST", "http://localhost:7860")
full_preview_url = f"{base_url}{preview_url}"
# Run AI agent on the preview
agent_result = await run_ai_agent(
task=f"{request.agent_task}. Start at URL: {full_preview_url}",
url=full_preview_url,
max_steps=request.max_steps
)
return {
"status": "success",
"execution": {
**exec_result,
"preview_url": preview_url
},
"agent": agent_result
}
else:
return {
"status": "error",
"error": "No preview generated for AI agent"
}
@app.get("/health")
async def health_check():
"""Health check endpoint"""
return {
"status": "healthy",
"landrun": "active",
"browser": "playwright-chromium",
"browser_use": "available" if BROWSER_USE_AVAILABLE else "not installed",
"ai_agent": "enabled" if (BROWSER_USE_AVAILABLE and os.getenv("OPENAI_API_KEY")) else "disabled"
}
@app.get("/")
async def root():
"""Root endpoint with API documentation"""
return {
"service": "Landrun + Browser-Use + Chromium",
"version": "2.0.0",
"features": {
"landrun": "Kernel-level code execution sandbox",
"playwright": "Direct browser automation",
"browser_use": "AI agent for intelligent browsing",
"chromium": "Headless browser engine"
},
"endpoints": {
"POST /execute": "Execute code in sandbox",
"GET /preview/{id}": "Get live HTML preview",
"POST /browser/test": "Test UI with Playwright",
"POST /browser/agent": "Run AI agent task",
"POST /browser/execute_and_test": "Execute + Playwright test",
"POST /browser/execute_and_agent": "Execute + AI agent (ONE-SHOT)"
}
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)