DmitPerson42/dsh-yandex-browser ↗★ 0

dsh-yandex-browser

运行带持久配置文件的浏览器并提供网页控制工具 适合需要智能体在保留用户登录状态的真实浏览器中执行网页任务的用户。

包名
dsh-yandex-browser
兼容性
待验证
版本
2.0.0
许可证
MIT
最近更新
2026年10月3日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:DmitPerson42/dsh-yandex-browser

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 перебирает оба стека. Плагин делает то же самое: пробует оба адреса и в ответе показывает тот, который реально отвечает.

Вход в аккаунты - один раз

  1. Запусти DSH с плагином: браузер поднимется сам (autoStart: true).
  2. Попроси агента: «открой страницу входа в Яндекс» - или вызови yandex_browser с action: "login".
  3. В окне браузера войди в аккаунты вручную. Поставь галочку «Запомнить меня» и, если предлагается, «Выходить на всех устройствах» - не надо, пароль хранится в профиле.
  4. Готово. Сессии лежат в профиле агента и работают при каждом следующем запуске.

Полезно один раз зайти и в расширения, которые хочешь иметь в браузере агента: расширения ставятся в профиль и переживают перезапуски.

Настройки

ПолеПо умолчаниюСмысл
autoStarttrueПоднимать браузер при загрузке плагина, чтобы MCP-клиент сразу нашёл живой эндпоинт
cdpEndpointYANDEX_CDP или http://localhost:9222Адрес DevTools
profileDirYANDEX_BROWSER_PROFILE или ~\.dsh\browsers\yandexПостоянный профиль
executableYANDEX_BROWSER_PATH или автопоискПуть к browser.exe
portYANDEX_BROWSER_PORT или порт из эндпоинтаПорт отладки
screenshotDir~\.dsh\browser-shotsКуда складывать скриншоты без явного file
tabStateFile`
\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.