# dsh-browser-cdp — Видимый браузер агента (подключение через CDP)
[简体中文](README.md) | [Français](README.fr.md) | [Deutsch](README.de.md) | [Italiano](README.it.md) | [Русский](README.ru.md) | [Español](README.es.md)
> **Репозиторий**: `github.com/drscrewdriver/dsh-browser-cdp` (ранее `dsh-ego-browser`, происходит от апстрим-проекта [Fisfzy/dsh-ego-browser](https://github.com/Fisfzy/dsh-ego-browser)) | История версий: см. [CHANGELOG.md](CHANGELOG.md)
### Матрица совместимости версий
| Зависимость | Минимальная версия | Рекомендуемая версия | Примечания |
|---|---|---|---|
| **DSH** (DeepSeek Harness) | `0.2.0-rc.1` | `≥ 0.2.0-rc.1 <0.2.1-0` | Линия 0.2.0: peer-зависимости синхронно зафиксированы на `>=0.2.0-rc.1 <0.2.1-0`; хост обеспечивает обратную совместимость API плагинов (composer/`forkSession` в 0.2.0 — расширение сигнатуры, плагин лишь вызывающая сторона, правки не требуются). Декларативная поверхность настроек введена с 0.1.7 (поля Config с `.volatile()` автоматически порождают форму настроек) и сохраняется в 0.2.0. Для DSH `0.1.2-rc.1` ~ `0.1.7` используйте линию **0.17.x**, для 0.1.0-rc.x / 0.1.1-rc.x — v0.8.0 и более ранние |
| **dsh-better-sidebar** | `0.12.2` (опционально) | `≥ 0.17.1` | Без него — автоматический откат к плавающей сфере наблюдения; `< 0.12.2` работает, но перехват внешних ссылок (`urlTarget`) деградирует молча |
| **Node.js** | `22` | — | Поставляется вместе со средой harness |
**Примечания о совместимости со всеми версиями DSH**: эта версия (**с v0.18.0, линия 0.2.0**) нацелена на DSH `0.2.0-rc.1+`: относительно линии 0.1.7 (v0.17.x) — **ноль изменений кода**, только смена зависимостей/метаданных — хост 0.2.0 обратно совместим по API плагинов, а этот плагин передаёт выделения через фасад `ctx.get('conversation').input` (без вызова `submit()`, без override), то есть вне зоны воздействия изменений 0.2.0. Декларативная поверхность настроек, введённая в 0.1.7, устроена так: плагин больше не регистрирует никаких секций настроек (регистрационный API `ctx.settings` удалён из хоста); вместо этого конфигурируемые поля помечаются `.volatile()` в схеме Config, а страница настроек хоста автоматически генерирует форму; изменения volatile-полей вступают в силу «на горячую» через событие `loader/volatile-update`, без перезагрузки плагина. Ключевые API хоста (`defineTool`, `ctx.tools.register`, `ctx.subprocess.spawn`, `ctx.webServer.register`, `ctx.inject`, CJS-фабрика `ModuleLoader`, `cordis.patch.yml`) сохраняют свой вид с 0.1.2. Для DSH `0.1.2-rc.1` ~ `0.1.7` используйте линию **0.17.x**.
**Примечания о совместимости с dsh-better-sidebar**: плагин регистрирует вкладку в боковой панели и слушает внешние ссылки через сервис `ctx.betterSidebar` (получается защитно, в try-catch). Версии появления ключевых API:
| API | Использование в этом плагине | Версия появления в better-sidebar |
|---|---|---|
| `registerTab()` / `openTab()` / `ctx.betterSidebar` | Регистрация + открытие вкладки | v0.9.0+ |
| `TabDescriptor.single` | Вкладка с одним экземпляром | v0.9.0+ |
| `TabDescriptor.urlTarget` | Перехват внешних ссылок | **v0.12.2+** (ниже этой версии перехват ссылок молча не работает) |
---
**Подробности о поддержке версий DSH**: основные изменения v0.8.2 → v0.8.3: слияние 6 PR от сообщества (адаптация root/xvfb/macOS headless, совместимость с rc.1, стабильность Windows), исправление уязвимости неаутентифицированных маршрутов `/api/bcdp/*`, ошибки запуска client на хосте без dsh-better-sidebar (#29), регрессии холодного старта на Windows (ложное определение Xvfb из #22), а также добавление `runtimeArgs`/`chromeArgs` в белый список настроек шлюза. Точки адаптации: переименование рантайма client (`@deepseek-ai/dsh-client-store`), id регистрации модуля client и имя строки загрузки по имени объявленного пакета, `dsh.client.inject` объявляет только реальные строки графа модулей, `webServer` доставляется через вложенную инъекцию (опциональный сервис), синхронизация с режимом вкладки боковой панели (dsh-better-sidebar).
**Поддержка боковой панели ([dsh-better-sidebar](https://www.npmjs.com/package/dsh-better-sidebar))**: если на хосте установлен `dsh-better-sidebar` (рекомендуется ≥ v0.12.2), окно живого наблюдения регистрируется как **нативная вкладка боковой панели** — «Браузер агента» появляется в меню «+» панели, открывается по клику и закрепляется вместе с выдвижной панелью; вкладка автоматически открывается при первом вызове агентом инструмента `bcdp_*` (с v0.8.5 открытие ограничено вызывающей сессией — в мультисессионном режиме больше не всплывает в чужой сессии). Без `dsh-better-sidebar` происходит автоматический откат к режиму **плавающей сферы наблюдения** в правом нижнем углу (`#dsh-ego-fab`). Обе формы разделяют один набор возможностей: SSE-стрим в реальном времени / клики / ввод / перехват загрузок. В окне наблюдения есть и кнопка «Открыть в окне»: браузер агента, работающий headless, одним кликом заменяется на оконный вариант с тем же Profile (вкладки сохраняются) — удобно для ручного вмешательства.
**Импорт состояния входа (новое в v0.8.5)**: инструмент `bcdp_login_import` копирует cookie входа из вашего повседневного Chrome/Edge/Brave в браузер агента **по доменам** (запуск настоящего бинарника в headless + чтение через прозрачный CDP, совместимость с App-Bound Encryption в Chrome 127+, без оффлайн-расшифровки; если исходный браузер запущен, перед импортом его можно корректно закрыть — окно восстановится при следующем запуске). Значения cookie не попадают ни в какие логи и выводы; перед импортом база cookie источника автоматически резервируется, при аномальной очистке восстанавливается. В сочетании с дисковым персистентным Profile по умолчанию импортированное состояние входа сохраняется между перезапусками.
**CDP-прокси браузера**: он встраивает [CitroLabs/ego-lite](https://github.com/CitroLabs/ego-lite) (Chromium для ИИ-агентов) как встроенный рантайм в DeepSeek Harness, управляет браузером с помощью **38 структурированных инструментов `bcdp_*`** и снабжён **фронтендом наблюдения в реальном времени** — пока агент в фоне работает со страницами, вы видите каждую посещаемую им страницу как прямой эфир и можете вмешаться напрямую.
**Особенность, которую мы считаем своей (self-observation)**: агент пользуется именно этим Chromium — даже когда он управляет **самим DSH** (сессиями, доской задач, настройками), окно наблюдения показывает это в прямом эфире, и вы в любой момент можете перехватить управление. Дело не только в том, чтобы «видеть, как агент работает в вебе»: даже работа агента с интерфейсом DSH полностью видима и контролируема.
**Готово к работе из коробки**: пакет плагина несёт в себе рантайм ego (`runtime/`, MIT, см. [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)) — не нужно клонировать официальный репозиторий и собирать вручную; обёртка `--no-sandbox` идёт в комплекте: root / Docker / машины без дисплея запускаются в один шаг.
---
## Наши настоящие преимущества (не лозунги, а способности, проверяемые по коду и в сравнении с конкурентами)
Другие плагины, подключающие ego-lite к DSH, делают из него лишь **3 инструмента** — скрипт `run`, справочник `help`, проверку `status` — и браузер остаётся **фоновым чёрным ящиком**. Этот плагин идёт другим путём: **открыть чёрный ящик и с самого начала в полной мере дать возможности «видеть» и «управлять»**.
| Способность | Этот плагин (этот репозиторий) | Аналогичный плагин (Da1dr1em/dsh-ego-browser) |
|---|---|---|
| Число структурированных инструментов | **38**, у каждого одна ответственность, детерминированный вызов | **3** (`run`/`help`/`status`) |
| Окно живого наблюдения (два бэкенда CDP JPEG / FFmpeg H.264 + панель вкладок + ящик истории) | ✅ Есть | ❌ Нет |
| **Прямое** управление настоящим браузером мышью из окна наблюдения (клики/перетаскивание/прокрутка передаются в CDP) | ✅ Есть | ❌ Нет |
| **Выбор элемента в окне наблюдения → захват и ссылка в поле ввода беседы** (структурированный блок `[CDP-PICKS]`, ручное указание цели) | ✅ Есть | ❌ Нет |
| Охрана единственного экземпляра worker + самолечение после сбоя/дублирования | ✅ Есть | ❌ Нет |
| Перехват загрузок `bcdp_download` / детекция капчи `bcdp_captcha`/`bcdp_page_info` | ✅ Есть | ❌ Нет |
| Адаптация к платформам (автоопределение Linux/macOS/Windows + откаты root/headless/`--no-sandbox`) | ✅ Все платформы | Только Windows-хост предпросмотра, ручная настройка |
| Персистентность состояния входа на диске `bcdp_auth_flush` | ✅ Есть | ⚠️ Только упоминание на уровне документации |
**Три ключевых отличия:**
- **Видно**: у других — чёрный ящик, который «в конце расскажет результат»; у нас прямой эфир — вы **смотрите, как агент работает**, и сразу замечаете, если он застрял на капче или свернул не туда.
- **Управляемо**: у других — только чтение; наше окно наблюдения **напрямую управляет** тем же браузером агента — при необходимости вы берёте управление сами (зум/перетаскивание/клик), не прерывая агента и не начиная всё заново.
- **Точное указание**: вы **выбираете** элемент страницы в окне наблюдения; плагин захватывает его `backendNodeId`/`tag`/`id` и семантическое описание и вставляет структурированным блоком `[CDP-PICKS]` в черновик поля ввода беседы (несколько выборов на одной странице автоматически объединяются и нумеруются) — агент получает точную цель, не догадываясь, «какая из кнопок имеется в виду».
> Приведённое сравнение опирается на публично проверяемые факты: код этого репозитория (`bin/cdp-cast-worker.mjs` — стрим в реальном времени + обратная передача ввода через CDP, `lib/index.js` — 38 зарегистрированных инструментов, `lib/cast-server.js` — мост к хосту, `deliverPickToConversation` в `lib/client.js` — ссылки выборов) и исходный код/README аналогичного плагина (чей `src/tools.ts` регистрирует только `ego_browser_run` / `ego_browser_help` / `ego_browser_status`). Этот документ никого не принижает — мы лишь сообщаем, какие способности мы дополнительно реализовали и проверили.
**По сравнению с самим [ego-lite](https://github.com/CitroLabs/ego-lite) мы добавили вот что (всё проверяемо по коду этого репозитория):**
| Способность | Описание (соответствующий код) |
|---|---|
| **Фронтенд наблюдения** | Сам по себе ego-lite — headless-CLI (только heredoc-скрипты + текстовый вывод); мы добавили **SSE-стрим в реальном времени + панель вкладок + ящик истории + прямое управление мышью из окна наблюдения + выбор элементов со ссылкой в поле ввода** (`bin/cdp-cast-worker.mjs`, `lib/cast-server.js`, `createPickControl`/`deliverPickToConversation` в `lib/client.js`) — «видеть», «управлять» и «указывать» стали возможностями первого класса |
| **Из коробки + самодостаточность на всех платформах** | `resolveEgoEnv` автоматически находит Chrome/Edge/Brave, встроенная обёртка `--no-sandbox`, нулевая настройка под root / Docker / без дисплея (`lib/index.js`); не нужно, как в официальном пути, сначала ставить GUI-хост |
| **Слой надёжности** | Автоматические повторы при холодном старте (повторяются только переходящие сбои CDP, настоящие ошибки не глотаются), охрана единственного экземпляра worker + автоперезапуск после сбоя, teardown плагина в режиме fire-and-forget без блокировки выхода хоста, потолок кэша кадров на фронтенде (`withWarmupRetry` / `makeEnsureWorker` / `frameCache`) |
| **Эксплуатационные инструменты** | `bcdp_doctor` (диагностика окружения), `bcdp_captcha` (детекция капчи), `bcdp_auth_flush` (персистентность входа), `bcdp_login_import` (импорт входа из системного браузера), `bcdp_http` (запросы в контексте браузера) и т.д. — слой, которого нет у нативных CLI-хелперов |
| **self-observation** | Даже когда агент управляет самим интерфейсом DSH, всё видно в прямом эфире, и управление можно перехватить |
> Мы не претендуем на равенство с околоядерными снапшотами или нативным мультиоконным опытом официального macOS-приложения; этот репозиторий решает задачу: «принести те же возможности браузера в DSH + Linux/WSL — и сделать это видимым».
---
## Какую проблему решает
Универсальные браузеры не созданы для агентов, а значительная часть веб-взаимодействий (состояния входа, капчи, динамический рендеринг, формы, сайты, требующие живой сессии) по силам только настоящему браузеру — отсюда наследие семейства ego из апстрима: **«пусть агент пользуется вашим уже залогиненным браузером, не мешая вам»** ([официальный сайт](https://github.com/CitroLabs/ego-lite)).
Этот плагин подключает его к DSH и решает самую болезненную точку — **вы не видите, что делает агент, и не можете вмешаться** — окном наблюдения:
> 🌐 Один клик по шарику открывает эфир; 🟦 панель вкладок для переключения/закрытия; 🕘 ящик истории для просмотра назад; 🔍 зум и перетаскивание; 🖱️ прямое управление настоящим браузером из окна. **Одной фразой: агент работает в браузере — вы всё видите и в любой момент можете перехватить управление.**
### Несколько типовых сценариев знакомства
- **Литература / сбор данных**: поручите агенту войти в CNKI / Google Scholar и собирать постранично; в окне наблюдения вы видите, как он прокручивает, жмёт «следующая страница», скачивает PDF — если застрянет, заметите сразу.
- **Формы и входы**: агент заполняет форму наполовину, в окне наблюдения выпадает капча — вы перехватываете, решаете капчу и возвращаете управление агенту, чтобы он продолжил.
- **QA / дымовые тесты**: попросите агента пощёлкать по вашему продукту; окно наблюдения становится «говорящей записью экрана», с бонусом — просмотром истории.
- **Наблюдать, как агент управляет самим DSH** (self-observation): когда агент управляет сессиями / правит настройки, всё видно в окне наблюдения, и вы можете вмешаться.
---
---
## Предварительные требования
| Требование | Примечания |
|---|---|
| Node ≥ 22 | Поставляется вместе со средой harness |
| **Любой Chrome / Chromium / Brave / Edge** | Автообнаружение или указание через `EGO_LINUX_CHROME`; под root — с комплектной обёрткой |
| DSH + dshx | Механизм загрузки плагинов |
| DSH Web с графическим интерфейсом (для окна наблюдения) | Headless-сессии по-прежнему могут пользоваться инструментами `bcdp_*`, просто без окна наблюдения |
## Установка
**Способ 1: прямая установка с GitHub (рекомендуется)**
```sh
dsh plugin --profile web add github:drscrewdriver/dsh-browser-cdp
# Можно также зафиксировать на конкретном commit / tag:
dsh plugin --profile web add github:drscrewdriver/dsh-browser-cdp#v0.9.0
```
> Установка через `github:` забирает tarball репозитория через pnpm, обращаясь к `codeload.github.com`, **без публикации в реестре npm**; она использует непосредственно **предварительно собранный и закоммиченный `lib/`** репозитория (`files` содержит только `lib/`, `bin/`, `runtime/`, `cordis.patch.yml`, `dsh-plugin.json`), поэтому **скрипты сборки не запускаются** и devDependencies не нужны. Вход хоста `lib/index.js`, клиент `lib/client.js` и воркер `bin/cdp-cast-worker.mjs` распространяются вместе с репозиторием.
**Способ 2: локальный tarball / git-URL**
```sh
dshx install dsh-browser-cdp # tarball или git-URL — годится и то и другое
dshx list # должно показать: [on] dsh-browser-cdp
```
> **Примечание о переименовании пакета**: имя пакета этого плагина — **`dsh-browser-cdp`** (прежние имена: `dsh-ego-browser`, псевдоним `@dsh-external/ego-browser`). Начиная с DSH Desktop 2.0.5 действует проверка согласованности «имя зависимости profile == реальное имя пакета»: если profile ссылается на старое имя, запуск уходит в режим восстановления. После обновления переименуйте **и** ключ зависимости в `package.json` профиля, **и** запись в `dsh.profile.bundles` в `dsh-browser-cdp`:
```diff
- "dsh-ego-browser": "github:Fisfzy/ego-browser",
+ "dsh-browser-cdp": "github:drscrewdriver/dsh-browser-cdp",
```
```diff
- "dsh-ego-browser",
+ "dsh-browser-cdp",
```
В настройках окна наблюдения доступны `captureBackend=auto|cdp|ffmpeg` (по умолчанию `auto`, сейчас разрешается в CDP), ступени качества, CDP FPS/качество JPEG/максимальная ширина, а также FFmpeg FPS/максимальная ширина/битрейт/кодировщик/свой путь. Плагин сначала проверяет пользовательский путь, системный PATH и управляемый кэш; загрузку с GitHub можно перенаправить, заменив `https://github.com` на `githubMirror`, например `https://gh-proxy.com/github.com`. Битрейт FFmpeg — от 500 до 20000 kbps, по умолчанию 2000/4000/8000 kbps для низкой/сбалансированной/высокой ступеней.
Никакой настройки на стороне хоста не требуется: `resolveEgoEnv` автоматически определяет root / отсутствие дисплея и применяет откаты. Маршруты хоста окна наблюдения (`/api/bcdp/spaces` и др.) регистрируются только при наличии HTTP-сервера; в headless это безопасный no-op.
## Способы подключения: CDP-эндпоинт / локальный ego CLI
Список подключений в панели настроек **упорядочен** — **порядок задаёт приоритет**, и активированный пункт управляет каждым вызовом `bcdp_*`. Есть два типа пунктов:
| Тип | Что делает | Ограничения |
|---|---|---|
| **CDP-эндпоинт** | Передаёт адрес браузера с уже открытым отладочным портом встроенному рантайму (инъекция `EGO_LINUX_CDP_URL`), который к нему **присоединяется** | Можно несколько |
| **Локальный ego CLI** | Локальный ego CLI **сам** управляет своим локальным браузером ego-lite — **никакой эндпоинт не инъецируется** | **Только локальная машина, глобально не более одного** |
**Зачем нужен второй тип**: инъецируемый `EGO_LINUX_CDP_URL` — приватный контракт **встроенного Linux-порта**; нативный `ego-browser` из приложения `ego lite` на macOS его **попросту не читает**. Если бы тип «CDP-эндпоинт» был единственным, пользователи macOS не смогли бы воспользоваться своим уже залогиненным ego-lite — пришлось бы подключаться к удалённому порту или позволить порту запустить стоковый Chromium. Тип «локальный CLI» закрывает именно эту брешь.
Порядок разрешения (если `cliPath` пуст): явный путь → `ego-browser` из PATH → хелпер внутри пакета приложения macOS (`/Applications/ego lite.app/…/Helpers/ego-browser`) → встроенный рантайм плагина.
Два значения по умолчанию, о которых стоит знать:
- **`--sdk-path` по умолчанию выключен**: по умолчанию используется harness, идущий с CLI (официально сопряжённый); лишь при включении инъецируется harness-пакет этого плагина. Если CLI не распознаёт этот флаг, плагин записывает подсказку и **автоматически повторяет попытку один раз без него** — вся цепочка из-за этого не рушится.
- **Проба готовности проходит через настоящий heredoc** (тот же канал, что и для реальной работы), поэтому она **не бесплатна**: проба может вызвать холодный старт фонового браузера (на встроенном порту замерено около 1,3 с).
Отношения с другими переключателями:
- `cdpMode`: `auto` следует активированному пункту (годятся оба типа); `remote` **принимает только CDP-эндпоинты** и при активированном локальном CLI явно сообщает `mode-kind-mismatch`; `local` идёт через управляемый локальный лаунчер.
- `remoteEnabled` (общий дистанционный выключатель) **управляет только удалённым CDP** и не влияет на подключения локального CLI.
- `allowLocalFallback` / `localHeadless` / `localUserDataDir` действуют только на откат CDP-эндпоинтов и управляемые запуски.
`bcdp_doctor` сообщает счётчик типов текущей последовательности, фактически разрешённый путь CLI и его форму, а также (если на той же машине установлен апстрим-плагин `dsh-ego-browser`) предупреждение о сосуществовании.
## Список инструментов (38, префикс `bcdp_`, полный индекс — в `bcdp_help`)
| Категория | Инструменты |
|---|---|
| Пространства задач | `bcdp_space_open` `bcdp_space_close` `bcdp_status` |
| Чтение страниц | `bcdp_snapshot` (семантическое дерево) `bcdp_page_info` `bcdp_read_element` |
| Навигация/ожидание | `bcdp_navigate` (повторно использует вкладку) `bcdp_wait` `bcdp_wait_for_selector` `bcdp_wait_for_url` `bcdp_wait_for_response` |
| Взаимодействие | `bcdp_click` `bcdp_fill` `bcdp_hover` `bcdp_drag` `bcdp_select` `bcdp_check` `bcdp_key` `bcdp_scroll` |
| Выполнение/отладка | `bcdp_js` (вычисление на странице) `bcdp_cdp` (сырой CDP) `bcdp_cli` (произвольный heredoc) `bcdp_script` (многошаговый скрипт) |
| Вывод | `bcdp_screenshot` `bcdp_download` `bcdp_upload` |
| Сессия/безопасность | `bcdp_auth_flush` (персистентность входа) `bcdp_login_import` (импорт входа между браузерами) `bcdp_captcha` `bcdp_dialog` |
| Мета-инструменты | `bcdp_help` `bcdp_doctor` `bcdp_http` |
| Ревью (JEV/Laya, опциональный внешний сервис вынесения суждений) | `bcdp_jev_status` `bcdp_jev_frame` `bcdp_jev_ask` `bcdp_jev_run` `bcdp_jev_attempt` |
## Как пользоваться окном наблюдения
**🌐 Постоянный шарик** в правом нижнем углу → клик, чтобы открыть:
- **Главный экран**: прямая трансляция текущей страницы агента; клик/перетаскивание/колесо действуют на страницу напрямую, Ctrl+колесо — зум, Ctrl+перетаскивание — панорамирование, двойной клик — сброс. После клика по экрану доступен прямой ввод с клавиатуры: китайский IME, вставка, Tab/Enter/стрелки и сочетания Ctrl/Cmd поддерживаются.
- **Выбор элемента** (ссылка выбором): нажмите кнопку на панели инструментов, чтобы войти в режим выбора, затем кликните любой элемент на живом экране — плагин захватит его `backendNodeId`/`tag`/`id` и семантическое описание и вставит структурированным блоком `[CDP-PICKS]` в черновик поля ввода беседы; несколько выборов на одной странице автоматически объединяются в один блок с последовательной нумерацией, агент точно использует их по номерам. Работает и с плавающим шариком, и с вкладкой боковой панели.
- **Панель вкладок**: горизонтальный ряд сверху, клик для переключения, `×` для закрытия.
- **Ящик истории** (🕘): просмотр следа посещений в хронологическом порядке.
- Во время действий строка URL внизу показывает подсказки на месте и восстанавливается через 2 секунды.
- После закрытия панели, скрытия вкладки sidebar или размонтирования компонента производство кадров прекращается по истечении льготных 1,5 секунды. Сам по себе уход окна DSH в фон не останавливает стрим — чтобы при возврате не пересобирать WGC/FFmpeg раз за разом; аномальное закрытие подстраховано тайм-аутом аренды worker в 120 секунд.
### Видеобэкенды
- `cdp`: JPEG через `Page.startScreencast`, по умолчанию 20 FPS. Каждый исходный кадр немедленно подтверждается (ACK) по ID кадра, предоставленному Chrome; хранится только последний ожидающий кадр; захватывается только просматриваемая вкладка, статичные страницы по умолчанию возвращаются к снимку раз в 3 секунды.
- `ffmpeg`: на Windows `gfxcapture(hwnd)` захватывает D3D11-поверхность целевого окна Chrome напрямую; другие платформы используют кроп источника отображения. Затем кодирование в H.264 fragmented MP4 → бинарные чанки HTTP → MediaSource `