flash-psyho
This commit is contained in:
1 parent
0f97b4320e
commit
821e616c4b
4 files changed
+66
-41
No files matched your search
@@ -19,3 +19,8 @@ AGENT_MAX_STEPS=20
|
||||
AGENT_USE_VISION=true
|
||||
SERVER_PORT=8383
|
||||
SERVER_HOST=0.0.0.0
|
||||
|
||||
# Remote Debugging
|
||||
REMOTE_DEBUGGING_ENABLED=true
|
||||
REMOTE_DEBUGGING_PORT=9222
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
FROM mcr.microsoft.com/playwright/python:v1.49.0-noble
|
||||
|
||||
# Установка системных зависимостей (socat для проброса портов)
|
||||
RUN apt-get update && apt-get install -y socat && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Установка дополнительных Python зависимостей
|
||||
RUN pip install --no-cache-dir --root-user-action=ignore \
|
||||
fastapi \
|
||||
|
||||
@@ -21,29 +21,34 @@ DEFAULT_MODEL = os.getenv("LLM_MODEL_NAME", "openai/gpt-4o-mini")
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
import logging
|
||||
|
||||
# Настройка логирования
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Startup logic
|
||||
import sys
|
||||
from importlib import metadata
|
||||
print(f"Python version: {sys.version}")
|
||||
logger.info(f"Python version: {sys.version}")
|
||||
|
||||
# Автоматический запуск Chrome при старте, если включен Remote Debugging
|
||||
if REMOTE_DEBUGGING_ENABLED:
|
||||
print("Remote Debugging enabled, starting Chrome on startup...")
|
||||
logger.info("Remote Debugging enabled, starting Chrome on startup...")
|
||||
# Выведем IP адреса для отладки
|
||||
import socket
|
||||
try:
|
||||
hostname = socket.gethostname()
|
||||
ip_address = socket.gethostbyname(hostname)
|
||||
print(f"Container IP: {ip_address}")
|
||||
logger.info(f"Container IP: {ip_address}")
|
||||
except:
|
||||
pass
|
||||
# Запускаем Chrome
|
||||
asyncio.create_task(run_browser_task("startup", "about:blank", 1, None))
|
||||
|
||||
yield
|
||||
# Shutdown logic (if needed)
|
||||
|
||||
app = FastAPI(title="Browser Use API", version="1.0.0", lifespan=lifespan)
|
||||
|
||||
@@ -117,15 +122,15 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
cdp_url = f"http://127.0.0.1:{REMOTE_DEBUGGING_PORT}"
|
||||
|
||||
# 1. Проверяем, не запущен ли уже Chrome с CDP
|
||||
print(f"[{task_id}] Checking if Chrome is already running with CDP at {cdp_url}...")
|
||||
logger.info(f"[{task_id}] Checking if Chrome is already running with CDP at {cdp_url}...")
|
||||
chrome_already_running = False
|
||||
try:
|
||||
response = urllib.request.urlopen(f"{cdp_url}/json/version", timeout=2)
|
||||
if response.status == 200:
|
||||
print(f"[{task_id}] Chrome is already running, connecting to existing instance.")
|
||||
logger.info(f"[{task_id}] Chrome is already running, connecting to existing instance.")
|
||||
chrome_already_running = True
|
||||
except Exception:
|
||||
print(f"[{task_id}] Chrome not detected at {cdp_url}. Starting new instance...")
|
||||
logger.info(f"[{task_id}] Chrome not detected at {cdp_url}. Starting new instance...")
|
||||
|
||||
if not chrome_already_running:
|
||||
# Список возможных путей к Chrome
|
||||
@@ -149,24 +154,27 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
chrome_exe = shutil.which("google-chrome") or shutil.which("chromium") or shutil.which("chromium-browser")
|
||||
|
||||
if not chrome_exe:
|
||||
# В образе Playwright путь обычно такой:
|
||||
chrome_exe = "/usr/bin/google-chrome"
|
||||
|
||||
print(f"[{task_id}] Using Chrome executable: {chrome_exe}")
|
||||
logger.info(f"[{task_id}] Using Chrome executable: {chrome_exe}")
|
||||
|
||||
# Используем постоянную директорию для сохранения сессий (логинов)
|
||||
user_data_dir = "/app/browser-data/main_profile"
|
||||
os.makedirs(user_data_dir, exist_ok=True)
|
||||
|
||||
# Запускаем Chrome с remote debugging
|
||||
# Внутренний порт для Chrome
|
||||
CHROME_INTERNAL_PORT = REMOTE_DEBUGGING_PORT + 1 # 9223
|
||||
|
||||
# Запускаем Chrome с remote debugging на внутреннем порту
|
||||
chrome_cmd = [
|
||||
chrome_exe,
|
||||
f"--remote-debugging-port={REMOTE_DEBUGGING_PORT}",
|
||||
"--remote-debugging-address=0.0.0.0",
|
||||
f"--user-data-dir={user_data_dir}",
|
||||
f"--remote-debugging-port={CHROME_INTERNAL_PORT}",
|
||||
"--remote-debugging-address=127.0.0.1",
|
||||
"--remote-allow-origins=*",
|
||||
"--headless=new",
|
||||
f"--user-data-dir={user_data_dir}",
|
||||
"--headless",
|
||||
"--no-sandbox",
|
||||
"--disable-setuid-sandbox",
|
||||
"--disable-dev-shm-usage",
|
||||
"--disable-gpu",
|
||||
"--no-first-run",
|
||||
@@ -175,46 +183,56 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
"about:blank"
|
||||
]
|
||||
|
||||
print(f"[{task_id}] Executing command: {' '.join(chrome_cmd)}")
|
||||
logger.info(f"[{task_id}] Executing Chrome: {' '.join(chrome_cmd)}")
|
||||
|
||||
# Запускаем процесс
|
||||
# Запускаем Chrome
|
||||
log_file = open(f"/tmp/chrome_{task_id}.log", "w")
|
||||
process = subprocess.Popen(
|
||||
subprocess.Popen(
|
||||
chrome_cmd,
|
||||
stdout=log_file,
|
||||
stderr=log_file,
|
||||
start_new_session=True
|
||||
)
|
||||
|
||||
# Запускаем socat для проброса порта 9222 -> 9223
|
||||
socat_cmd = [
|
||||
"socat",
|
||||
f"TCP-LISTEN:{REMOTE_DEBUGGING_PORT},fork,reuseaddr",
|
||||
f"TCP:127.0.0.1:{CHROME_INTERNAL_PORT}"
|
||||
]
|
||||
logger.info(f"[{task_id}] Executing socat: {' '.join(socat_cmd)}")
|
||||
subprocess.Popen(
|
||||
socat_cmd,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
start_new_session=True
|
||||
)
|
||||
|
||||
# Ждем пока Chrome запустится и CDP будет готов
|
||||
cdp_ready = False
|
||||
for i in range(30): # Ждем до 30 секунд
|
||||
# Для внутреннего использования приложением используем 9223
|
||||
internal_cdp_url = f"http://127.0.0.1:{CHROME_INTERNAL_PORT}"
|
||||
|
||||
for i in range(30):
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Проверка порта
|
||||
import socket
|
||||
for host in ['127.0.0.1', '0.0.0.0', ip_address]:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||
if s.connect_ex((host, REMOTE_DEBUGGING_PORT)) == 0:
|
||||
print(f"[{task_id}] Port {REMOTE_DEBUGGING_PORT} is OPEN on {host}!")
|
||||
else:
|
||||
print(f"[{task_id}] Port {REMOTE_DEBUGGING_PORT} is CLOSED on {host}!")
|
||||
|
||||
try:
|
||||
response = urllib.request.urlopen(f"{cdp_url}/json/version", timeout=2)
|
||||
response = urllib.request.urlopen(f"{internal_cdp_url}/json/version", timeout=2)
|
||||
if response.status == 200:
|
||||
cdp_ready = True
|
||||
print(f"[{task_id}] CDP is ready at {cdp_url}")
|
||||
logger.info(f"[{task_id}] CDP is ready at {internal_cdp_url} (proxied to {REMOTE_DEBUGGING_PORT})")
|
||||
break
|
||||
except Exception:
|
||||
if i % 5 == 0:
|
||||
print(f"[{task_id}] Waiting for CDP at {cdp_url}... (attempt {i})")
|
||||
logger.info(f"[{task_id}] Waiting for Chrome at {internal_cdp_url}... (attempt {i})")
|
||||
|
||||
if not cdp_ready:
|
||||
with open(f"/tmp/chrome_{task_id}.log", "r") as f:
|
||||
print(f"[{task_id}] Chrome Logs:\n{f.read()}")
|
||||
if task_id != "startup":
|
||||
raise RuntimeError(f"Failed to start Chrome or CDP not ready after 30s at {cdp_url}")
|
||||
if not cdp_ready:
|
||||
with open(f"/tmp/chrome_{task_id}.log", "r") as f:
|
||||
logger.error(f"[{task_id}] Chrome Logs:\n{f.read()}")
|
||||
if task_id != "startup":
|
||||
raise RuntimeError(f"Failed to start Chrome at {internal_cdp_url}")
|
||||
|
||||
# Обновляем cdp_url для Browser
|
||||
cdp_url = internal_cdp_url
|
||||
|
||||
# Подключаемся через CDP
|
||||
browser = Browser(cdp_url=cdp_url)
|
||||
@@ -230,7 +248,7 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
|
||||
# Если это был просто запуск при старте - выходим
|
||||
if task_id == "startup":
|
||||
print("[startup] Chrome started successfully and ready for connections.")
|
||||
logger.info("[startup] Chrome started successfully and ready for connections.")
|
||||
return
|
||||
|
||||
# Создание агента
|
||||
@@ -251,12 +269,11 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
tasks[task_id]["result"] = result
|
||||
|
||||
except Exception as e:
|
||||
print(f"[{task_id}] Error: {e}")
|
||||
logger.error(f"[{task_id}] Error: {e}")
|
||||
if task_id in tasks:
|
||||
tasks[task_id]["status"] = "failed"
|
||||
tasks[task_id]["error"] = str(e)
|
||||
finally:
|
||||
# Не закрываем браузер
|
||||
pass
|
||||
|
||||
@app.get("/api/tasks/{task_id}", response_model=TaskResponse)
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@ services:
|
||||
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}
|
||||
- REMOTE_DEBUGGING_ENABLED=true
|
||||
- REMOTE_DEBUGGING_PORT=9222
|
||||
volumes:
|
||||
- /home/nafer/dokploy_data/browser-use:/app/browser-data
|
||||
shm_size: '2gb'
|
||||
|
||||
Reference in new issue
Block a user