← Back to home@dsh-plugin-db

dsh-session-trash

Delete sessions from the DeepSeek Harness Web sidebar straight into a Trash settings page, then restore them or delete them permanently.

Stars
0
Language
JavaScript
Created
Oct 16, 2026
Updated
Oct 16, 2026

Introduction

dsh-session-trash

Delete sessions from the sidebar into a Trash page in Settings, then restore them or delete them permanently.

A global DeepSeek Harness plugin published as one npm package carrying both halves: a Host plugin mounted by the bundle patch, and a browser half served from the same package's ./client export.

Install

This package is a DeepSeek Harness bundle: dsh.bundle.patch is its Host row, dsh.client is its browser half, and the package resolves both. Install it into a profile with the harness's own Plugin Manager — point it at this directory (or at the repository URL) and it records the bundle in the profile:

  • dsh CLI, if the harness exposes the Plugin Manager surface: dsh plugin --profile <name> add <source>
  • or add it to the profile's dependencies and bundle list directly, then boot.

The profile's own cordis.patch.yml is applied after this bundle's layer, so it is also where any config below is pinned.

What it adds

  • A delete button at the end of every Session row in the sidebar, beside the shipped archive and pin buttons. One press deletes: the session goes straight to Trash with no confirmation step, because Trash is the undo.
  • A Delete session row in the Session's … menu, for keyboard users and anyone who never hovers a row.
  • A Trash page in Settings listing every deleted session, with Restore and Delete permanently per session and Empty Trash for the whole list. Permanently deleting a session drops its log and its derived projection cache; a live session cannot be trashed or purged. These two stay behind a confirmation, because they are the irreversible half.

The deleted row leaves an open browser immediately

Moving a log aside makes the session absent from the Host catalog on the next listing — but nothing schedules one. The browser's session store was filled by a pull that already happened, so a deleted row would otherwise stay on screen (the sidebar renders it as an ungrouped "stray") until the page was reloaded.

After the log actually moves, the Host therefore emits the declared Remote Event api-session/removed, which Cordis relays to every connected client. That is the same path the shipped Session controller uses for its own disposal notifications (dsh-api-session-controller/lib/index.js), so the browser clears the row through its ordinary list-mutation code — no client-side list surgery, and no plugin knowledge of another package's internals. The route's response reports announced: false if the relay was unavailable, so a deployment without the event simply falls back to clearing on the next load.

How deletion works

The Harness ships no session-deletion API: SessionPersistence creates, opens, lists, and flushes handles but never removes one, and the browser session controller exposes no delete verb. What the store does publish is its addressing rule — a session is visible exactly when its directory holds a canonical generation log (session.jsonl, session.v<N>.jsonl, either with the configured compression suffix).

So deleting a session appends .trashed to that one basename inside the session's own directory. Nothing is copied and the log's bytes are untouched: stat/list/open all report the session as absent, so the sidebar catalog, search, title folding, and lineage traces treat it as gone without knowing this plugin exists. Restoring removes the suffix again, which brings the title back with the log, and permanently deleting removes the directory and the session's projection-cache record.

The trash index is this plugin's own plain JSON document. A missing, empty, or hand-edited index is reconciled against the session root on every read, so a trashed session is never stranded by index damage.

Configuration

The row takes an optional config, set from the profile's own cordis.patch.yml (the layer applied after this bundle's):

- id: session-trash
  name: 'dsh-session-trash'
  config:
    # Defaults to $DSH_HOME/sessions, the session-persistence root.
    sessionsRoot: /absolute/path/to/sessions
    # Defaults to $DSH_HOME/storages/dsh-session-trash/index.json.
    indexFile: /absolute/path/to/index.json
    # Defaults to $DSH_HOME/storages/session_projcache/sessions.
    projectionCacheDir: /absolute/path/to/session_projcache/sessions

Verification

Two dependency-free suites ship with the package and run against a scratch session root in the system temporary directory:

node verify.mjs        # the store: trash, list, restore, purge, empty, recovery
node verify-route.mjs  # the route: dispatch, validation, refusals, envelopes

verify.mjs asserts the property this design rests on — a trashed session is invisible to a canonical-generation scan while its bytes are byte-for-byte unchanged, and restoring brings back the identical file.

Upgrade stability

The Host half imports no Harness package; its one contribution is a connection.fetch exact route on the authenticated /api channel, and the store knowledge it relies on is the filename grammar above — a storage-format constant rather than a module API, with v<N> left open-ended so a future format generation is matched by the same scan. The browser half imports no Harness Client package either: it uses the module-loader factory contract, ctx.slots.inject/register, the slot's standard useSessions hook, ctx.locale, and --dsw-alias-* theme tokens only.