# 📦 @goodandready/dsh-session-control

Продвинутое управление сессиями, закрепление, полнотекстовый поиск и просмотр архивов для DeepSeek Harness

npm version license DSH Plugin Node version

Все проекты автора

🇬🇧 English • 🇨🇳 中文说明 • 🇷🇺 Русский

⭐ Если вам нравится этот плагин, поставьте ему звезду на GitHub — это покажет мне, что плагин вам полезен, и будет мотивировать меня развивать его дальше.

🐛 Если вы нашли баг или хотите предложить новый функционал, создайте issue на GitHub на любом языке — я рассмотрю ваше предложение и реализую полезные идеи в одной из следующих версий плагина.
--- ## Что плагин делает с панелью Плагин **заменяет тело боковой панели** — блок со списком рабочих папок и сессий. Остальная панель остаётся штатной: бренд, кнопка создания новой сессии, подвал и вход в настройки не затрагиваются. Замена необходима архитектурно: слот `sidebar.workspaces` объявлен ядром как `kind: "single"`, второго регистранта у него не бывает, а другого слота в теле панели нет. --- ## Архитектура и поток данных ```mermaid graph LR subgraph Browser ["Браузерный клиент (lib/client.js)"] UIW["Служба uiWorkspace\n(заместитель сервиса Cordis)"] PANEL["SessionListPanel\n(слот sidebar.workspaces)"] JUMP["Окно QuickJump\n(сочетание Alt+K)"] VIEWER["Модалка ArchiveViewer\n(просмотрщик JSONL)"] SETTINGS["SettingsCard\n(settings.plugin.item)"] end subgraph Host ["Серверная часть Node.js (lib/index.js & transcript.js)"] SERVER["Cordis WebServer\nHTTP-маршруты"] STORE["DSH Session Persistence\n(дескрипторы / логи)"] TRANS["Чистый парсер расшифровок\n(JSONL -> Markdown)"] end PANEL -->|"переключение / переименование"| UIW JUMP -->|"фильтрация и быстрый переход"| UIW VIEWER -->|"GET /dsh-session-control/transcript"| SERVER PANEL -->|"GET /dsh-session-control/titles"| SERVER PANEL -->|"GET /dsh-session-control/export-batch"| SERVER SERVER -->|"чтение логов сессии"| STORE STORE -->|"дескриптор / события"| TRANS TRANS -->|"структурированный текст / markdown"| SERVER ``` ## Сравнение со штатной панелью | Возможность | Штатная панель | С плагином `dsh-session-control` | |---|---|---| | **Закрепление диалогов** | ❌ Нет | ✅ Общая группа закреплённых сессий вверху панели | | **Раздел архива** | ❌ Не виден нигде | ✅ Отдельный раздел, разбитый по периодам | | **Чтение архивной сессии** | ❌ Невозможно | ✅ Окно расшифровки (только на чтение) | | **Результаты поиска** | ⚠️ Только заголовок строки | ✅ Заголовок + фрагмент текста с совпадением | | **Пустые сессии** | ⚠️ Вперемешку с рабочими | ✅ Скрыты автоматически (кроме текущей сессии) | | **Действия над пачкой строк** | ❌ Нет | ✅ Множественный выбор чекбоксами и диапазоны по Shift | | **Скрыть лишнее** | ❌ Только необратимый архив | ✅ Обратимое скрытие в один клик | | **Индикатор активной сессии** | ❌ Не показан | ✅ Пульсирующая точка активности в строке | | **Переименование по месту** | ⚠️ Модальный диалог | ✅ Двойной клик или клавиша F2 прямо в строке | | **Группировка поверх папок** | ❌ Невозможна: членство выводится из рабочего каталога | ✅ Свои метки, не зависящие от папок | | **Имена диалогов** | ⚠️ Имя каталога проекта у всех безымянных | ✅ Начало вашей первой фразы в этом диалоге | | **Переход с клавиатуры** | ❌ Нет | ✅ `Alt+K` — переход по активным и архивным сразу | | **Забрать содержимое** | ❌ Невозможно | ✅ Копирование и сохранение расшифровки в Markdown | > Штатные возможности — рабочие папки, поиск по содержимому диалогов, ответвление сессии — остаются на месте: плагин их переиспользует, а не переписывает. --- ## Установка Установка через CLI `dsh` для профиля `web`: ```bash dsh plugin --profile web add @goodandready/dsh-session-control ``` Перезапустите веб-профиль DeepSeek Harness для применения бандл-патча. --- ## Как вернуть штатную панель Чтобы в любой момент вернуть стандартную боковую панель: ```bash dsh plugin --profile web remove @goodandready/dsh-session-control ``` Штатный ряд `ui-workspace` немедленно включается обратно, панель возвращается к исходному виду. Настройки закреплений и скрытий сохраняются на хосте и автоматически подхватятся при повторной установке плагина. --- ## Возможности ### 📌 Закрепление сессий Нужные диалоги выносятся в отдельную группу сверху панели. Закрепления сохраняются при перезагрузке, смене браузера и переходе на другое устройство, так как настройки хранятся на хосте. ### 🔍 Поиск с контекстным фрагментом Ядро ищет по содержимому диалогов и возвращает кусок текста вокруг совпадения — плагин выводит его второй строкой под заголовком, поэтому сразу видно причину совпадения без необходимости открывать сессию. ### 🗄️ Архив по временным периодам Сессии архива разбиты на сворачиваемые группы: *Сегодня*, *На этой неделе*, *В этом месяце*, *Раньше*. Свёрнутый период не рендерится в DOM, что исключает лаги интерфейса при тысячах старых сессий. При активном поиске периоды с совпадениями раскрываются автоматически. ### 📜 Расшифровка архивной сессии Заархивированную сессию нельзя открыть в режиме беседы (ядро снимает выбор с таких сессий). Плагин предоставляет изолированное модальное окно просмотра расшифровки через маршрут `GET /dsh-session-control/transcript?session=` только на чтение. ### 🧹 Скрытие пустых сессий Сессии без сообщений непрерывно генерируются шедулерами, мессенджерами и канбан-досками. Они автоматически скрываются, сохраняя чистоту панели. Текущая активная сессия не скрывается никогда. Поведение настраивается в карточке плагина. ### 👁️ Обратимое скрытие Собственный механизм скрытия, в отличие от необратимого ядрового архива: скрытая сессия восстанавливается одним кликом. ### ☑️ Множественный выбор и пакетные операции Выбор строк чекбоксами при наведении и выбор диапазона через Shift+Click. Над выбранными строками доступны групповое скрытие, закрепление и разархивация видимости. ### 🏷️ Метки Перенести диалог в другую рабочую папку нельзя: папка — это каталог на хосте, членство выводится из рабочего каталога сессии, и ядро отвергает сессию с несовпадающим путём. Метки дают ту ось группировки, которой у папок нет: метка ставится из меню строки или сразу на выбранную пачку, а щелчок по чипу над списком оставляет в панели только её диалоги, включая архивные. Снимается там же: пункт меню так и называется — «убрать из «имя»», а не прячется за галочкой. Под включённым фильтром по метке её можно снять сразу со всей выбранной пачки. Метка, потерявшая последнюю сессию, исчезает сама. ### 🧾 Имя из первой фразы Без сохранённого названия ядро показывает имя каталога проекта, поэтому все диалоги одной папки выглядят одинаково. Плагин берёт начало первой фразы, которую вы написали в этом диалоге. Никакой модели и никаких расходов: текст уже лежит в журнале сессии. Переименование всегда главнее — как только вы назвали диалог сами, выведенное имя исчезает. Разбираются только строки, которые сейчас на экране, поэтому свёрнутые разделы не стоят ничего. ### ⌨️ Быстрый переход (`Alt+K`) Окно поверх интерфейса ищет и по названию, и по содержимому сразу. Именно `Alt`, а не `Ctrl`: `Ctrl+K` браузер оставляет себе и странице не отдаёт. Русская раскладка учтена — клавиша работает независимо от неё. Стрелки двигают выбор, `Enter` открывает, `Esc` закрывает и возвращает фокус на прежнее место. Архивный результат открывается расшифровкой — так же, как из списка. ### 🚦 Индикатор размера сессии Лента чата DSH держит в странице все события сессии сразу. В очень большой сессии долгий ход агента может намертво подвесить вкладку, а вместе с ней и все остальные вкладки DSH того же адреса. Строка теперь предупреждает заранее: **жёлтый** значок, когда сессия распухла, и **красный**, когда она уже опасна для интерфейса. На значке число событий текстом, так что смысл не держится на одном цвете, а подсказка добавляет размер журнала. Размер берётся из метаданных сессии, журнал для этого не распаковывается. Пороги по умолчанию — 1 500 и 3 000 событий, их можно поменять в карточке настроек. ### ↪️ Продолжить в новой сессии Пункт меню строки **«Продолжить в новой сессии»** открывает новый чат в той же рабочей папке и кладёт в его поле ввода **черновик**: название и папку старой сессии, ваши последние запросы и последний отчёт агента. Ничего не отправляется — вы читаете, правите и отправляете сами. Выдержка собирается мгновенно и модели не требует. **«Продолжить с пересказом моделью»** делает то же, но с итогом, написанным моделью: цель, что сделано, что осталось, договорённости и ключевые ссылки. Это тратит токены, поэтому запускается только явным нажатием и недоступно, пока в карточке настроек не указаны провайдер и модель. Гигантская сессия модели целиком не отдаётся: берётся новейшая часть в пределах заданного бюджета, и итог об этом прямо пишет. ### 📤 Выгрузка в Markdown Окно расшифровки умеет скопировать разговор в буфер обмена и сохранить его файлом `.md`. Урезанная расшифровка помечена прямо в выгрузке, чтобы огрызок не приняли за целый разговор. ### ✏️ Быстрое переименование Переименование сессии по двойному клику на заголовок или по нажатию клавиши `F2`. --- ## Настройки Карточка расположена в: **Настройки → Плагины → Настройки плагинов → Управление сессиями** (`dsh-session-control`): | Поле | Тип | По умолчанию | Описание | |---|---|---|---| | `pinned` | `string[]` | `[]` | Идентификаторы закреплённых сессий (порядок в массиве задаёт порядок в панели) | | `hidden` | `string[]` | `[]` | Идентификаторы скрытых сессий | | `hideBlank` | `boolean` | `true` | Автоматически скрывать сессии без сообщений | | `sizeWarnEvents` | `number` | `1500` | С какого числа событий строка получает жёлтый значок | | `sizeDangerEvents` | `number` | `3000` | С какого числа событий строка получает красный значок | | `handoffProvider` | `string` | `''` | Провайдер для пересказа моделью; пусто — пересказ выключен | | `handoffModel` | `string` | `''` | Модель для пересказа; пусто — пересказ выключен | | `handoffMaxInputChars` | `number` | `60000` | Бюджет расшифровки для модели, в символах | | `handoffTimeoutSeconds` | `number` | `90` | Таймаут вызова модели, в секундах | | `labels` | `Record` | `{}` | Имя метки и идентификаторы её сессий | Настройки хранятся на хосте и синхронизируются между всеми клиентами. --- ## Архитектурные ограничения * **Перенос диалога в другую рабочую папку не поддерживается:** Рабочая папка привязана к каталогу на диске, а принадлежность сессии выводится из её рабочего каталога (`cwd`). Реестр ядра строго отвергает несоответствие путей. * **Возврат из архива не предусмотрен:** В API ядра есть только архивация, метод возврата отсутствует. Архивная сессия доступна для безопасного чтения через расшифровку. * **Чтение устаревших журналов:** Часть архивных сессий раннего формата ядро не парсит; такие логи отображаются с информативным пояснением, а не с ложным «нет сообщений». * **Удаление сессий отсутствует:** Удаление не предусмотрено в публичном API ядра, и плагин строго соблюдает контракт безопасности. --- ## Справочник HTTP API маршрутов Серверная половина плагина предоставляет три выделенных HTTP-маршрута через Cordis `webServer`: | Метод | Маршрут | Параметры (Query / Body) | Формат ответа | Описание | |---|---|---|---|---| | `GET` | `/dsh-session-control/transcript` | `session=`, `format=`, `title=` | JSON или Markdown | Читает JSONL-журнал сессии через дескриптор. Возвращает разобранные события диалога или готовый Markdown. | | `GET` | `/dsh-session-control/titles` | `sessions=` | JSON `{"ok": true, "titles": { "": "<подпись>" }}` | Выводит подписи диалогов из первой фразы пользователя (до 60 id в запросе; результат кэшируется в памяти). | | `GET` | `/dsh-session-control/export-batch` | `sessions=` | Markdown (`text/markdown`) | Формирует единый объединенный Markdown-файл нескольких сессий со сквозным оглавлением. | | `GET` | `/dsh-session-control/sizes` | `sessions=` | JSON `{"ok": true, "sizes": { "": {...} }}` | Размер и число событий для строк панели (до 60 сессий), без распаковки журналов. | | `GET` | `/dsh-session-control/handoff` | `session=&title=...&cwd=...` | JSON `{"ok": true, "handoff": {...}}` | Мгновенный черновик переноса контекста в новую сессию без обращения к модели. | | `POST` | `/dsh-session-control/handoff-summary` | Body: `{"session": "...", "title": "...", "cwd": "..."}` | JSON `{"ok": true, "draft": "..."}` | Пересказ итогов сессии моделью; требует настройки провайдера и модели. | | `GET, POST` | `/api/dsh-session-control/update` | Заголовок: `x-dsh-plugin-update: 1` (для POST) | JSON | Проверка текущей и доступной версии (GET) и обновление плагина в один клик (POST; только loopback и same-origin). | ## Архитектура и надежность Плагин спроектирован по **двухчастной архитектуре** для гарантии отказоустойчивости: 1. **Сервисная половина (`uiWorkspace` провайдер):** * Заменяемый модуль `ui-workspace` регистрирует обязательный сервис `uiWorkspace`, от которого зависят `dsh-client-ui-sidebar` и `dsh-client-ui-conversation`. * Сервисная половина отдаёт сервис и корневые хуки без React-рендеринга и оверхеда. 2. **Интерфейсная половина (UI):** * Дерево рабочих пространств, поиск, модальное окно расшифровки и карточка настроек. * Полностью изолирована предохранителями (Error Boundaries): сбой вёрстки не ломает панель и окно диалога. 3. **Серверный маршрут:** * `GET /dsh-session-control/transcript` безопасно парсит и отдаёт лог JSONL архивной сессии. --- ## Языки интерфейса Поставляется со строками на английском языке по умолчанию. Переводы (включая русский язык) подключаются через языковые пакеты (`@goodandready/dsh-russian-lang`). --- ## Совместимость - DeepSeek Harness `0.1.2-rc.1` и `0.1.3-alpha.1`. - Node.js `^20.19.0` или `>=22.12.0`. - Полная совместимость с `@goodandready/dsh-lanmode`, `@goodandready/dsh-kanban`, `@goodandready/dsh-cron` и другими плагинами DSH. --- ## Лицензия MIT © GoodAndReady