From 0fab25c80f53b31b03ab4a3d427fc17ea87f56d1 Mon Sep 17 00:00:00 2001 From: nafer Date: Thu, 5 Mar 2026 22:43:55 +0300 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B2=D0=B5=D0=B1-=D0=B8=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=20=D0=B8=20dashboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлен веб-интерфейс для Browser Use API с главной страницей и dashboard. Реализованы: HTML-шаблоны для UI, новый эндпоинт GET /api/tasks для списка задач, поддержка remote debugging для браузера через Chromium args. Обновлена конфигурация docker-compose с новыми переменными окружения. --- __pycache__/app.cpython-312.pyc | Bin 0 -> 13776 bytes app.py | 210 +++++++++++++++++++++++++++++++- docker-compose.yml | 4 + 3 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 __pycache__/app.cpython-312.pyc diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e1b3cedea7027d3a47d415c1a167eca3887eefc GIT binary patch literal 13776 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 literal 0 HcmV?d00001 diff --git a/app.py b/app.py index fd1fe70..5f41084 100644 --- a/app.py +++ b/app.py @@ -9,10 +9,13 @@ from fastapi import FastAPI, HTTPException from pydantic import BaseModel from browser_use import Agent, Browser, ChatOpenAI from browser_use.agent.views import AgentHistoryList +from browser_use.browser.context import BrowserContextConfig, BrowserConfig import uvicorn +from fastapi.responses import HTMLResponse -# Обход проверки API ключа browser-use -os.environ["OPENAI_API_KEY"] = os.environ.get("OPENAI_API_KEY", "dummy") +# Настройки Remote Debugging +REMOTE_DEBUGGING_PORT = int(os.getenv("REMOTE_DEBUGGING_PORT", "9222")) +REMOTE_DEBUGGING_ENABLED = os.getenv("REMOTE_DEBUGGING_ENABLED", "false").lower() == "true" app = FastAPI(title="Browser Use API", version="1.0.0") @@ -20,7 +23,7 @@ app = FastAPI(title="Browser Use API", version="1.0.0") class TaskRequest(BaseModel): task: str max_steps: Optional[int] = 20 - model: Optional[str] = "openai/gpt-4o-mini" + model: Optional[str] = DEFAULT_MODEL class TaskResponse(BaseModel): task_id: str @@ -69,12 +72,22 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str): api_key=api_key ) - # Инициализация браузера с постоянной директорией для cookies - browser = Browser( + # Настройки браузера + browser_config = BrowserConfig( user_data_dir="/app/browser-data", - profile_directory="Default" + profile_directory="Default", + headless=True, ) + # Добавляем remote debugging если включено + if REMOTE_DEBUGGING_ENABLED: + browser_config.extra_chromium_args = [ + f"--remote-debugging-port={REMOTE_DEBUGGING_PORT}", + "--remote-debugging-address=0.0.0.0" + ] + + browser = Browser(config=browser_config) + # Создание агента agent = Agent( task=task, @@ -117,6 +130,22 @@ async def get_task(task_id: str): error=task.get("error") ) +@app.get("/api/tasks") +async def list_tasks(): + """Получить список всех задач""" + return { + "tasks": [ + { + "task_id": task_id, + "status": task["status"], + "task": task.get("task", ""), + "result": task.get("result"), + "error": task.get("error") + } + for task_id, task in tasks.items() + ] + } + @app.get("/api/health") async def health_check(): """Проверка здоровья сервера""" @@ -126,5 +155,174 @@ async def health_check(): "version": "1.0.0" } +# Web UI - Главная страница +WEB_UI_HTML = """ + + + + + + Browser Use API + + + +

Browser Use API

+

REST API для автоматизации браузера с помощью AI

+ +
+

Быстрые ссылки

+

Открыть Dashboard

+
+ +
+

API Endpoints

+
    +
  • POST /api/tasks - Создать задачу
  • +
  • GET /api/tasks/{task_id} - Получить результат
  • +
  • GET /api/health - Проверка здоровья
  • +
+
+ +
+

Пример использования

+
curl -X POST http://localhost:8383/api/tasks \\
+  -H "Content-Type: application/json" \\
+  -d '{"task": "Перейди на example.com", "max_steps": 20}'
+
+ + +""" + +DASHBOARD_HTML = """ + + + + + + Browser Use Dashboard + + + +
+ +

Browser Use Dashboard

+ +
+

Создать задачу

+
+ + + + +
+
+ +
+

Задачи

+ +
    +
    +
    + + + + +""" + +@app.get("/", response_class=HTMLResponse) +async def root(): + """Главная страница""" + return HTMLResponse(content=WEB_UI_HTML) + +@app.get("/dashboard", response_class=HTMLResponse) +async def dashboard(): + """Dashboard""" + return HTMLResponse(content=DASHBOARD_HTML) + if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8383) diff --git a/docker-compose.yml b/docker-compose.yml index 6c798cb..cd172f3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,12 @@ services: container_name: browser-use ports: - "8383:8383" + - "9222:9222" environment: - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} + - LLM_MODEL_NAME=${LLM_MODEL_NAME:-arcee-ai/trinity-large-preview:free} + - REMOTE_DEBUGGING_ENABLED=${REMOTE_DEBUGGING_ENABLED:-false} + - REMOTE_DEBUGGING_PORT=${REMOTE_DEBUGGING_PORT:-9222} volumes: - /home/nafer/dokploy_data/browser-use:/app/browser-data shm_size: '2gb'