Skip to content
dsh.fish
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

  • 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.
Source