Spaces:
Running
Running
| 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 | |
| } | |
| def home(): | |
| """Serve the HTML interface""" | |
| return send_from_directory("static", "index.html") | |
| 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" | |
| } | |
| } | |
| } | |
| }) | |
| def health(): | |
| """Health check endpoint""" | |
| return jsonify({ | |
| "status": "healthy", | |
| "service": "browser-use-server", | |
| "version": "1.0.0" | |
| }) | |
| 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" | |
| ] | |
| }) | |
| 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) | |