opus_ctrl+v enable
This commit is contained in:
1 parent
f6f4ba4067
commit
d379c19b8c
1 file changed
+108
-9
@@ -7,7 +7,7 @@ import asyncio
|
||||
from typing import Optional
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from browser_use import Agent, Browser, BrowserProfile, ChatOpenAI
|
||||
from browser_use import Agent, Browser, BrowserProfile, ChatOpenAI, ActionResult
|
||||
from browser_use.agent.views import AgentHistoryList
|
||||
import uvicorn
|
||||
from fastapi.responses import HTMLResponse
|
||||
@@ -27,6 +27,99 @@ import logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Создаём Tools с кастомными действиями
|
||||
try:
|
||||
from browser_use import Tools, BrowserSession
|
||||
|
||||
custom_tools = Tools()
|
||||
|
||||
@custom_tools.action(description='Paste text from clipboard into the currently focused element using Ctrl+V. Use this instead of regular typing when a website requires a paste event to trigger special behavior (e.g., URL preview generation, link formatting). Parameters: text - the text to paste, index - optional index of element to click/focus first.')
|
||||
async def paste_text(text: str, index: int = None, browser_session: BrowserSession = None):
|
||||
"""Вставляет текст через Ctrl+V (эмуляция вставки из буфера обмена)"""
|
||||
import json as json_util
|
||||
try:
|
||||
page = await browser_session.get_current_page()
|
||||
|
||||
# Если указан индекс элемента — кликаем на него для фокуса
|
||||
if index is not None:
|
||||
dom_element = await browser_session.get_dom_element_by_index(index)
|
||||
if dom_element:
|
||||
await browser_session.click_element_node(dom_element)
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
# Экранируем текст для безопасной вставки в JS
|
||||
safe_text = json_util.dumps(text)
|
||||
|
||||
# Записываем текст в буфер обмена через JavaScript
|
||||
await page.evaluate(f'''() => {{
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = {safe_text};
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-9999px';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
}}''')
|
||||
|
||||
# Также пробуем через Clipboard API
|
||||
try:
|
||||
await page.evaluate(f'''async () => {{
|
||||
await navigator.clipboard.writeText({safe_text});
|
||||
}}''')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Нажимаем Ctrl+V для вставки
|
||||
await page.keyboard.down('Control')
|
||||
await page.keyboard.press('v')
|
||||
await page.keyboard.up('Control')
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
return ActionResult(
|
||||
extracted_content=f"Text pasted successfully: {text[:100]}...",
|
||||
include_in_memory=True
|
||||
)
|
||||
except Exception as e:
|
||||
# Fallback: эмулируем paste event через JavaScript
|
||||
try:
|
||||
page = await browser_session.get_current_page()
|
||||
safe_text = json_util.dumps(text)
|
||||
await page.evaluate(f'''() => {{
|
||||
const el = document.activeElement;
|
||||
if (el) {{
|
||||
const clipboardData = new DataTransfer();
|
||||
clipboardData.setData('text/plain', {safe_text});
|
||||
const pasteEvent = new ClipboardEvent('paste', {{
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clipboardData: clipboardData
|
||||
}});
|
||||
el.dispatchEvent(pasteEvent);
|
||||
|
||||
if ('value' in el) {{
|
||||
el.value = {safe_text};
|
||||
el.dispatchEvent(new Event('input', {{ bubbles: true }}));
|
||||
el.dispatchEvent(new Event('change', {{ bubbles: true }}));
|
||||
}} else if (el.isContentEditable) {{
|
||||
document.execCommand('insertText', false, {safe_text});
|
||||
}}
|
||||
}}
|
||||
}}''')
|
||||
return ActionResult(
|
||||
extracted_content=f"Text pasted via fallback: {text[:100]}...",
|
||||
include_in_memory=True
|
||||
)
|
||||
except Exception as e2:
|
||||
return ActionResult(error=f"Failed to paste text: {e2}")
|
||||
|
||||
logger.info("Custom tools (paste_text) registered successfully")
|
||||
except ImportError as e:
|
||||
custom_tools = None
|
||||
logger.warning(f"Could not import Tools/BrowserSession from browser_use: {e}. Custom tools disabled.")
|
||||
|
||||
|
||||
def patch_chrome_binary():
|
||||
"""Патчит бинарный файл Chrome для удаления строки cdc_, которую ищут антифроды"""
|
||||
possible_paths = [
|
||||
@@ -224,9 +317,11 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
existing_prefs['safebrowsing'] = {}
|
||||
existing_prefs['safebrowsing']['enabled'] = False
|
||||
|
||||
# Разрешаем cookies для всех сайтов
|
||||
existing_prefs['profile']['default_content_setting_values'] = existing_prefs.get('profile', {}).get('default_content_setting_values', {})
|
||||
# Разрешаем cookies и clipboard для всех сайтов
|
||||
if 'default_content_setting_values' not in existing_prefs['profile']:
|
||||
existing_prefs['profile']['default_content_setting_values'] = {}
|
||||
existing_prefs['profile']['default_content_setting_values']['cookies'] = 1 # 1 = Allow
|
||||
existing_prefs['profile']['default_content_setting_values']['clipboard'] = 1 # 1 = Allow (для paste_text action)
|
||||
|
||||
# Отключаем Tracking Protection
|
||||
if 'tracking_protection' not in existing_prefs:
|
||||
@@ -413,12 +508,16 @@ async def run_browser_task(task_id: str, task: str, max_steps: int, model: str):
|
||||
logger.info("[startup] Chrome started successfully and ready for connections.")
|
||||
return
|
||||
|
||||
# Создание агента
|
||||
agent = Agent(
|
||||
task=task,
|
||||
llm=llm,
|
||||
browser=browser,
|
||||
)
|
||||
# Создание агента с кастомными действиями (paste_text и др.)
|
||||
agent_kwargs = {
|
||||
"task": task,
|
||||
"llm": llm,
|
||||
"browser": browser,
|
||||
}
|
||||
if custom_tools is not None:
|
||||
agent_kwargs["tools"] = custom_tools
|
||||
|
||||
agent = Agent(**agent_kwargs)
|
||||
|
||||
# Выполнение задачи
|
||||
history: AgentHistoryList = await agent.run(max_steps=max_steps)
|
||||
|
||||
Reference in new issue
Block a user