File size: 6,144 Bytes
b1e7fce
 
 
 
 
 
 
 
31506fb
b1e7fce
 
 
730e275
b1e7fce
 
730e275
 
b1e7fce
 
 
730e275
b1e7fce
5c85665
b1e7fce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730e275
c816944
730e275
c816944
730e275
c816944
730e275
 
 
b1e7fce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31506fb
c816944
b1e7fce
 
c816944
b1e7fce
c816944
b1e7fce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c816944
b1e7fce
 
 
 
 
 
c816944
b1e7fce
 
 
 
 
 
 
 
c816944
b1e7fce
 
 
 
 
 
 
730e275
 
b1e7fce
 
 
 
 
 
730e275
8ed40a8
 
 
 
b1e7fce
 
 
c816944
b1e7fce
 
 
 
 
 
c816944
b1e7fce
 
c816944
b1e7fce
 
c816944
 
b1e7fce
 
730e275
b1e7fce
 
730e275
b1e7fce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31506fb
c816944
b1e7fce
 
 
 
730e275
b1e7fce
 
c816944
b1e7fce
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
import asyncio
import os
import sys
from threading import Thread
import json
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Import browser-use components and LLM libraries
try:
    from langchain_openai import ChatOpenAI
    from langchain_anthropic import ChatAnthropic
    from langchain_google_genai import ChatGoogleGenerativeAI
    from browser_use import Agent
except ImportError as e:
    print(f"Import error: {e}")
    print("Make sure to install browser-use, langchain-openai, langchain-anthropic, and langchain-google-genai")

app = Flask(__name__, static_folder="static")
CORS(app)  # Enable CORS for all routes

# Global variables for managing async operations
loop = None
thread = None

def start_background_loop(loop):
    """Start the asyncio event loop in a background thread"""
    asyncio.set_event_loop(loop)
    loop.run_forever()

def get_or_create_eventloop():
    """Get or create the asyncio event loop"""
    global loop, thread
    if loop is None:
        loop = asyncio.new_event_loop()
        thread = Thread(target=start_background_loop, args=(loop,))
        thread.daemon = True
        thread.start()
    return loop

async def run_browser_task(task, model="gpt-4o-mini"):
    """Run a browser automation task using browser-use"""
    try:
        # Initialize the LLM based on the model name
        if model.startswith("gpt"):
            llm = ChatOpenAI(model=model, temperature=0.1)
        elif model.startswith("claude"):
            llm = ChatAnthropic(model=model, temperature=0.1)
        elif model.startswith("gemini"):
            llm = ChatGoogleGenerativeAI(model=model, temperature=0.1)
        else:
            raise ValueError(f"Unsupported model: {model}")
        
        # Create the agent
        agent = Agent(task=task, llm=llm)
        
        # Run the task
        result = await agent.run()
        
        return {
            "success": True,
            "result": str(result),
            "task": task
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "task": task
        }

@app.route("/")
def home():
    """Serve the HTML interface"""
    return send_from_directory("static", "index.html")

@app.route("/api")
def api_docs():
    """API documentation endpoint"""
    return jsonify({
        "message": "Browser-Use Server API",
        "endpoints": {
            "/": "Web interface",
            "/api": "This API documentation",
            "/health": "Health check",
            "/run-task": "POST - Run a browser automation task",
            "/status": "Get server status"
        },
        "usage": {
            "run_task": {
                "method": "POST",
                "url": "/run-task",
                "body": {
                    "task": "Description of the task to perform",
                    "model": "gpt-4o-mini (optional, default)"
                },
                "example": {
                    "task": "Go to google.com and search for 'Python programming'",
                    "model": "gpt-4o-mini"
                }
            }
        }
    })

@app.route("/health")
def health():
    """Health check endpoint"""
    return jsonify({
        "status": "healthy",
        "service": "browser-use-server",
        "version": "1.0.0"
    })

@app.route("/status")
def status():
    """Get server status and configuration"""
    return jsonify({
        "status": "running",
        "environment": {
            "python_version": sys.version,
            "has_openai_key": bool(os.getenv("OPENAI_API_KEY")),
            "has_anthropic_key": bool(os.getenv("ANTHROPIC_API_KEY")),
            "has_google_api_key": bool(os.getenv("GOOGLE_API_KEY"))
        },
        "supported_models": [
            "gpt-4o",
            "gpt-4o-mini", 
            "gpt-4-turbo",
            "claude-3-sonnet-20240229",
            "claude-3-haiku-20240307",
            "gemini-2.0-flash",
            "gemini-2.5-flash",
            "gemini-2.0-flash-exp",
            "gemini-2.0-flash-lite"
        ]
    })

@app.route("/run-task", methods=["POST"])
def run_task():
    """Run a browser automation task"""
    try:
        # Get request data
        data = request.get_json()
        
        if not data or "task" not in data:
            return jsonify({
                "success": False,
                "error": "Missing 'task' in request body"
            }), 400
        
        task = data["task"]
        model = data.get("model", "gpt-4o-mini")
        
        # Validate API keys
        if not os.getenv("OPENAI_API_KEY") and not os.getenv("ANTHROPIC_API_KEY") and not os.getenv("GOOGLE_API_KEY"):
            return jsonify({
                "success": False,
                "error": "No API keys configured. Please set OPENAI_API_KEY, ANTHROPIC_API_KEY, or GOOGLE_API_KEY environment variable."
            }), 500
        
        # Get the event loop
        loop = get_or_create_eventloop()
        
        # Run the task asynchronously
        future = asyncio.run_coroutine_threadsafe(
            run_browser_task(task, model), 
            loop
        )
        
        # Wait for the result (with timeout)
        try:
            result = future.result(timeout=300)  # 5 minute timeout
            return jsonify(result)
        except asyncio.TimeoutError:
            return jsonify({
                "success": False,
                "error": "Task timed out after 5 minutes"
            }), 408
            
    except Exception as e:
        return jsonify({
            "success": False,
            "error": f"Server error: {str(e)}"
        }), 500

if __name__ == "__main__":
    print("Starting Browser-Use Server...")
    print("Make sure you have set your API keys:")
    print("- OPENAI_API_KEY for OpenAI models")
    print("- ANTHROPIC_API_KEY for Anthropic models")
    print("- GOOGLE_API_KEY for Google Gemini models")
    
    # Run the Flask app
    app.run(host="0.0.0.0", port=7860, debug=False)