flash-psyho
This commit is contained in:
1 parent
0f97b4320e
commit
821e616c4b
4 files changed
+63
-38
No files matched your search
@@ -19,3 +19,8 @@ AGENT_MAX_STEPS=20
|
|||||||
AGENT_USE_VISION=true
|
AGENT_USE_VISION=true
|
||||||
SERVER_PORT=8383
|
SERVER_PORT=8383
|
||||||
SERVER_HOST=0.0.0.0
|
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
|
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 зависимостей
|
# Установка дополнительных Python зависимостей
|
||||||
RUN pip install --no-cache-dir --root-user-action=ignore \
|
RUN pip install --no-cache-dir --root-user-action=ignore \
|
||||||
fastapi \
|
fastapi \
|
||||||
|
|||||||
@@ -21,29 +21,34 @@ DEFAULT_MODEL = os.getenv("LLM_MODEL_NAME", "openai/gpt-4o-mini")
|
|||||||
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Настройка логирования
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
# Startup logic
|
# Startup logic
|
||||||
import sys
|
import sys
|
||||||
from importlib import metadata
|
from importlib import metadata
|
||||||
print(f"Python version: {sys.version}")
|
logger.info(f"Python version: {sys.version}")
|
||||||
|
|
||||||
# Автоматический запуск Chrome при старте, если включен Remote Debugging
|
# Автоматический запуск Chrome при старте, если включен Remote Debugging
|
||||||
if REMOTE_DEBUGGING_ENABLED:
|
if REMOTE_DEBUGGING_ENABLED:
|
||||||
print("Remote Debugging enabled, starting Chrome on startup...")
|
logger.info("Remote Debugging enabled, starting Chrome on startup...")
|
||||||
# Выведем IP адреса для отладки
|
# Выведем IP адреса для отладки
|
||||||
import socket
|
import socket
|
||||||
try:
|
try:
|
||||||
hostname = socket.gethostname()
|
hostname = socket.gethostname()
|
||||||
ip_address = socket.gethostbyname(hostname)
|
ip_address = socket.gethostbyname(hostname)
|
||||||
print(f"Container IP: {ip_address}")
|
logger.info(f"Container IP: {ip_address}")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
# Запускаем Chrome
|
# Запускаем Chrome
|
||||||
asyncio.create_task(run_browser_task("startup", "about:blank", 1, None))
|
asyncio.create_task(run_browser_task("startup", "about:blank", 1, None))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
# Shutdown logic (if needed)
|
|
||||||
|
|
||||||
app = FastAPI(title="Browser Use API", version="1.0.0", lifespan=lifespan)
|
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}"
|
cdp_url = f"http://127.0.0.1:{REMOTE_DEBUGGING_PORT}"
|
||||||
|
|
||||||
# 1. Проверяем, не запущен ли уже Chrome с CDP
|
# 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
|
chrome_already_running = False
|
||||||
try:
|
try:
|
||||||
response = urllib.request.urlopen(f"{cdp_url}/json/version", timeout=2)
|
response = urllib.request.urlopen(f"{cdp_url}/json/version", timeout=2)
|
||||||
if response.status == 200:
|
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
|
chrome_already_running = True
|
||||||
except Exception:
|
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:
|
if not chrome_already_running:
|
||||||
# Список возможных путей к Chrome
|
# Список возможных путей к 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")
|
chrome_exe = shutil.which("google-chrome") or shutil.which("chromium") or shutil.which("chromium-browser")
|
||||||
|
|
||||||
if not chrome_exe:
|
if not chrome_exe:
|
||||||
# В образе Playwright путь обычно такой:
|
|
||||||
chrome_exe = "/usr/bin/google-chrome"
|
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"
|
user_data_dir = "/app/browser-data/main_profile"
|
||||||
os.makedirs(user_data_dir, exist_ok=True)
|
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_cmd = [
|
||||||
chrome_exe,
|
chrome_exe,
|
||||||
f"--remote-debugging-port={REMOTE_DEBUGGING_PORT}",
|
f"--remote-debugging-port={CHROME_INTERNAL_PORT}",
|
||||||
"--remote-debugging-address=0.0.0.0",
|
"--remote-debugging-address=127.0.0.1",
|
||||||
f"--user-data-dir={user_data_dir}",
|
|
||||||
"--remote-allow-origins=*",
|
"--remote-allow-origins=*",
|
||||||
"--headless=new",
|
f"--user-data-dir={user_data_dir}",
|
||||||
|
"--headless",
|
||||||
"--no-sandbox",
|
"--no-sandbox",
|
||||||
|
"--disable-setuid-sandbox",
|
||||||
"--disable-dev-shm-usage",
|
"--disable-dev-shm-usage",
|
||||||
"--disable-gpu",
|
"--disable-gpu",
|
||||||
"--no-first-run",
|
"--no-first-run",
|
||||||
@@ -175,46 +183,56 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
|||||||
"about:blank"
|
"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")
|
log_file = open(f"/tmp/chrome_{task_id}.log", "w")
|
||||||
process = subprocess.Popen(
|
subprocess.Popen(
|
||||||
chrome_cmd,
|
chrome_cmd,
|
||||||
stdout=log_file,
|
stdout=log_file,
|
||||||
stderr=log_file,
|
stderr=log_file,
|
||||||
start_new_session=True
|
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 будет готов
|
# Ждем пока Chrome запустится и CDP будет готов
|
||||||
cdp_ready = False
|
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)
|
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:
|
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:
|
if response.status == 200:
|
||||||
cdp_ready = True
|
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
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
if i % 5 == 0:
|
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:
|
if not cdp_ready:
|
||||||
with open(f"/tmp/chrome_{task_id}.log", "r") as f:
|
with open(f"/tmp/chrome_{task_id}.log", "r") as f:
|
||||||
print(f"[{task_id}] Chrome Logs:\n{f.read()}")
|
logger.error(f"[{task_id}] Chrome Logs:\n{f.read()}")
|
||||||
if task_id != "startup":
|
if task_id != "startup":
|
||||||
raise RuntimeError(f"Failed to start Chrome or CDP not ready after 30s at {cdp_url}")
|
raise RuntimeError(f"Failed to start Chrome at {internal_cdp_url}")
|
||||||
|
|
||||||
|
# Обновляем cdp_url для Browser
|
||||||
|
cdp_url = internal_cdp_url
|
||||||
|
|
||||||
# Подключаемся через CDP
|
# Подключаемся через CDP
|
||||||
browser = Browser(cdp_url=cdp_url)
|
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":
|
if task_id == "startup":
|
||||||
print("[startup] Chrome started successfully and ready for connections.")
|
logger.info("[startup] Chrome started successfully and ready for connections.")
|
||||||
return
|
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
|
tasks[task_id]["result"] = result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[{task_id}] Error: {e}")
|
logger.error(f"[{task_id}] Error: {e}")
|
||||||
if task_id in tasks:
|
if task_id in tasks:
|
||||||
tasks[task_id]["status"] = "failed"
|
tasks[task_id]["status"] = "failed"
|
||||||
tasks[task_id]["error"] = str(e)
|
tasks[task_id]["error"] = str(e)
|
||||||
finally:
|
finally:
|
||||||
# Не закрываем браузер
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@app.get("/api/tasks/{task_id}", response_model=TaskResponse)
|
@app.get("/api/tasks/{task_id}", response_model=TaskResponse)
|
||||||
|
|||||||
+2
-2
@@ -13,8 +13,8 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
|
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
|
||||||
- LLM_MODEL_NAME=${LLM_MODEL_NAME:-arcee-ai/trinity-large-preview:free}
|
- LLM_MODEL_NAME=${LLM_MODEL_NAME:-arcee-ai/trinity-large-preview:free}
|
||||||
- REMOTE_DEBUGGING_ENABLED=${REMOTE_DEBUGGING_ENABLED:-false}
|
- REMOTE_DEBUGGING_ENABLED=true
|
||||||
- REMOTE_DEBUGGING_PORT=${REMOTE_DEBUGGING_PORT:-9222}
|
- REMOTE_DEBUGGING_PORT=9222
|
||||||
volumes:
|
volumes:
|
||||||
- /home/nafer/dokploy_data/browser-use:/app/browser-data
|
- /home/nafer/dokploy_data/browser-use:/app/browser-data
|
||||||
shm_size: '2gb'
|
shm_size: '2gb'
|
||||||
|
|||||||
Reference in new issue
Block a user