mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-07-28 02:23:46 +00:00
Co-authored-by: Douglas Lai <115660088+Douglasymlai@users.noreply.github.com> Co-authored-by: Douglas <douglas.ym.lai@gmail.com>
167 lines
5 KiB
Python
167 lines
5 KiB
Python
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
|
|
|
import logging
|
|
import time
|
|
from typing import Any
|
|
|
|
from fastapi import Request
|
|
|
|
from app.component.environment import env
|
|
from app.utils.browser_launcher import (
|
|
_is_cdp_available,
|
|
is_cdp_url_available,
|
|
is_local_cdp_host,
|
|
normalize_cdp_url,
|
|
)
|
|
|
|
logger = logging.getLogger("cdp_browser_state")
|
|
|
|
_web_cdp_browser_meta_by_owner: dict[str, dict[str, Any]] = {}
|
|
|
|
|
|
def browser_owner_key(request: Request | None) -> str:
|
|
auth = getattr(getattr(request, "state", None), "brain_auth", None)
|
|
user_id = getattr(auth, "user_id", None)
|
|
if user_id and user_id != "local":
|
|
return str(user_id)
|
|
|
|
# Bridge release fallback: NoneAuth still emits "local", while the
|
|
# frontend already sends X-User-ID. Phase B auth will make this token-only.
|
|
if request is not None:
|
|
header_user_id = request.headers.get("x-user-id")
|
|
if header_user_id:
|
|
return header_user_id
|
|
return "local"
|
|
|
|
|
|
def build_web_cdp_browser(
|
|
endpoint: str,
|
|
*,
|
|
is_external: bool,
|
|
name: str | None = None,
|
|
added_at: int | None = None,
|
|
resource_session_id: str | None = None,
|
|
managed_by: str = "local",
|
|
) -> dict[str, Any]:
|
|
normalized_endpoint, host, port = normalize_cdp_url(endpoint)
|
|
default_location = (
|
|
str(port) if is_local_cdp_host(host) else f"{host}:{port}"
|
|
)
|
|
browser_name = name or (
|
|
f"External Browser ({default_location})"
|
|
if is_external
|
|
else f"Managed Browser ({default_location})"
|
|
)
|
|
browser_id = resource_session_id or (
|
|
f"web-cdp-{port}"
|
|
if is_local_cdp_host(host)
|
|
else f"web-cdp-{host.replace('.', '-')}-{port}"
|
|
)
|
|
return {
|
|
"id": browser_id,
|
|
"port": port,
|
|
"endpoint": normalized_endpoint,
|
|
"host": host,
|
|
"isExternal": is_external,
|
|
"name": browser_name,
|
|
"addedAt": added_at or int(time.time() * 1000),
|
|
"resourceSessionId": resource_session_id,
|
|
"managedBy": managed_by,
|
|
}
|
|
|
|
|
|
def get_connected_cdp_endpoint(owner_key: str) -> str | None:
|
|
if owner_key in _web_cdp_browser_meta_by_owner:
|
|
return _web_cdp_browser_meta_by_owner[owner_key].get("endpoint")
|
|
cdp_url = env("EIGENT_CDP_URL")
|
|
if cdp_url:
|
|
return cdp_url
|
|
return None
|
|
|
|
|
|
def get_connected_cdp_endpoint_for_request(
|
|
request: Request | None,
|
|
) -> str | None:
|
|
return get_connected_cdp_endpoint(browser_owner_key(request))
|
|
|
|
|
|
def get_connected_cdp_meta(owner_key: str) -> dict[str, Any] | None:
|
|
return _web_cdp_browser_meta_by_owner.get(owner_key)
|
|
|
|
|
|
def get_connected_cdp_port(owner_key: str) -> int | None:
|
|
cdp_url = get_connected_cdp_endpoint(owner_key)
|
|
if not cdp_url:
|
|
return None
|
|
try:
|
|
_, _, port = normalize_cdp_url(cdp_url)
|
|
return port
|
|
except Exception:
|
|
logger.warning("Invalid EIGENT_CDP_URL: %s", cdp_url)
|
|
return None
|
|
|
|
|
|
def set_connected_cdp_browser(
|
|
owner_key: str,
|
|
endpoint: str,
|
|
*,
|
|
is_external: bool,
|
|
name: str | None = None,
|
|
resource_session_id: str | None = None,
|
|
managed_by: str = "local",
|
|
) -> dict[str, Any]:
|
|
normalized_endpoint, _, _ = normalize_cdp_url(endpoint)
|
|
browser = build_web_cdp_browser(
|
|
normalized_endpoint,
|
|
is_external=is_external,
|
|
name=name,
|
|
resource_session_id=resource_session_id,
|
|
managed_by=managed_by,
|
|
)
|
|
_web_cdp_browser_meta_by_owner[owner_key] = browser
|
|
return browser
|
|
|
|
|
|
def clear_connected_cdp_browser(owner_key: str) -> None:
|
|
_web_cdp_browser_meta_by_owner.pop(owner_key, None)
|
|
|
|
|
|
def clear_connected_cdp_browser_for_request(request: Request | None) -> None:
|
|
clear_connected_cdp_browser(browser_owner_key(request))
|
|
|
|
|
|
def is_cdp_endpoint_available(endpoint: str) -> bool:
|
|
_, host, port = normalize_cdp_url(endpoint)
|
|
if is_local_cdp_host(host):
|
|
return _is_cdp_available(port)
|
|
|
|
return is_cdp_url_available(endpoint)
|
|
|
|
|
|
def list_connected_cdp_browsers(owner_key: str) -> list[dict[str, Any]]:
|
|
meta = _web_cdp_browser_meta_by_owner.get(owner_key)
|
|
endpoint = get_connected_cdp_endpoint(owner_key)
|
|
if endpoint is None:
|
|
return []
|
|
|
|
if not is_cdp_endpoint_available(endpoint):
|
|
if meta and meta.get("endpoint") == endpoint:
|
|
clear_connected_cdp_browser(owner_key)
|
|
return []
|
|
|
|
if meta and meta.get("endpoint") == endpoint:
|
|
return [meta]
|
|
|
|
return [build_web_cdp_browser(endpoint, is_external=True)]
|