dsh-yandex-browser
Русский | English
Плагин для DeepSeek Harness: поднимает Яндекс Браузер с постоянным профилем и отладочным портом, чтобы агент мог работать в твоём настоящем браузере - вместе с авторизациями, которые ты в него входишь, - и даёт модели прямые инструменты для страниц.
Зачем он нужен
Агент в браузере обычно работает в одноразовом профиле: каждый запуск - чистый браузер без вкладок, расширений и cookies. Отсюда неудобства: нельзя открыть почту, нельзя зайти в личный кабинет, нельзя пользоваться расширениями.
Плагин решает ровно это: у браузера агента один постоянный профиль
(%USERPROFILE%\.dsh\browsers\yandex). Ты один раз входишь в аккаунты руками -
дальше сессии живут, и агент ими пользуется.
Как это устроено
Яндекс Браузер - это Chromium, поэтому он умеет открывать локальный порт отладки (Chrome DevTools Protocol). Через него внешняя программа видит вкладки, открывает новые и выполняет JavaScript внутри страницы. Плагин делает три вещи:
DSH GUI -> композиция
|-- yandex_browser: поднимает браузер на порту 9222 и следит за ним
|-- yandex_page: читает страницу (текст, элементы, eval, скриншот)
|-- yandex_act: действует на странице (переход, клик, ввод, вкладки)
`-- MCP yandex (необязательно): Playwright с теми же 25 инструментами
Плагин не зависит от MCP: yandex_page и yandex_act говорят с браузером
напрямую по тому же порту. Нужен именно этот слой, когда MCP-клиент не может
подключиться - он делал это и раньше, и падал по таймауту.
Инструменты
yandex_browser - жизненный цикл
| Действие | Что делает |
|---|---|
status |
Браузер запущен или нет, версия, адрес эндпоинта, путь профиля, открытые вкладки |
start |
Запустить браузер с профилем агента и портом отладки (если уже запущен - ничего не делает) |
open |
Открыть URL в новой вкладке; если браузер не запущен - сначала запустит |
login |
Открыть страницу входа (по умолчанию Яндекс Паспорт), чтобы ты сам ввёл пароль |
tabs |
Список открытых вкладок |
close |
Закрыть браузер; сохранённые входы остаются в профиле |
yandex_page - чтение
| Действие | Что делает |
|---|---|
text |
Текст страницы плюс список интерактивных элементов с подписями |
eval |
Выполнить произвольное JavaScript-выражение и вернуть значение |
screenshot |
Сохранить PNG (по умолчанию видна только область экрана, параметр fullPage берёт всю страницу) |
tabs |
Вкладки с их id; у вкладок, созданных плагином, стоит отметка |
text отдаёт не только innerText, но и подписи элементов из aria-label,
title и placeholder. Это то, что делает читаемым интерфейс на веб-компонентах:
у Google Диска, например, строки файлов живут в кастомных элементах, и в обычном
тексте страницы их нет.
yandex_act - действия
| Действие | Что делает |
|---|---|
navigate |
Перейти по URL в текущей или новой вкладке |
click |
Кликнуть элемент, найденный по CSS-селектору или по видимому тексту |
type |
Ввести текст в поле (очищает поле, работает с React-формами), опционально отправить Enter |
key |
Нажать клавишу (Enter, Tab, Escape, стрелки, PageUp/PageDown) |
activate |
Показать вкладку пользователю |
close |
Закрыть одну вкладку |
close_created |
Закрыть все вкладки, которые открыл этот плагин |
wait |
Ждать появления элемента по селектору или тексту |
Типичный сценарий: status -> open -> text (понять, что на странице) ->
click / type -> close.
Пароли агент никогда не вводит. Для входа в аккаунт он зовёт login, а ты вводишь
данные в видимом окне браузера.
Правило про вкладки
Вкладка, открытая агентом, - это мусор, если её оставить. Поэтому плагин помнит
id всех вкладок, которые открыл сам (agent-tabs.json в профиле, переживает
перезапуск DSH), и умеет закрывать их одной командой:
yandex_act action: "close_created" # закроет всё, что открыл плагин
Твои рабочие вкладки плагин не трогает: закрыть можно только по явному id,
который вернул yandex_page action: "tabs" или yandex_act.
Установка
dsh plugin --profile web add github:DmitPerson42/dsh-yandex-browser
Плагин ставится как обычный bundle: пакет объявляет dsh.bundle.patch, а лежащий
рядом cordis.patch.yml добавляет его в профиль. Перезапусти DSH GUI - и всё.
Тем же способом он ставится кнопкой из маркета плагинов
(dsh plugin --profile web add dshmarket), когда плагин появится в каталоге.
Установка вручную, без CLI
git clone https://github.com/DmitPerson42/dsh-yandex-browser
pwsh -File .\dsh-yandex-browser\install.ps1
Скрипт копирует плагин в ~\.dsh\plugins\dsh-yandex-browser (без зависимостей,
только встроенные модули Node) и печатает, что нужно добавить в
~\.dsh\profiles\web\cordis.patch.yml:
- insert:
- id: yandex-browser
name: "file:///C:/Users/Druli/.dsh/plugins/dsh-yandex-browser/lib/index.js"
config:
autoStart: true
После правки конфигурации перезапусти DSH GUI.
Важно: исправление MCP-клиента
Тот же cordis.patch.yml содержит MCP-сервер yandex. В исходной конфигурации
адрес передавался позиционным аргументом:
args: ["-y", "@playwright/mcp@latest", "http://127.0.0.1:9222"] # так не работает
Актуальная версия Playwright MCP такого аргумента не принимает и падает с
too many arguments. Expected 0 arguments but got 1, из-за чего сервер всегда
висел в статусе disconnected. Нужен явный флаг:
args:
- "-y"
- "@playwright/mcp@latest"
- "--cdp-endpoint"
- "http://localhost:9222"
Здесь два момента, оба проверены на практике.
Адрес пишется литералом. Синтаксис !!js в patch-записях не вычисляется:
MCP-сервер получал строку process.env.YANDEX_CDP ?? 'http://localhost:9222' и
падал с Invalid URL. Меняешь порт - правь эту строку и port плагина
одновременно.
Именно localhost, а не 127.0.0.1. Браузер поднимает сокет отладки то на
IPv4, то только на IPv6 - на этой машине он один раз слушался на [::1], и запрос
к 127.0.0.1 его не видел. localhost в Node перебирает оба стека. Плагин
делает то же самое: пробует оба адреса и в ответе показывает тот, который
реально отвечает.
Вход в аккаунты - один раз
- Запусти DSH с плагином: браузер поднимется сам (
autoStart: true). - Попроси агента: «открой страницу входа в Яндекс» - или вызови
yandex_browserсaction: "login". - В окне браузера войди в аккаунты вручную. Поставь галочку «Запомнить меня» и, если предлагается, «Выходить на всех устройствах» - не надо, пароль хранится в профиле.
- Готово. Сессии лежат в профиле агента и работают при каждом следующем запуске.
Полезно один раз зайти и в расширения, которые хочешь иметь в браузере агента: расширения ставятся в профиль и переживают перезапуски.
Настройки
| Поле | По умолчанию | Смысл |
|---|---|---|
autoStart |
true |
Поднимать браузер при загрузке плагина, чтобы MCP-клиент сразу нашёл живой эндпоинт |
cdpEndpoint |
YANDEX_CDP или http://localhost:9222 |
Адрес DevTools |
profileDir |
YANDEX_BROWSER_PROFILE или ~\.dsh\browsers\yandex |
Постоянный профиль |
executable |
YANDEX_BROWSER_PATH или автопоиск |
Путь к browser.exe |
port |
YANDEX_BROWSER_PORT или порт из эндпоинта |
Порт отладки |
screenshotDir |
~\.dsh\browser-shots |
Куда складывать скриншоты без явного file |
tabStateFile |
<profileDir>\agent-tabs.json |
Память вкладок, созданных плагином |
Порт и профиль связаны с MCP-клиентом: меняешь YANDEX_CDP - меняются оба.
Проверка
node .\test\smoke.mjs # только status, браузер не запускается
node .\test\smoke.mjs --launch # start + open + tabs
node .\test\check-login.mjs # вошёл ли пользователь в аккаунт
node .\test\mcp-check.mjs # поднимает MCP поверх живого браузера и печатает инструменты
node .\test\page-tools.mjs # низкоуровневый прогон CDP: вкладка, текст, eval, скриншот
node .\test\tools.mjs # все три инструмента на локальной странице-фикстуре
node .\test\close-test-browsers.mjs # закрыть тестовые экземпляры: порты в аргументах
tools.mjs - главный тест: он загружает плагин с поддельным реестром инструментов,
открывает test/fixtures/page.html в новой вкладке, читает страницу, вводит
текст, нажимает кнопки по подписи и по aria-label, снимает скриншот и закрывает
вкладку. Запуск без DSH не нужен - достаточно запущенного браузера агента.
check-login не полагается на редиректы: он читает имя аккаунта из куки
yandex_login, наличие Session_id и открывает passport.yandex.ru/profile -
если форма входа не появилась, сессия живая. Значения остальных кук не читаются.
Если что-то пошло не так
Страница в фоне не отвечает. Chromium замораживает фоновые вкладки, а
замороженная вкладка не отвечает ни на один Runtime.evaluate - выглядит это
как мёртвая страница. Плагин решает это сам: каждая сессия начинается с
Page.bringToFront. Побочный эффект - вкладка, с которой работает агент,
всплывает наверх. Это заметно, но иначе фоновые страницы читать нельзя.
Порт 9222 уже занят другим браузером - плагин скажет, кем именно. Закрой его
или перенеси порт через YANDEX_CDP (не забудь про YANDEX_BROWSER_PORT, чтобы
плагин и MCP смотрели на один адрес).
Первый запуск дольше минуты - холодный профиль один раз создаёт свои
компоненты (AsrSubtitles, component_crx_cache и прочее) и показывает
приветственную страницу. Плагин ждёт до 60 секунд; следующие запуски занимают
пару секунд.
MCP server is disconnected - клиент не дождался браузера и исчерпал попытки
переподключения. Запусти браузер через yandex_browser action: "start" и
перезапусти сессию DSH. На yandex_page и yandex_act это не влияет - они
подключаются на каждый вызов заново.
Браузер не стартует, профиль пустой - начиная с Chromium 136 ключ
--remote-debugging-port игнорируется для основного профиля. Плагин всегда
запускает браузер с отдельным --user-data-dir; менять это нельзя, иначе порт не
откроется.
Второй экземпляр не поднимается - если уже открыт Яндекс Браузер с твоим обычным профилем, агент всё равно запускает отдельный экземпляр со своим профилем. Оба могут работать одновременно; порт при этом занимает только экземпляр агента.
Песочница - в режиме workspace-write плагин не сможет создать профиль за
пределами рабочей папки. В DSH плагин работает в хост-процессе, поэтому штатной
этой проблемы нет; ограничение касается только запуска тестов из песочницы
(tools.mjs в этом случае пишет скриншоты во временный каталог и предупреждает
о неудачной записи списка вкладок - на результат теста это не влияет).
Как устроен код
| Файл | Смысл |
|---|---|
lib/index.js |
Три инструмента, жизненный цикл браузера, учёт вкладок |
lib/cdp.js |
Низкоуровневый клиент CDP: HTTP-эндпоинт, WebSocket-сессия вкладки, скрипты чтения страницы |
test/*.mjs |
Прогоны без DSH: смоук, логин, MCP, CDP, все инструменты |
install.ps1 |
Копирование плагина в профиль и подсказка для cordis.patch.yml |
Сессии CDP короткоживущие: на одну операцию - один WebSocket, который сразу закрывается. Так нечему протекать, и такой сеанс переживает вкладку, которую закрыли или перезагрузили посреди работы.
Лицензия
MIT.
No comments yet. Be the first to write one.