"""仿真 RPA 档位:演示共享库 browser / anti_detect 用法(需浏览器,默认开发档)。""" from __future__ import annotations import asyncio import os from jiangchang_skill_core import config from jiangchang_skill_core.rpa import anti_detect, artifacts, errors, launch_persistent_browser from jiangchang_skill_core.rpa.human_login import wait_for_captcha_pass from util.constants import SKILL_SLUG from util.runtime_paths import get_skill_data_dir, get_skill_root from .base import AdapterBase, ExampleItem, ExampleResult class SimRpaAdapter(AdapterBase): name = "sim_rpa" def do_batch(self, target: str, items: list[ExampleItem]) -> ExampleResult: return asyncio.run(self._do_batch_async(target, items)) async def _do_batch_async(self, target: str, items: list[ExampleItem]) -> ExampleResult: example_path = os.path.join(get_skill_root(), ".env.example") config.ensure_env_file(SKILL_SLUG, example_path) url = config.get("TARGET_BASE_URL") or target or "https://example.com" batch_id = "sim-demo" data_dir = get_skill_data_dir() profile_dir = os.path.join(data_dir, "browser-profile") os.makedirs(profile_dir, exist_ok=True) record_video = config.get_bool("OPENCLAW_RECORD_VIDEO") video_dir = os.path.join(data_dir, "rpa-artifacts", batch_id, "video") if record_video else None if video_dir: os.makedirs(video_dir, exist_ok=True) try: from playwright.async_api import async_playwright except ImportError: return ExampleResult( ok=False, serial_no=None, error_msg="playwright not installed", artifacts={}, ) artifact_paths: dict = {} try: async with async_playwright() as pw: context = await launch_persistent_browser( pw, profile_dir=profile_dir, headless=config.get_bool("OPENCLAW_BROWSER_HEADLESS"), record_video_dir=video_dir, ) page = context.pages[0] if context.pages else await context.new_page() await page.goto(url, wait_until="domcontentloaded", timeout=60_000) await anti_detect.human_mouse_wiggle(page) # 演示拟人输入:若页面有 search 输入框则尝试输入 search = page.locator('input[type="search"], input[name="q"]').first if await search.count() > 0: demo_text = items[0].label if items else "openclaw-demo" await anti_detect.human_type(page, search, demo_text) await anti_detect.human_delay_short() if not await wait_for_captcha_pass( page, timeout_sec=config.get_int("HUMAN_WAIT_TIMEOUT", 180), ): shot = await artifacts.capture_failure(page, data_dir, batch_id, "captcha") if shot: artifact_paths["captcha"] = shot return ExampleResult( ok=False, serial_no=None, error_msg=errors.ERR_CAPTCHA_NEED_HUMAN, artifacts=artifact_paths, ) await context.close() except Exception as exc: return ExampleResult( ok=False, serial_no=None, error_msg=str(exc), artifacts=artifact_paths, ) return ExampleResult( ok=True, serial_no=f"SIM-{len(items)}", error_msg=None, artifacts={"mode": "sim_rpa", "url": url, **artifact_paths}, )