""" Browser Use Custom Component для Langflow Интеграция с browserless + OpenRouter Основано на документации из Context7 """ import os from typing import Optional, Dict, Any, List from langflow.custom import Component from langflow.inputs import SecretStrInput, StrInput, DictInput from langflow.template import Output class BrowserUseComponent(Component): """ Browser Use компонент с интеграцией browserless + OpenRouter Подключение к browserless через CDP URL. Использует OpenRouter API для LLM. """ display_name = "Browser Use" description = "browser-use с browserless + OpenRouter" icon = "Globe" inputs = [ SecretStrInput( name="browserless_url", display_name="Browserless URL", value=os.getenv("BROWSERLESS_API_URL", "http://browserless.home"), required=True, helper_text="CDP URL browserless сервера", ), StrInput( name="task", display_name="Задача", required=True, placeholder="Например: найди информацию о...", ), StrInput( name="model", display_name="OpenRouter Модель", value="arcee-ai/trinity-large-preview:free", advanced=True, helper_text="Модель: anthropic/claude-3-opus, openai/gpt-4o, google/gemini-pro и др.", ), SecretStrInput( name="openrouter_api_key", display_name="OpenRouter API Key", value=os.getenv("OPENROUTER_API_KEY", ""), required=True, ), ] outputs = [ Output(name="result", display_name="Результат", method="run_browser"), ] def run_browser(self) -> str: """ Запускает browser-use агент с browserless + OpenRouter """ try: from browser_use import Agent, Browser from langchain_openai import ChatOpenAI # URL browserless browserless_url = self.browserless_url # Формируем WebSocket URL для browserless cdp_url = browserless_url.replace("http://", "ws://").replace("https://", "wss://") cdp_url = f"{cdp_url}/playwright" # Конфигурация браузера с CDP подключением browser = Browser( cdp_url=cdp_url, headless=True, ) # Инициализация LLM через OpenRouter api_key = self.openrouter_api_key or os.getenv("OPENROUTER_API_KEY") llm = ChatOpenAI( model=self.model, api_key=api_key, base_url="https://openrouter.ai/api/v1", default_headers={ "HTTP-Referer": "http://langflow.home", "X-Title": "Langflow", }, ) # Создание агента agent = Agent( task=self.task, llm=llm, browser=browser, ) # Запуск агента result = agent.run() return str(result) except ImportError as e: return f"Ошибка импорта: {e}. Убедитесь, что browser-use установлен." except Exception as e: return f"Ошибка выполнения: {e}" class BrowserUsePlaywrightComponent(Component): """ Альтернативный компонент - Playwright напрямую с browserless """ display_name = "Browser Use (Playwright)" description = "Playwright напрямую с browserless" icon = "Globe" inputs = [ SecretStrInput( name="browserless_url", display_name="Browserless URL", value=os.getenv("BROWSERLESS_API_URL", "http://browserless.home"), required=True, ), StrInput( name="url", display_name="URL", required=True, placeholder="https://example.com", ), StrInput( name="action", display_name="Действие", value="navigate", advanced=True, options=["navigate", "click", "fill", "screenshot", "get_content"], ), StrInput( name="selector", display_name="CSS Selector", advanced=True, ), StrInput( name="fill_text", display_name="Текст для заполнения", advanced=True, ), ] outputs = [ Output(name="result", display_name="Результат", method="run_playwright"), ] async def run_playwright(self) -> Dict[str, Any]: """Запускает Playwright с browserless""" from playwright.async_api import async_playwright browserless_url = self.browserless_url ws_endpoint = browserless_url.replace("http://", "ws://").replace("https://", "wss://") ws_endpoint = f"{ws_endpoint}/playwright?launch=%s" % str({"headless": True}) async with async_playwright() as p: try: browser = await p.chromium.connect_over_cdp(ws_endpoint) page = await browser.new_page() try: if self.action == "navigate": await page.goto(self.url) content = await page.content() return {"status": "success", "content": content[:5000]} elif self.action == "click": await page.click(self.selector or "body") return {"status": "success", "action": "clicked"} elif self.action == "fill": await page.fill(self.selector or "body", self.fill_text or "") return {"status": "success", "action": "filled"} elif self.action == "screenshot": await page.goto(self.url) screenshot_bytes = await page.screenshot() import base64 return {"status": "success", "screenshot": base64.b64encode(screenshot_bytes).decode()} elif self.action == "get_content": await page.goto(self.url) content = await page.content() return {"status": "success", "content": content} finally: await page.close() await browser.close() except Exception as e: return {"status": "error", "message": str(e)} class SimpleBrowserAgentComponent(Component): """ Простой browser-use агент с OpenRouter (локальный браузер) """ display_name = "Simple Browser Agent + OpenRouter" description = "browser-use агент с OpenRouter (локальный браузер)" icon = "Globe" inputs = [ StrInput( name="task", display_name="Задача", required=True, ), StrInput( name="model", display_name="Модель", value="arcee-ai/trinity-large-preview:free", advanced=True, ), SecretStrInput( name="openrouter_api_key", display_name="OpenRouter API Key", value=os.getenv("OPENROUTER_API_KEY", ""), required=True, ), ] outputs = [ Output(name="result", display_name="Результат", method="run_agent"), ] def run_agent(self) -> str: try: from browser_use import Agent, Browser from langchain_openai import ChatOpenAI # Локальный браузер browser = Browser(headless=True) api_key = self.openrouter_api_key or os.getenv("OPENROUTER_API_KEY") llm = ChatOpenAI( model=self.model, api_key=api_key, base_url="https://openrouter.ai/api/v1", default_headers={ "HTTP-Referer": "http://langflow.home", "X-Title": "Langflow", }, ) agent = Agent(task=self.task, llm=llm, browser=browser) result = agent.run() return str(result) except Exception as e: return f"Ошибка: {e}"