hermes-erkenntnisse/bridges/wegb-2026-07-22/cdp.py

84 lines
3 KiB
Python

"""Weg B — CDPBridge: an das BEREITS eingeloggte Chrome auf gpu-pc (CDP :9223) andocken,
statt einen eigenen Browser (launch_persistent_context) mit injizierten Cookies zu starten.
suno.py macht das bereits (eigenes get_page() mit connect_over_cdp). Dieses Modul verallgemeinert
exakt dieses erprobte Muster, damit gemini.py und qolaba.py denselben Weg nutzen, ohne ihre
Selector-/Ablauf-Logik anzufassen.
Die Session MUSS auf gpu-pc eingeloggt sein (sonst [BAER - PWA-Login]). Auto-Relogin aus dem
Bridge-Prozess ist bei geteiltem CDP-Context nicht moeglich (relogin_supported=False).
"""
import asyncio, os, socket
from urllib.parse import urlparse, urlunparse
from patchright.async_api import async_playwright as _patchright_async_playwright
from .base import PWABridge
CDP_URL = os.environ.get("PWA_CDP_URL") or os.environ.get("SUNO_CDP_URL") \
or "http://host.docker.internal:9223"
_cdp_pw = None
_cdp_browser = None
def _resolve_cdp_url(url: str) -> str:
try:
parsed = urlparse(url)
if parsed.hostname in ("host.docker.internal", "localhost"):
ip = socket.gethostbyname(parsed.hostname)
netloc = f"{ip}:{parsed.port}" if parsed.port else ip
return urlunparse(parsed._replace(netloc=netloc))
except Exception as e:
print(f"[cdp] _resolve_cdp_url err ({e}), using raw CDP_URL", flush=True)
return url
async def _cdp_connect():
global _cdp_pw, _cdp_browser
if _cdp_pw is None:
_cdp_pw = await _patchright_async_playwright().start()
if _cdp_browser is not None:
try:
_ = _cdp_browser.contexts
except Exception:
_cdp_browser = None
if _cdp_browser is None:
resolved = _resolve_cdp_url(CDP_URL)
_cdp_browser = await asyncio.wait_for(
_cdp_pw.chromium.connect_over_cdp(resolved), timeout=12)
return _cdp_browser
class CDPBridge(PWABridge):
match_host: str = ""
relogin_supported = False
async def get_ctx(self):
b = await _cdp_connect()
return b.contexts[0] if b.contexts else await b.new_context()
async def get_page(self):
global _cdp_browser
try:
b = await _cdp_connect()
ctx = b.contexts[0] if b.contexts else await b.new_context()
except Exception as e:
print(f"[{self.name}] CDP stale handle ({e}), forcing reconnect", flush=True)
_cdp_browser = None
b = await _cdp_connect()
ctx = b.contexts[0] if b.contexts else await b.new_context()
host = self.match_host or (urlparse(self.url).hostname or "")
for p in ctx.pages:
try:
if host and host in (p.url or ""):
return p
except Exception:
pass
p = await ctx.new_page()
if self.url:
try:
await p.goto(self.url, wait_until="domcontentloaded", timeout=30000)
except Exception as e:
print(f"[{self.name}] CDP initial goto err: {e}", flush=True)
return p