Ragnoryok1/dsh-plugin-doctor ↗★ 0
@ragnoryok1/dsh-plugin-doctor
Diagnostics for DeepSeek Harness: finds plugins that failed to load, bundles whose rows never started, version mismatches and unmanageable entries, and explains what to do 适合需要排查插件未加载、更新失败等故障并获取修复建议的用户。
Install
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:Ragnoryok1/dsh-plugin-doctorREADME
Read the full README ↗@ragnoryok1/dsh-plugin-doctor

Панель диагностики плагинов для веб-интерфейса DeepSeek Harness (dsh).
Вкладка «Диагностика» в разделе «Встроенные плагины». Показывает все плагины, которые знает работающий харнесс, и объясняет, что именно не работает: плагины, которые не загрузились (с их собственным сообщением об ошибке), строки бандлов, объявленные но так и не запущенные — след неудачного обновления, — записи, которыми нельзя управлять из интерфейса, с указанием причины, выключенные плагины и предупреждения о версиях. Для каждого раздела даётся одна подсказка, а не повторяется под каждой строкой, и панель всегда сообщает, сколько плагинов она проверила: иначе «проблем нет» неотличимо от «проверка ничего не увидела». Читает только штатные сервисы (remote.pluginManager по Remote-протоколу) и никогда — файлы или внутренности других пакетов, поэтому переживает обновления харнесса.
Что он проверяет
| Раздел | Что означает |
|---|---|
| Не загрузились | Плагин сообщил об ошибке при запуске. Показывается само сообщение. |
| Объявлены, но не запущены | Бандл объявляет строку, но живой записи у неё нет — так выглядит след неудачного обновления. |
| Не управляются из интерфейса | Запись есть, но переключить её отсюда нельзя. Указывается причина: management-required, unaddressable и другие. |
| Выключены | Отключены намеренно. |
| Предупреждения о версиях | Не смертельно, но стоит прочитать перед обновлением. |
Проблемами считаются только ошибки. Справочные разделы видны, но не делают здоровый профиль сломанным.
Как выглядит

Установка
dsh plugin --profile web add @ragnoryok1/dsh-plugin-doctor
Затем откройте Настройки → Встроенные плагины → Диагностика.
Почему это работает после обновлений
Плагин не читает чужие файлы и не лезет во внутренности пакетов. Всё, что он
показывает, приходит из штатных сервисов: плагин-менеджер отдаёт состояние
через Remote-протокол (remote.pluginManager), а ответы распаковываются из
конверта { ok, value }.
Отсюда же две особенности, которые легко сделать неправильно и которые здесь сделаны намеренно:
- ответ «проблем нет» всегда сопровождается счётчиком проверенного, иначе он неотличим от «проверка ничего не увидела»;
- справочное не считается проблемой: встроенные модули, которыми управляет сам профиль, — это норма, а не поломка.
Как это проверялось
Утверждение «находит неработающие плагины» ничего не стоит без настоящей поломки,
поэтому проверка сделана на живом харнессе с заведомо сломанным плагином:
в fixtures/canary/ лежит фикстура, чей apply() всегда падает.
| Состояние профиля | Что показала панель |
|---|---|
| канарейка установлена | «Найдена 1 проблема» → «Объявлены, но не запущены (1): doctor-canary», с модулем и советом |
| канарейка удалена | «Проблем нет: все плагины загружены и совместимы.» |
Порядок повторения — в fixtures/canary/README.md.
Отдельно стоит знать: упавшая на хосте строка не попадает в список живых
плагинов, поэтому meta.error показать некому — срабатывает проверка строк
бандлов. Обе проверки нужны, и это подтвердилось на практике.
Две половины: панель и проверка диска
Панель читает состояние плагинов через штатные сервисы — но они живут в браузере и файловой системы не видят. Отказы, которые мы раз за разом разбираем руками, лежат именно на диске, поэтому о них сообщает отдельный скрипт:
node bin/doctor-scan.mjs
# или, если пакет установлен отдельно: npx dsh-doctor
| Что ищет | Почему это важно |
|---|---|
Каталоги *.parked | отложенная копия плагина — след обхода заблокированного переименования при обновлении |
Каталоги _tmp_* | остаток неудачной установки; именно из-за него обновления падают с EPERM |
Битые ссылки file: | профиль указывает на файл, которого больше нет: установка падает с ENOENT ещё до начала |
| Отчёты о сбоях запуска | logs/startup-*.log: лаунчер сам называет плагины, которые не активировались, — с пакетом, ошибкой и числом ждущих сервисов |
Проверено на настоящем мусоре. Скрипт запускался на чистом профиле, затем на профиле с намеренно созданными остатками (нашёл оба), затем снова на чистом — замечаний нет. Попутно он нашёл и настоящий *.parked, оставшийся в профиле от обхода EPERM при обновлении плагина, — тот был убран.
Почему остатки не в панели. Чтобы показать их в интерфейсе, плагину нужен собственный remote-сервис, а имена в ctx.remote.* генерируются сборочным конвейером харнесса. Генератор (@deepseek-ai/dsh-typert-generator) опубликован, так что путь существует — но это отдельная работа, и она не выдаётся за сделанную.
Чего он не делает
- не чинит ничего сам: только сообщает;
- не отправляет данные наружу: всё считается локально.
Почему диапазон peer такой длинный
В peerDependencies стоит не короткий диапазон, а девять ветвей с явными пререлизными метками. Это не украшение: node-semver пропускает пререлизную версию, только если в диапазоне есть сравнение на том же тупле major.minor.patch, и само оно помечено пререлизом. Поэтому выглядящий широким `>=0.1.0-rc.2 lib/index.js (host half) + lib/client.js (client bundle) npm pack
`lib/client.js` собирается в формате, который понимает клиентский загрузчик `dsh`
(`__ModuleLoader__.load`), и экспортирует `inject`/`apply`. React и пакеты
харнесса остаются внешними и резолвятся загрузчиком.
## Содержимое
- `src/client/index.ts` — панель, проверки и регистрация вкладки;
- `src/client/locales.ts` — словари `ru`, `zh` и `en` для собственного интерфейса;
- `src/index.ts` — пустая host-половина (нужна как загружаемая node-точка входа);
- `cordis.patch.yml` — профиль-патч (`- insert:` клиентской строки `plugin-doctor`);
- `bin/doctor-scan.mjs` — проверка диска (остатки и битые ссылки);
- `fixtures/canary/` — фикстура-канарейка для проверки панели.
## Лицензия
MIT. Пакет сообщества, **не связан с DeepSeek**.