Merge remote-tracking branch 'origin/feature/telegram-browser-integration' into feature/telegram-browser-integration

This commit is contained in:
Максим Туревич 2026-04-03 17:58:36 +03:00
commit bb5ce8e762
3 changed files with 197 additions and 24 deletions

18
READ.md
View file

@ -6,16 +6,30 @@ git clone https://git.lambda.coredump.ru/APEX/BrowserUse_and_ComputerUse_skills.
git switch feature/telegram-browser-integration git switch feature/telegram-browser-integration
touch .env touch .env
``` ```
В создавшемся .env файле заполните переменные в соответствии с шаблоном, расположенном в .env.example В создавшемся .env файле заполните переменные в соответствии с шаблоном, расположенном в .env.example
BROWSER_VIEW_URL заполняется после запуска BROWSER_VIEW_URL заполняется после запуска
#### Запуск удаленно
```commandline ```commandline
docker compose up -d --build docker compose --profile remote up --build
docker compose logs tunnel docker compose logs tunnel
``` ```
После команды логов листаешь терминал и ищешь ссылку https в рамке. Её вписываешь в переменную BROWSER_VIEW_URL. После команды логов листаешь терминал и ищешь ссылку https в рамке. Её вписываешь в переменную BROWSER_VIEW_URL.
Чтобы увидеть действия агента, переходишь по данной сслыке и выбираешь vnc.html. Чтобы увидеть действия агента, переходишь по данной ссылке и выбираешь vnc.html.
Далее в мессенджере просишь агента сделать что-то через tool browser-use. Далее в мессенджере просишь агента сделать что-то через tool browser-use.
Возможно придётся перезапустить контейнеры, но при перезапуске контейнеров меняется ссылка. Возможно придётся перезапустить контейнеры, но при перезапуске контейнеров меняется ссылка.
#### Запуск локально
BROWSER_VIEW_URL устанавливается как http://localhost:6080
```commandline
docker compose up
```
---
```commandline ```commandline
docker compose down docker compose down
docker compose up -d docker compose up -d

View file

@ -1,41 +1,191 @@
#!/bin/bash #!/usr/bin/env bash
set -Eeuo pipefail
export DISPLAY=:99 export DISPLAY="${DISPLAY:-:99}"
DISPLAY_NUM="${DISPLAY#:}"
XVFB_LOG="/tmp/xvfb.log"
mkdir -p /var/run/dbus VNC_PORT="${VNC_PORT:-5900}"
dbus-uuidgen > /var/lib/dbus/machine-id NOVNC_PORT="${NOVNC_PORT:-6080}"
dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address & CHROME_LOCAL_DEBUG_PORT="${CHROME_LOCAL_DEBUG_PORT:-9223}"
CHROME_PUBLIC_DEBUG_PORT="${CHROME_PUBLIC_DEBUG_PORT:-9222}"
CHROME_PROFILE_DIR="${CHROME_PROFILE_DIR:-/src/browser_data}"
Xvfb :99 -screen 0 1280x720x16 -ac +extension GLX +render -noreset & MAX_RESTARTS="${MAX_RESTARTS:-10}"
sleep 2 RESTART_WINDOW_SEC="${RESTART_WINDOW_SEC:-60}"
RESTART_BACKOFF_SEC="${RESTART_BACKOFF_SEC:-2}"
fluxbox & PIDS=()
x11vnc -display :99 -nopw -listen 0.0.0.0 -xkb -forever -shared & STOPPING=0
websockify --web=/usr/share/novnc/ 6080 localhost:5900 & WINDOW_START="$(date +%s)"
RESTART_COUNT=0
socat TCP-LISTEN:9222,fork,reuseaddr TCP:127.0.0.1:9223 & log() {
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
}
echo "--- Запуск Chromium в режиме Local-Only (Port 9223) ---" start_bg() {
"$@" &
local pid=$!
PIDS+=("$pid")
log "started: $* (pid=$pid)"
}
wait_for_port() {
local host=$1
local port=$2
local timeout_sec=$3
local end_ts=$(( $(date +%s) + timeout_sec ))
while [ "$(date +%s)" -lt "$end_ts" ]; do
if bash -c "</dev/tcp/${host}/${port}" >/dev/null 2>&1; then
return 0
fi
sleep 0.2
done
return 1
}
wait_for_x_display() {
local timeout_sec=$1
local end_ts=$(( $(date +%s) + timeout_sec ))
while [ "$(date +%s)" -lt "$end_ts" ]; do
if [ -S "/tmp/.X11-unix/X${DISPLAY_NUM}" ] && DISPLAY="$DISPLAY" bash -c 'echo >/dev/null' >/dev/null 2>&1; then
return 0
fi
sleep 0.2
done
return 1
}
cleanup() {
if [ "$STOPPING" -eq 1 ]; then
return
fi
STOPPING=1
log "shutdown signal received, stopping processes..."
if [ -n "${CHROME_PID:-}" ] && kill -0 "$CHROME_PID" >/dev/null 2>&1; then
kill "$CHROME_PID" >/dev/null 2>&1 || true
fi
for pid in "${PIDS[@]:-}"; do
kill "$pid" >/dev/null 2>&1 || true
done
sleep 1
if [ -n "${CHROME_PID:-}" ] && kill -0 "$CHROME_PID" >/dev/null 2>&1; then
kill -9 "$CHROME_PID" >/dev/null 2>&1 || true
fi
for pid in "${PIDS[@]:-}"; do
if kill -0 "$pid" >/dev/null 2>&1; then
kill -9 "$pid" >/dev/null 2>&1 || true
fi
done
log "shutdown complete"
}
trap cleanup SIGTERM SIGINT EXIT
mkdir -p /var/run/dbus /var/lib/dbus "$CHROME_PROFILE_DIR"
if [ ! -f /var/lib/dbus/machine-id ]; then
dbus-uuidgen > /var/lib/dbus/machine-id 2>/dev/null || true
fi
# Удаляем stale lock/socket от прошлых падений Xvfb на том же DISPLAY.
rm -f "/tmp/.X${DISPLAY_NUM}-lock" "/tmp/.X11-unix/X${DISPLAY_NUM}" || true
log "starting X stack on DISPLAY=${DISPLAY}"
Xvfb "$DISPLAY" -screen 0 1280x720x24 -ac +extension GLX +render -noreset >"$XVFB_LOG" 2>&1 &
XVFB_PID=$!
PIDS+=("$XVFB_PID")
log "started: Xvfb $DISPLAY (pid=$XVFB_PID)"
if ! wait_for_x_display 15; then
log "fatal: Xvfb did not initialize DISPLAY=${DISPLAY}"
if [ -f "$XVFB_LOG" ]; then
log "xvfb log tail:"
tail -n 40 "$XVFB_LOG" || true
fi
exit 1
fi
start_bg fluxbox
start_bg x11vnc -display "$DISPLAY" -rfbport "$VNC_PORT" -nopw -listen 0.0.0.0 -xkb -forever -shared
start_bg websockify --web=/usr/share/novnc/ "$NOVNC_PORT" "localhost:${VNC_PORT}"
start_bg socat "TCP-LISTEN:${CHROME_PUBLIC_DEBUG_PORT},fork,reuseaddr" "TCP:127.0.0.1:${CHROME_LOCAL_DEBUG_PORT}"
if ! wait_for_port 127.0.0.1 "$VNC_PORT" 20; then
log "fatal: x11vnc did not open port ${VNC_PORT}"
exit 1
fi
if ! wait_for_port 127.0.0.1 "$NOVNC_PORT" 20; then
log "fatal: websockify did not open port ${NOVNC_PORT}"
exit 1
fi
log "browser infrastructure is ready (noVNC:${NOVNC_PORT}, DevTools proxy:${CHROME_PUBLIC_DEBUG_PORT})"
while true; do while true; do
rm -f /src/browser_data/SingletonLock for pid in "${PIDS[@]}"; do
if ! kill -0 "$pid" >/dev/null 2>&1; then
log "fatal: required background process died (pid=${pid})"
exit 1
fi
done
rm -f "${CHROME_PROFILE_DIR}/SingletonLock" "${CHROME_PROFILE_DIR}/SingletonCookie" "${CHROME_PROFILE_DIR}/SingletonSocket" 2>/dev/null || true
log "starting Chromium (local DevTools:${CHROME_LOCAL_DEBUG_PORT})"
chromium \ chromium \
--no-sandbox \ --no-sandbox \
--disable-dev-shm-usage \ --disable-dev-shm-usage \
--remote-debugging-port=9223 \ --ozone-platform=x11 \
--remote-debugging-port="${CHROME_LOCAL_DEBUG_PORT}" \
--remote-debugging-address=127.0.0.1 \ --remote-debugging-address=127.0.0.1 \
--remote-allow-origins=* \ --remote-allow-origins='*' \
--window-size=1280,720 \ --window-size=1280,720 \
--user-data-dir=/src/browser_data \ --user-data-dir="${CHROME_PROFILE_DIR}" \
--disable-blink-features=AutomationControlled \ --disable-blink-features=AutomationControlled \
--no-first-run \ --no-first-run \
--disable-gpu \ --disable-gpu \
--mute-audio \ --mute-audio \
--no-default-browser-check \ --no-default-browser-check \
--disable-software-rasterizer \ --disable-software-rasterizer \
--disable-features=site-per-process --disable-features=site-per-process \
--disable-crash-reporter \
--disable-extensions \
--disable-sync &
CHROME_PID=$!
wait "$CHROME_PID" || CHROME_EXIT=$?
CHROME_EXIT=${CHROME_EXIT:-0}
if [ "$STOPPING" -eq 1 ]; then
break
fi
now="$(date +%s)"
if [ $(( now - WINDOW_START )) -gt "$RESTART_WINDOW_SEC" ]; then
WINDOW_START="$now"
RESTART_COUNT=0
fi
RESTART_COUNT=$((RESTART_COUNT + 1))
log "Chromium exited with code=${CHROME_EXIT}; restart ${RESTART_COUNT}/${MAX_RESTARTS} in current window"
if [ "$RESTART_COUNT" -ge "$MAX_RESTARTS" ]; then
log "fatal: too many Chromium restarts in ${RESTART_WINDOW_SEC}s"
exit 1
fi
sleep "$RESTART_BACKOFF_SEC"
unset CHROME_EXIT
unset CHROME_PID
done
echo "Chromium упал или был закрыт агентом, рестарт через 2 секунды..."
sleep 2
done

View file

@ -15,7 +15,8 @@ services:
- ./workspace:/app/workspace:rw - ./workspace:/app/workspace:rw
- ./config.example.yaml:/app/config.example.yaml:ro - ./config.example.yaml:/app/config.example.yaml:ro
depends_on: depends_on:
- browser browser:
condition: service_healthy
stdin_open: true stdin_open: true
tty: true tty: true
restart: always restart: always
@ -50,9 +51,17 @@ services:
volumes: volumes:
- browser_profiles:/src/browser_data - browser_profiles:/src/browser_data
restart: always restart: always
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9222/json/version >/dev/null || exit 1"]
interval: 10s
timeout: 3s
retries: 12
start_period: 20s
tunnel: tunnel:
image: cloudflare/cloudflared:latest image: cloudflare/cloudflared:latest
profiles:
- remote
container_name: hermes-tunnel container_name: hermes-tunnel
restart: always restart: always
command: tunnel --protocol http2 --url http://browser:6080 --no-tls-verify command: tunnel --protocol http2 --url http://browser:6080 --no-tls-verify