npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-sidebar-pins

v0.1.0

Published

Pinned-sessions block for the DeepSeek Harness sidebar: a collapsible pinned panel above the Settings row, hover pin buttons on session rows and a session-header toggle. Pins live in the plugin's own settings namespace and are migrated once from dsh-sessi

Readme

English | Русский

dsh-sidebar-pins

Самодостаточные закреплённые сессии для левой панели DeepSeek Harness: свой набор пинов, свои кнопки закрепления и блок «📌 ЗАКРЕПЛЁННЫЕ» сверху сайдбара — вместо всплывающего окна, которое уезжает в правый верхний угол и закрывается от клика мимо.

Плагин написан под DSH 0.1.5-rc.1 и заменяет dsh-session-pin целиком: после его установки старый плагин можно удалить (см. «Удаление старого плагина»).

Зачем

dsh-session-pin 0.7.11 на этой версии ядра не может выдать то, что обещает:

  • он переставляет хостовый список (workspaces.insertSessionBefore) — и тот действительно переставлен, это видно в ~/.dsh/storages/workspace.json;
  • а сайдбар рисует браузерный порядок (dsh.workspace.view.v5), поверх которого хостовый список уже не влияет, — публичного API к этому хранилищу у плагинов нет;
  • слот sidebar.workspaces объявлен ядром как kind: "single", поэтому встроить в него второй блок невозможно;
  • слота sessions.row.action на 0.1.5-rc.1 нет, поэтому кнопки в строках — DOM-оверлей.

Что делает

| Поверхность | Поведение | |---|---| | Блок «Закреплённые» | Внутри подвала сайдбара, над строкой «Настройки». Место выводится только из собственной метки-якоря: собирается вся цепочка контейнеров от неё вверх, и панель садится перед той веткой, что ведёт к якорю. Контейнеры, которые раскладывают детей в строку (штатный footerActions — именно такой), пропускаются по измерению, поэтому панель не встаёт сбоку от «Настройки»; уровни выше корня сайдбара не рассматриваются вообще — иначе панель оказалась бы над всем сайдбаром. Высота — до 30vh, список пинов прокручивается внутри. Сворачивание вручную помнится per-browser; в режиме рейки панель показывает только иконку и количество | | Строка пина | Клик — открыть сессию; × справа — открепить (появляется при наведении) | | Кнопка в строке сессии | 📌 при наведении на строку — закрепить/открепить. Сессия определяется по React-fiber, с откатом на вложенный span с уникальным заголовком | | Кнопка в шапке сессии | Тумблер закрепа открытой сессии (слот conversation.session.header.actions) | | Пропавшие сессии | Остаются в списке приглушёнными (сырой id), чтобы их можно было открепить | | Легаси-панель | Плавающая панель, подвал «Pinned sessions», полоса бордов, старая кнопка в шапке и старые кнопки в строках скрываются — вся закреп-UI теперь здесь |

Плагин ничего не пишет в лог сессии, не обращается к сети и не влияет на запросы к модели.

Хранилище

  • Основное место — свой namespace настроек sidebar-pins (регистрирует хостовая половина), то есть пины durable и видны в ~/.dsh/settings.yaml.
  • Если клиент не видит namespace (хост-половина не смонтировалась, remote-браузер) — откат на localStorage["dsh.sidebar-pins.pinned"].
  • При первом запуске набор разово переносится из session-pin (хостовой половиной, до открытия страницы), поэтому пины переживают удаление старого плагина. Перенос идёт только пока поле pinned не появилось в пользовательском слое: осознанно опустошённый набор больше не заполняется.

Установка

Из GitHub:

dsh plugin --profile web add github:AndreyTepaykin/dsh-sidebar-pins

Из npm (когда пакет опубликован):

dsh plugin --profile web add dsh-sidebar-pins

Для локальной разработки — из каталога с рабочей копией плагина:

dsh plugin --profile web add .

Затем перезапустить DSH (клиентский бандл попадает на страницу при пересборке boot-графа) и обновить страницу GUI.

Проверка

node --test "test/*.test.mjs"                                     # 43 теста
dsh --profile web --dump-config | Select-String "sidebar-pins"    # строка загрузчика

Прямо над кнопкой «Настройки» появится «📌 ЗАКРЕПЛЁННЫЕ (3)» — панель высотой 30vh с прокруткой; список сессий остаётся выше.

Если панели нет, плагин сам скажет почему — в консоли браузера:

__dshSidebarPins

Объект диагностики (window.__dshSidebarPins) всегда заполнен: paneConnected, paneParent, anchors (якорь и цепочка контейнеров до него), seat/seatLabel (какое место выбрано), skipped (места, отброшенные как row-контейнеры), rail, rows и rowButtons (сколько строк сайдбара видно и на скольких появилась кнопка), styleNode, pinned, ignoredPosition и notes со всеми предупреждениями. Подробный лог включается отдельно:

localStorage.setItem("dsh.sidebar-pins.debug", "1");
location.reload();

Панель к тому же само-восстанавливается без опроса таймером: всё, что может её снести, — это изменение DOM, поэтому наблюдается ровно три цели: тело документа (снятие/перерисовка панели), head (стилевой узел) и класс корня сайдбара (переход список ↔ рейка). Любое из этих изменений возвращает панель и стиль на место.

Настройки (браузер, localStorage)

| Ключ | Значение | |---|---| | dsh.sidebar-pins.collapsed | 1 — панель свёрнута до строки заголовка | | dsh.sidebar-pins.show-legacy | 1 — не скрывать легаси-поверхности dsh-session-pin | | dsh.sidebar-pins.debug | 1 — писать подробную диагностику в консоль |

dsh.sidebar-pins.position больше не читается: место панели фиксировано. Значение, оставшееся в localStorage от прежней версии, показывается в диагностике как ignoredPosition и ни на что не влияет.

Удаление старого плагина

dsh plugin --profile web remove dsh-session-pin

Порядок важен: сначала убедитесь, что блок и кнопки работают (пины перенесены), потом удаляйте. После удаления в ~/.dsh/settings.yaml останется неиспользуемая секция session-pin — её можно убрать вручную, плагин её не читает.

Ограничения

  • Основной список не переупорядочивается. Закреплённые живут в панели снизу и остаются в обычном списке: браузерный порядок живёт в props-store ядра, недоступном плагинам.
  • Высота панели — до 30vh (сайдбар занимает высоту окна), а не фиксированное число пикселей; если сайдбар короткий, панель отдаёт место, а не выдавливает «Настройки» за край. Свёрнутая (и любая в режиме рейки) панель занимает только строку заголовка.
  • Идентификация строки сессии опирается на React-fiber (__reactFiber$…, React 18) с откатом на любой вложенный span с уникальным заголовком: при дублирующихся заголовках кнопка не появится (вместо угадывания). Кнопка в шапке сессии от этой эвристики не зависит.
  • В режиме рейки строк сессий в DOM нет вообще — там нечего помечать кнопкой, поэтому 📌 в строках появляется при развёрнутом сайдбаре (rows: 0 в диагностике в рейке — это норма, а не сбой).
  • Место панели выводится только из своей метки-якоря и не зависит ни от строк сессий, ни от обёрток. Живой хост добавляет лишний безымянный div вокруг корня сайдбара и по одному div вокруг каждой записи слота подвала, а сам footerActions раскладывает детей в строку. Поэтому вместо фиксированной цепочки собирается весь путь вверх от якоря, и место выбирается по измерению: контейнер должен раскладывать детей столбцом (иначе панель легла бы сбоку от «Настройки»), а панель — оказаться выше строки «Настройки». Уровни выше корня сайдбара не рассматриваются: оттуда панель попала бы над всем сайдбаром. Выбранное место и отброшенные видны в диагностике (seat, seatLabel, skipped), а последнее убежище — конец ближайшего «столбцового» контейнера, то есть панель остаётся внутри сайдбара. Стилевой узел переустанавливается на каждом проходе: панель без стилей разрослась бы по содержимому и выдавила «Настройки» за край.
  • Плагин сознательно не импортирует ни одного внешнего пакета. При установке ссылкой (link:) в профиль это ещё и вынужденно: Node разрешает bare-импорты от реального пути пакета (рабочей копии), где нет node_modules, и вход не загрузился бы с ERR_MODULE_NOT_FOUND. Поэтому схема настроек описана руками (см. ниже) — при установке из npm/git ограничение снято, но ручная схема остаётся, чтобы поведение не зависело от способа установки.

Сериализованная схема

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

node scripts/check-schema-envelope.mjs

Скрипт поднимает тот же вендорный код из dsh-client-ui-settings/lib/client.js, ре-гидратирует конверт и проверяет {pinned:["a","b"]}, {}, {pinned:[1]}. Этот же тест есть в наборе (test/host.test.mjs) и пропускается, если оболочки на машине нет. Запускайте после обновления DSH.

Разработка

node --test "test/*.test.mjs"

43 теста: чистые хелперы (нормализация id, разбор легаси-документа, модели строк, словарь, toggle), хост-половина (регистрация, схема, миграция, конверт), цепочка мест от своего якоря (включая лишние обёртки живого хоста и отсутствие строк сессий), отказ от row-контейнеров, посадка над строкой «Настройки», геометрическая проверка и переход к следующему месту, последнее убежище внутри сайдбара, поведение в рейке (только иконка и число), отсутствие перерисовки без изменений, наблюдаемые цели, восстановление снесённых панели и стилевого узла, кнопки в строках (fiber / вложенный заголовок / неоднозначность), делегированный клик, кнопка в шапке, откат на localStorage и размонтирование.