Bundle
dsh-plugin-undo
Conversation undo for DeepSeek Harness: /undo <n> rewinds the model-visible surface and the Web UI collapses the undone turns.
- Source
- wang-xudong
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 14 days ago
Readme
# dsh-plugin-undo
Conversation undo for DeepSeek Harness: undo the last n turns within the current session — no new session, no project file changes.
## Why this plugin
Most conversation-rewind plugins use `sessions.fork` to copy a history prefix into a **new session** (the original session is kept or archived). This plugin undoes **in place** on the current session's surface, so:
- **No fork, no new session** — the session id stays the same
- No duplicate “original + new” sessions in the sidebar
- You keep chatting in the same session, and the model context is exactly the retained history
## Features
- `/undo` or `/undo 1` — undo the last completed turn
- `/undo 3` — undo the last 3 completed turns
- `/undo all` — undo every turn currently visible to the model
After undo:
- The model-visible history is replaced by the retained turns; undone turns leave the model context
- The raw session log stays append-only and is never rewritten
- The Web UI collapses the undone turns into a compact header
- The current session continues; no fork, no new session
## Effect
Undone turns collapse in the chat view as:
```text
↩ 第 N 轮已撤销 · 点击展开
```
Click the header to expand or collapse that turn in place. The `/undo` command card itself is hidden; the folded headers are the only visible undo feedback.
## How it works
1. The host derives the currently model-visible turns from `turn/start` / `turn/end`
2. It takes the last n turns and appends `surfaceOp: { op: 'replace', start, end }` over their surface range
3. The checkpoint is an **empty assistant message** outside any turn boundary; message derivation skips empty assistant content, so the model sees only the retained history — no undo marker, no turn numbers
4. The client half reads the successful `/undo` command nodes and folds the undone turns with DOM/CSS
## Install
```bash
dsh plugin --profile <profile> add file:/path/to/dsh-plugin-undo
```
Restart the profile:
```bash
dsh --profile <profile>
```
No additional configuration is required.
## Usage
Type in the session input:
```text
/undo
/undo 1
/undo 3
/undo all
```
The command requires the session to be idle. Stop the running turn first if the UI reports it is busy.
## Build & pack
Published entry points live in `lib/`; source lives in `src/`. Build and create the distributable tarball:
```bash
npm run build
npm pack
```
This produces `dsh-plugin-undo-<version>.tgz`, which can also be installed directly:
```bash
dsh plugin --profile <profile> add file:/path/to/dsh-plugin-undo-<version>.tgz
```
## Project layout
```text
dsh-plugin-undo/
├── README.md
├── README_zh.md
├── cordis.patch.yml
├── package.json
├── scripts/
│ └── build.mjs
├── src/ # source
│ ├── index.js # host: /undo command and surface replacement
│ └── client.js # web: folds undone turns, hides the command card
└── lib/ # build output (generated by npm run build)
```
## License
[MIT](./LICENSE)
## Limitations
- Only consecutive trailing turns can be undone; picking an arbitrary message in the middle is not supported
- Only the model-visible conversation history is rewound; project files are never touched
- The session must be idle when `/undo` runs
Install
dsh plugin --profile web add github:wang-xudong/dsh-plugin-undo
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-plugin-undo 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.