NattoCB/dsh-plugin-sidebar-views

NattoCB/dsh-plugin-sidebar-views

在侧栏列表上方加「工作区 / 最新会话」切换条,含固定会话分组、行级菜单(固定/取消固定、复制 Session ID)、标题过滤;pin 存于浏览器 localStorage,并对 dsh-plugin-pin-session 做一次性迁移与过渡双写。

UI Enhancementsdeepseek-harnesssession-pinsidebar

dsh-plugin-sidebar-views

Two views and pinned sessions for the DSH sidebar — switch between Workspaces and Recent sessions in one click; automation traffic no longer buries your own work.







Integration surface: client-only injection (window.__ModuleLoader__ bundle) · localStorage dsx2-pins / dsx2-groups · declares dsh.bundle.patch + dsh.client(web)

Language / 语言:English | 中文

A DeepSeek Harness client-side plugin that upgrades the sidebar session list: a Workspaces / Recent sessions switcher above the list — Workspaces is the native grouping; Recent flattens every session into one recency-sorted list with relative timestamps, running-state dots, and the owning workspace as a tag. A pinned-sessions group stays on top in both views. Since 0.3.0 the Recent view splits into Workspace / External groups — automation traffic is collapsed by default with a live count. Plain DOM throughout — no React, no portals, no slot takeover. Install into the web profile and restart.

✨ Features

  • 🔀 Two-view switcher: two tabs above the list — Workspaces (the native grouping) and Recent sessions (every session in one recency-sorted flat list, with relative timestamps, running/completed/pending state dots, and the owning workspace as a tag).
  • 📌 Pinned sessions group: stays above the list in both views, with a live count, collapse memory, and dimmed rows for sessions that no longer exist.
  • 🗂️ Workspace / external groups: the Recent view splits into Workspace (sessions attached to a regular workspace, expanded by default) on top and External (workspace-less headless sessions plus Automation-* workspace sessions — i.e. automation traffic) below, collapsed by default with a live count. Automation runs do join a real workspace, matched by workspace title or directory basename prefix (Automation-). Collapse state persists in localStorage (dsx2-groups); searching always expands both groups; collapsed groups skip row rendering entirely, so thousands of automation history rows never build DOM.
  • ⋯ Per-row menu: every row (pinned and flat) gets a "⋯" menu: pin/unpin the session and copy its session id.
  • 🔎 Title filter: a filter box in the Recent view for instant title matching.
  • 📁 Open in Finder: the native workspace "…" menu gains an open-in-Finder item, using the workspace cwd carried by the menu's fiber payload and activated through the stock workspaces.openPath service — zero host-side code.
  • 🧩 Plain DOM, zero framework: no React rendering, no portals, no slot takeover. The switcher is planted as the first child of the native sidebar list container; a CSS class hides the native list in Recent mode; a keep-alive interval survives native re-renders; a ResizeObserver hides the widget entirely when the sidebar rail collapses.
  • ⚡ Large-list performance: DocumentFragment batch inserts, content-visibility so off-screen groups skip layout/paint, and a 400 ms throttle on data refreshes (direct interactions — tab switch, collapse, search — stay unthrottled). Expanding 2400+ rows measures in milliseconds.
  • 🔁 Legacy migration: when the older dsh-plugin-pin-session plugin is still installed, its pin list is merged once at startup via GET /pin-session/pins (id-deduplicated, stays oldest-first), and every pin/unpin is dual-written to its POST /pin-session/pin|unpin during the transition. Both calls are silent no-ops once the legacy plugin is gone.

Quick Start

Prerequisites

  • DeepSeek Harness installed (dsh web runs).
  • Client bundles join the boot graph only at process start — restart dsh web after installing.

Install (into the web profile)

One command:

dsh plugin --profile web add github:NattoCB/dsh-plugin-sidebar-views

Manual install: in the profile's package.json, add the package to dependencies and the plugin name to dsh.profile.bundles, then run pnpm install inside the profile directory and restart dsh web.

Run

After the restart the switcher appears above the sidebar list — zero configuration. View, pin, and collapse state all live in browser localStorage and survive refreshes.

Storage & migration

Pins and group state live in browser localStorage — pins follow the browser profile, not the DSH host:

localStorage keyContents
dsx2-pinsPin list (oldest-first [{ id, title?, pinnedAt }])
dsx2-pins-collapsedCollapse state of the pinned group
dsx2-groupsCollapse state of the workspace/external groups (external collapsed by default)

Migration semantics toward the legacy dsh-plugin-pin-session: see 🔁 above — one-shot merge plus transition dual-writes, both silently fault-tolerant.

Uninstalling safely

Remove the plugin from both dependencies and dsh.profile.bundles in the profile package.json, then restart DSH. Deleting the package from node_modules while leaving the bundles entry in place makes the boot graph request a client.js that no longer exists — the module loader treats that as fatal and the whole web GUI fails to mount.

Development

npm test        # node --test: package contract + pin merge logic

client/client.js is a window.__ModuleLoader__.load({ id, factory }) bundle in the same shape as DSH's own client bundles. The pin-merge logic is exported as exports._mergePins so tests exercise the real code, not a copy.