dsh-restart
Перезапуск DeepSeek Harness из интерфейса или инструментом агента — с возможностью продолжить ту же сессию после старта.
Что делает
| Возможность | Где |
|---|---|
| Кнопка «Перезапустить» | футер сайдбара, рядом с аккаунтом (иконка питания) |
| Та же кнопка у поля ввода | conversation.input.dock |
| Подтверждение | модалка с двумя кнопками, без лишних опций |
| Инструмент агента | dsh_restart({ fake }) |
| Продолжение сессии | рестарт всегда открывает сессию и пишет [auto.continue] |
Как работает рестарт
Перезапускающий процесс не может быть потомком приложения: taskkill /T убивает всё
дерево вместе с ним. Поэтому плагин:
- пишет маркер
%LOCALAPPDATA%\dsh-restart\pending.json; - создаёт одноразовую задачу планировщика
DSH-Restart(Windows) с helper-скриптом; - helper ждёт 1.5 с, закрывает дерево процесса приложения, ждёт 1.8 с, запускает
.exeи удаляет задачу.
На macOS/Linux используется отдельный sh-процесс (kill + open/запуск).
Автопродолжение
После старта клиент читает маркер через локальный мост 127.0.0.1:49233:
GET /claim → { marker } — атомарно: маркер получает только один клиент
POST /restart → записать маркер и перезапустить
Маркер забирает ровно одна загрузка страницы, поэтому двойная инициализация не даёт
двух сообщений. Любой рестарт — из модалки или инструментом — возвращает сессию
сообщением [auto.continue]: клиент открывает ту же сессию, дожидается готовности
композера, вставляет текст и отправляет его кнопкой отправки (Enter — запасной вариант).
Черновик пользователя не теряется: если в поле уже есть текст, он временно
откладывается в localStorage, отправляется [auto.continue], после чего текст
возвращается в поле ввода (без отправки). Очередь сообщений — состояние сессии,
плагин её не читает и не меняет.
Инструмент
dsh_restart { fake: true }
→ Preflight passed; fake restart requested, nothing was restarted.
Без fake инструмент перезапускает приложение и возвращает сессию сообщением
[auto.continue]. Флаг fake прогоняет все проверки, но ничего не перезапускает —
для тестов.
Настройки плагина
На странице Plugins → Restart → Configure:
| Настройка | По умолчанию | Что делает |
|---|---|---|
Команда dsh_restart доступна агенту |
включено | при выключении инструмент исчезает; вызов из старой памяти падает с unknown tool "dsh_restart" |
| Сторож активен | включено | при выключении рестарт просто закрывает и открывает приложение, без отката профиля |
| Ожидание сторожа, сек | 10 | сколько ждать признака живого старта перед откатом (1–120) |
Переопределения хранятся в %LOCALAPPDATA%\dsh-restart\settings.json; значения из
cordis.patch.yml остаются умолчаниями. Сохранение настроек не требует перезапуска:
инструмент регистрируется и снимается на лету.
Когда инструмент отказывает
dsh_restart доступен агенту только в «тихом» режиме — когда перезапуск никому не помешает:
| Проверка | Отказ |
|---|---|
| Режим доступа не Full access | dsh_restart requires the Full access permission preset (current: …) |
| Другая сессия или подагент ещё работает | dsh_restart refused: N other session(s) or subagent(s) are still working (…) |
| Есть работающая фоновая задача | dsh_restart refused: N background job(s) are still running (…) |
Проверки идут через ctx.permissionPresets.current(agent.session), ctx.agents.list()
и ctx.jobs.list(agentId); статус «работает» — running либо непустая очередь входа агента.
Кнопка в интерфейсе эти проверки не выполняет: пользователь сам решает, когда перезапускать.
Ограничения
- пункт в трее и в нативном меню Application плагином добавить нельзя: трей и меню живут в процессе Electron main, а плагин — в дочернем host-процессе;
- перезапуск выполняется через Планировщик задач Windows; если политика запрещает создание задач, рестарт не сработает;
- воркспейс-сессии, которые в этот момент выполняют ход, будут прерваны (как и предупреждает модалка).
Кнопка и инструмент ведут себя по-разному
dsh_restart(агент) — всегда открывает сессию и пишет[auto.continue](или[auto.continue.failed], если сторож откатил профиль).- Кнопка «Restart DeepSeek Harness» в сайдбаре — просто перезапускает приложение: маркер не создаётся, сессия не продолжается, авто-сообщение не отправляется.
Куки и «Web authentication failed»
Каждый запуск Desktop Host занимает новый порт и ставит куку dsh-auth-<random>
для 127.0.0.1. Chromium хранит куки по хосту, а не по порту, поэтому старые куки
не заменяются и копятся. Примерно после 70 запусков заголовок Cookie перестаёт
влезать в лимит 16 КБ, приветственный запрос получает 431, и приложение падает
с desktop welcome: Web authentication failed.
Перед каждым запуском (после убийства приложения, до Start-Process) helper
запускает src/cookie-clean.py и удаляет только строки dsh-auth-* для
127.0.0.1/localhost. Остальные куки не трогаются.
Если приложение всё же упало именно на приветствии (лог падения содержит
Web authentication failed), сторож не откатывает профиль и не отключает
плагины: он чистит куки, запускает приложение ещё раз и ждёт здорового старта.
Привязка сторожа к рестарту
Каждый рестарт получает токен:
dsh_restart → marker { token, sessionId } + watchdog.json { token }
сторож → перед откатом сверяет токен в watchdog.json
старт → хост удаляет watchdog.json (токен аннулирован)
Поэтому сторож срабатывает только для того рестарта, который его запустил, и не может тронуть приложение, поднятое позже или другим рестартом.
Перед откатом сторож сравнивает SHA-256 файлов package.json, cordis.patch.yml,
cordis.yml с сохранёнными в момент запроса. Если файлы изменились вручную, откат
не выполняется — считается, что правки взял на себя человек.
Файлы профиля пишутся без BOM (WriteAllText + UTF8Encoding(false)), иначе хост
не может прочитать package.json.
Известное ограничение: задача подагента после его завершения
Если подагент запустил фоновую задачу и завершил ход, DSH удаляет запись об этой задаче вместе с агентом, хотя сама задача продолжает работать. Проверка перед рестартом такую задачу не увидит и рестарт не отклонит.
Что покрыто:
| Владелец работы | Отказ |
|---|---|
| Своя фоновая задача | да |
| Подагент или чужая сессия ещё работают | да |
| Их задачи, пока владелец жив | да |
| Задача подагента после завершения его хода | нет |
Почему так: реестр задач ctx.jobs ключуется по id агента и очищается при его
уничтожении; обёртка jobs.start видит только задачи, запущенные через этот путь, а
подагент запускает их иначе. Детект по дочерним процессам ненадёжен: рядом постоянно
появляются и исчезают служебные процессы приложения. Решение отложено.
Установка
npx --yes github:machine202502/dsh-restart
Или вручную:
"dsh-restart": "github:machine202502/dsh-restart#main"
и добавить dsh-restart в dsh.profile.bundles.
После установки нужен перезапуск приложения (можно кнопкой, когда она появится).
Проверка
node tests/smoke.mjs # инструмент, проверки, fake, мост
node tests/load-client.mjs client.js # клиентский модуль грузится и отдаёт apply
Лицензия
MIT
No comments yet. Be the first to write one.