Bundle
dsh-delete
DSH-DELETE: recoverable conversation deletion for DeepSeek Harness — a session menu item and /delete-conversation command that queue deletions, hide sessions immediately, and move logs to a recoverable trash on restart
- Source
- Hyna-hla
- stars
- 1 stars
- License
- MIT
- Updated
- Updated yesterday
Readme
# DSH-DELETE
**English** | [中文](README.zh.md)
Recoverable conversation deletion for DeepSeek Harness: adds a **Delete conversation** item to the session row `…` menu and registers the `/delete-conversation` human command. After confirmation the target Session enters a deletion queue and is immediately hidden from the list through the Workspace persisted archive projection; on the next DSH startup the plugin validates the Session's full lifecycle before the Web Workspace builds its session index, then atomically moves its log directory into a recoverable trash.
> Derived from [omdsh-dev/dsh-essential](https://github.com/omdsh-dev/dsh-essential) (MIT, Copyright (c) 2026 ExDragine). This repository renames the package / Remote IDs / UI class names to `dsh-delete` and adds a `stateDir` default (`~/.dsh/conversation-trash`) so marketplace one-click installs need no manual config.
## Why deletion is two-phase
DSH's Session persistence is append-only and the public services expose no delete method; an active Agent's destroy handle belongs to its creator only. The plugin cannot safely move logs out from under an active writer. Deletion therefore happens in two phases: the running process only writes a durable request and hides the row immediately; the next startup completes the log move before any session recovery. This boundary avoids log rebuilds, partial writes, and lifecycle races.
## Install
### Option 1: DSH plugin marketplace (recommended)
This repository ships built artifacts (`lib/`), so marketplace one-click install needs no build and no config:
1. DSH Web GUI → Settings → DSH plugin marketplace
2. Search `DSH-DELETE`, click **Install**
3. Restart DSH
### Option 2: official bundle install
```sh
node /path/to/DSH/apps/cli/lib/bin.js plugin --profile web add /path/to/DSH-DELETE
```
Restart DSH afterwards. The bundle mounts `dsh-delete` and makes the Web Workspace wait for the `conversationDeletion` service to finish startup recovery before building the Session index.
### Option 3: write cordis.patch.yml directly
```yaml
- insert:
- id: dsh-delete
name: dsh-delete
config:
stateDir: /absolute/path/to/conversation-trash
- id: workspace
inject: [conversationDeletion]
```
`stateDir` must be absolute and outside Session artifact directories; it defaults to `~/.dsh/conversation-trash`.
## Usage
- Open the target session's `…` menu in the session list and choose **Delete conversation**. Confirmation is an in-page card (title "Confirm deleting this conversation?", actions "Cancel / Delete conversation") — no native browser dialogs.
- A confirmed request archives the Session immediately, hiding it across all session groups (the row disappearing is the success feedback).
- If the request was written but the archive call failed, the card reports "queued but cannot hide yet" instead of misreporting a failed deletion.
- Human command: `/delete-conversation CONFIRM` (deletes the current conversation); `/delete-conversation <session-id> CONFIRM` (deletes another conversation by Session id).
After confirming, restart DSH; logs are moved to `<stateDir>/trash/<session-lifecycle-key>/`. `deletion.json` inside records the original directory.
## Recovery
Stop DSH, delete the `deletion.json` inside the recovery directory, then move that directory back to `originalDirectory`. Do not recover while DSH is running.
## Config
| Field | Type | Default | Description |
|---|---|---|---|
| `stateDir` | string | `~/.dsh/conversation-trash` | Directory holding pending requests and the recoverable trash; must be absolute and outside Session artifact directories |
| `commandName` | string | `delete-conversation` | Optional human-command alias (no leading `/`); the menu always uses the stable `/delete-conversation` |
## Safety and recovery semantics
- The command requires the literal `CONFIRM`; nothing is written without it.
- Requests bind `sessionId`, `createdAt`, and `cwd`; a reused id will not delete a new Session lifecycle.
- The move re-validates the persisted list, backend location, and full inspect results.
- The product operation uses same-filesystem directory `rename`, never `unlink` of Session logs; post-move crashes are recoverable.
- Validation/move failures keep the pending request and record an error; the original log stays untouched.
- **Per-Session JSONL backends only**: SQLite has no independent artifact location, and the plugin refuses it explicitly.
- **Not permanent erasure**: logs go to a recoverable trash; retention and final cleanup are deployment-administrator policy.
## Building from source
Requires Node `^22.19.0 || >=24.0.0` (tsdown needs `Promise.withResolvers`). On Windows keep the Node 22+ used for building first in PATH:
```sh
pnpm install
pnpm add -D -w unrun # optional peer of tsdown; must be explicit when autoInstallPeers=false
pnpm run build
pnpm run verify:self-contained
pnpm run typecheck
pnpm test
```
## License
MIT. Original copyright belongs to [dsh-essential](https://github.com/omdsh-dev/dsh-essential) (Copyright (c) 2026 ExDragine); see [LICENSE](LICENSE).
Install
dsh plugin --profile web add github:Hyna-hla/DSH-DELETE
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-delete from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.