diff --git a/Dockerfile b/Dockerfile
index 34fa1a153fd4c16409519e142328d15cf713b91e..d120acc153ee2c4270f4d0ce13a77a2ee3b90e94 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
# ============================================================
-# LANDRUN SANDBOX - Kernel-level Linux Security
-# Multi-stage build: Build landrun + Run FastAPI app
+# LANDRUN + BROWSER-USE + CHROMIUM - MERGED SYSTEM
+# Multi-stage build: Build landrun + Python + Browser-Use + Chromium
# ============================================================
# Stage 1: Build landrun binary from Go source
@@ -8,20 +8,20 @@ FROM golang:1.22-bookworm AS builder
WORKDIR /build
-# Copy landrun source with proper structure
+# Copy landrun source (from D:\sand\landrun-main\landrun-main)
COPY landrun-main/ ./
# Build landrun with full module context
RUN go mod download && \
go build -ldflags="-s -w" -o landrun ./cmd/landrun
-# Stage 2: Production image with Python + landrun + Browser
+# Stage 2: Production image with Python + landrun + Browser-Use + Chromium
FROM python:3.11-slim-bookworm
# Install system dependencies + compilers + browser deps
RUN apt-get update && apt-get install -y \
# Core utilities
- nodejs npm curl procps strace \
+ nodejs npm curl procps strace git \
# Compilers
gcc g++ make cmake \
# Browser dependencies (Playwright Chromium)
@@ -41,17 +41,24 @@ RUN landrun --version
# Set working directory
WORKDIR /app
+# Copy Browser-Use source (from D:\sand\landrun-main\browser-use-main)
+COPY browser-use-main/browser_use ./browser_use
+COPY browser-use-main/pyproject.toml ./
+
# Copy Python requirements
COPY requirements.txt .
-# Install Python dependencies
+# Install Python dependencies (Browser-Use + Playwright + FastAPI)
RUN pip install --no-cache-dir -r requirements.txt
+# Install Browser-Use in editable mode
+RUN pip install -e .
+
# Install Playwright and Chromium browser
RUN playwright install chromium --with-deps
# Copy application code
-COPY app.py .
+COPY app_enhanced.py ./app.py
# Create execution directory
RUN mkdir -p /tmp/sandbox && chmod 777 /tmp/sandbox
@@ -64,6 +71,7 @@ ENV PYTHONUNBUFFERED=1
ENV HOST=0.0.0.0
ENV PORT=7860
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
+ENV BROWSER_USE_SETUP_LOGGING=false
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
diff --git a/app.py b/app.py
index 7f2df16801a4becca1d25d32a5d9100838f3cdf3..ebf5a11f8165541e567a9bb5745074934dd03a6f 100644
--- a/app.py
+++ b/app.py
@@ -1,23 +1,53 @@
"""
-FastAPI Universal Code Execution Sandbox with LANDRUN Security + Browser Automation
-Kernel-level sandboxing using Linux Landlock for maximum isolation
-Browser automation with Playwright for UI testing
+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
+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 shlex
import uuid
from datetime import datetime, timedelta
import asyncio
+import json
+
+# Playwright for direct browser control
from playwright.async_api import async_playwright
-app = FastAPI()
+# 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(
@@ -28,14 +58,46 @@ app.add_middleware(
allow_headers=["*"],
)
-# Store preview pages in memory (with expiration)
+# 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"""
- # Language configurations
configs = {
"python": {
"ext": ".py",
@@ -49,7 +111,7 @@ def execute_with_landrun(language: str, code: str) -> dict:
},
"html": {
"ext": ".html",
- "cmd": None, # Static file
+ "cmd": None,
"allowed_paths": [],
},
"react": {
@@ -63,659 +125,401 @@ def execute_with_landrun(language: str, code: str) -> dict:
if not config:
return {"error": f"Unsupported language: {language}"}
- # Create temporary file
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
- # For HTML/static files, return directly
+ # 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()
+ "preview": base64.b64encode(html_content.encode()).decode(),
+ "exit_code": 0
}
- # Build landrun command with security restrictions
- landrun_cmd = [
- "/usr/local/bin/landrun",
- "--ldd", # Auto-detect library dependencies
- "--add-exec", # Auto-add executable
- "--ro", "/usr", # Read-only access to system files
- "--ro", "/lib", # Read-only access to libraries
- "--ro", "/lib64", # Read-only 64-bit libraries
- "--ro", "/etc", # Read-only config (for DNS, etc.)
- "--rw", "/tmp/sandbox", # Write access to sandbox only
- "--ro", temp_file, # Read-only access to code file
- "--connect-tcp", "80,443", # Allow HTTP/HTTPS
- "--log-level", "error",
- ]
-
- # Add language-specific paths
- for path in config['allowed_paths']:
- landrun_cmd.extend(["--ro", path])
-
- # Add execution command
- landrun_cmd.extend(config['cmd'] + [temp_file])
-
- # Execute with timeout
- result = subprocess.run(
- landrun_cmd,
- capture_output=True,
- text=True,
- timeout=10,
- cwd="/tmp/sandbox"
- )
-
- # Clean up
- os.unlink(temp_file)
-
- # Prepare output
- output = result.stdout
- if result.stderr:
- output += f"\n--- STDERR ---\n{result.stderr}"
-
- # Generate preview HTML and store with unique ID
- preview_id = str(uuid.uuid4())
- preview_url = None
- preview_html = None
-
- # React: Always create preview with JSX
+ # React - wrap and transpile
if language.lower() == "react":
- preview_html = f"""
+ react_wrapper = f"""
+import React from 'react';
+import {{ createRoot }} from 'react-dom/client';
+
+{code}
+
+const root = createRoot(document.getElementById('root'));
+root.render(