メインコンテンツへスキップ
K

dsh-delete-session

kagurazakayashi/dsh-delete-session

A minimal DeepSeek Harness Web plugin that appends a delete-session item below the archive-session item in the sidebar session row menu, resolved by an exact displayTitle + relative-time match.

インストール

dsh plugin --profile web add github:kagurazakayashi/dsh-delete-session

README

dsh-delete-session

Language: English · 简体中文

A DeepSeek Harness Web plugin for quickly and thoroughly deleting sessions.

The plugin adds a Delete session item to a session row's … menu in the left sidebar of the DeepSeek Harness Web UI.

  1. First click: turns the item into an in-place warning state (red background + warning icon).
  2. Second click: permanently deletes that session.

So an unwanted session can be deleted conveniently with a double-click.

It is a minimal DeepSeek Harness Web out-of-tree plugin. It neither modifies the DSH core installation nor any profile configuration; instead it appends the Delete session menu item via DOM injection in the browser.

Quick install

Run these two commands in your terminal to install and start:

dsh plugin --profile web add @kagurazakayashi/dsh-delete-session
dsh web

After the restart, refresh the page and open any session row's … menu — Delete session appears below Archive session.

Features

  • Host side (index.js) registers POST /delete-session/delete.
  • Browser side (client.js) watches for session-row … menu popups and injects a Delete session item below Archive session (zh / en bilingual).
  • Two-step deletion, no confirmation dialog: the first click switches the menu item to an in-place warning state (red background, warning icon, "Click again to delete" / "再次点击删除") without closing the menu or showing a dialog; the second click actually calls the delete route, then refreshes the session and workspace lists.
  • The warning state is remembered per session id (in-memory, auto-disarms after 8 seconds); reopening the menu within that window still shows the warning state. A failed deletion also disarms it.
  • Deletion failures show a lightweight error notice (plain DOM, not a confirm dialog) explaining the reason (session busy / not found / network error, etc.).
  • Running sessions are refused (HTTP 409): only sessions whose agent status is not idle (i.e. running a task) are rejected, to avoid corrupting a log that is still being written. Idle sessions that were merely opened and then switched away (still resident in memory) can be deleted normally.

Menu diagram

After clicking the … button on a session row, the opened menu looks like this (Delete session is injected by this plugin). The screenshot below contrasts the menu before and after the first click — the second click is what actually deletes:

Delete session demo

Session row menu

├─ Rename session     (core)
├─ Archive session    (core)
└─ Delete session     ← injected by this plugin (zh / en)

Usage (two-step deletion)

Deletion uses a two-step confirmation with no dialog:

First click "Delete session"
        │
        ▼
The item turns into a red warning state "Click again to delete"
        │
        ├─ not clicked again within 8s ──▶ reverts to normal "Delete session"
        │
        └─ clicked again within 8s ──▶ calls POST /delete-session/delete
                                            │
                                            ├─ session is running ──▶ 409 refused, error notice
                                            │
                                            └─ idle session ──▶ archive → rm session directory
                                                                   │
                                                                   ▼
                                                              200 OK, refresh lists

Installation

dsh plugin --profile web add @kagurazakayashi/dsh-delete-session

This pulls the plugin from npm and registers it in the profile's bundle list automatically (no manual config editing).

Install from source

This plugin is structured like dsh-archive-manager: put it on disk, then add it to an existing web profile.

  1. Place the plugin source somewhere on disk, e.g. on Windows:

    C:\Users\<you>\.dsh\plugins\dsh-delete-session
    

    (On macOS / Linux: ~/.dsh/plugins/dsh-delete-session.)

  2. Add it to the web profile with dsh:

    # Windows (replace <you> with your username)
    dsh plugin --profile web add "C:\Users\<you>\.dsh\plugins\dsh-delete-session"
    
    # macOS / Linux
    dsh plugin --profile web add "~/.dsh/plugins/dsh-delete-session"
    
  3. Make sure the bundle list in $DSH_HOME/profiles/web/package.json includes this plugin. Newer dsh versions append it automatically on add; if not, add it by hand:

    {
      "name": "dsh-profile-web",
      "private": true,
      "dependencies": {
        "@kagurazakayashi/dsh-delete-session": "link:../../plugins/dsh-delete-session"
      },
      "dsh": {
        "profile": {
          "bundles": [
            "@deepseek-ai/dsh-base",
            "@deepseek-ai/dsh-web-app",
            "@kagurazakayashi/dsh-delete-session"
          ]
        }
      }
    }
    

    The dependencies entry is written by dsh plugin --profile web add; if dsh.profile.bundles is not appended automatically, add it by hand.

  4. The plugin's cordis.patch.yml (declared via dsh.bundle.patch) injects the host row:

    - insert:
        - id: delete-session
          name: '@kagurazakayashi/dsh-delete-session'
    

Restart to take effect

A running process does not load new bundle rows, so restart the web profile:

dsh web

After refreshing the page, open any session row's … menu; eligible rows show Delete session below Archive session. Click once to enter the warning state, click again to delete.

Notes (safety & limitations)

  • Running sessions refused: ctx.agents.get(id)?.status !== 'idle' returns 409, and a second check runs right before deletion. Only idle sessions resident in memory are exempt.
  • Auto-archive before delete: the destructive rm is preceded by workspaceRegistry.archiveSession(id), which lets the sidebar hide the session immediately via the host/archived-sessions-changed broadcast (and lets the client auto-clear the current selection), so it does not linger in the list until restart. Archiving is idempotent; a failure does not block the main deletion flow.
  • Raw artifact backend required: the persistence backend must expose supportsRawArtifacts === true and a locate() returning { kind: 'jsonl', path }, otherwise it returns 501.
  • Deletes only the session directory: rm(dirname(location.path), { recursive: true, force: false }); an archive marker is written first, but workspace groups, projection caches, and shared attachments are left untouched.
  • Irreversible: deletion is a recursive rm with no recycle bin; operate with care.
  • In-memory two-step state: the warning state lives only in browser memory (per session id, 8-second window) and disappears on plugin unmount, page refresh, or timeout; no persistent state is produced.
  • Conservative same-name policy: if two rows share both the same title and the same relative time (match count ≥2), neither gets a delete item.
  • Inherent DOM-injection fragility: this plugin depends on the core UI's DOM structure (button → span.root → span.rowActions → time span → title span) and the "Archive session" menu-item text. If DSH changes either in an upgrade, injection fails silently (no error, and no accidental deletion); client.js must then be updated to match the new structure.
  • Relative-time boundary drift: the row's relative time is computed by the core at render time, while matching recomputes it with the current time; near a bucket boundary this may yield 0 matches and no injection (conservative and safe).
  • No injection before data is ready: opening the menu during early startup (before the session/workspace lists are pulled from the host) shows no delete item; reopen the menu once data is ready. If data arrives and triggers a repaint while the menu stays open, the observer re-injects automatically.

Uninstall

Remove @kagurazakayashi/dsh-delete-session from the profile's dsh.profile.bundles (and dependencies) and restart. The plugin produces no persistent state, so no other cleanup is needed.

License

MIT — see LICENSE, copyright KagurazakaYashi(KagurazakaMiyabi).

Languages

関連プラグイン