dsh-plugin-edit-message
English · 中文
DSH (DeepSeek Harness) Web GUI plugin: edit the last user message back into
the composer after stopping a turn — no more retyping from scratch.
Why
Sending a message, stopping the reply, and wanting to re-ask with a small
change currently means typing the whole prompt again. This plugin adds an
"Edit last message" button to the composer tool row: it restores the tail user
message text and focuses the input, ready to edit and send.
It is a client-side plugin — the conversation log stays append-only. Sending
the edited text appends a new turn (the original message and the interrupted
reply remain in the transcript). It never touches the host, the session log,
or the agent loop.
Install
The plugin bundles as a dsh.bundle + dsh.client package. It works on any
DSH setup that loads third-party bundles (source dsh web, DSH Desktop,
custom profiles).
From npm (published — recommended)
dsh plugin --profile web add dsh-plugin-edit-message
Restart the GUI (fully quit and reopen) after installing — client plugin
bundles register at startup.
DSH Desktop users: Desktop's DSH_HOME lives under
%APPDATA%\dsh-desktop\harness, so target that explicitly:
DSH_HOME="${APPDATA}/dsh-desktop/harness" \
dsh plugin --profile web add dsh-plugin-edit-message
Then quit and reopen DSH Desktop.
From GitHub or a local checkout (unpublished builds)
# GitHub repository
dsh plugin --profile web add git+https://github.com/WyxBUPT-22/dsh-plugin-edit-message.git
# local checkout (pnpm install && pnpm run build first)
dsh plugin --profile web add /path/to/dsh-plugin-edit-message
From this source checkout
The repository is self-contained: devDependencies resolve the official
harness client packages from the npm registry, so no deepseek-harness
checkout is needed.
pnpm install # pulls the official client packages from npm
pnpm run build # emits lib/index.js + lib/client.js + lib/types
dsh plugin --profile <name> add /path/to/dsh-plugin-edit-message
dsh --profile <name>
Uninstall with dsh plugin --profile <name> remove dsh-plugin-edit-message.
See docs/user/develop/basic/publish.md in the harness checkout for the
dsh plugin workflow.
How it works
- Registers one client plugin (
dsh.client manifest, platform: web) that
contributes an entry to the official conversation.input.left composer
tool-row slot (a documented multi-plugin list slot — zero official changes).
- The button renders only while the session is idle, a tail user/steering
message exists, and that message is plain text (draft images are browser
File-backed and cannot be resurrected from the durable log).
- On click:
inputActions.setDraft(text) restores the text and the composer
is focused. The plugin prefers inputActions.focus when the deployed
runtime exposes it, otherwise it focuses the editable surface —
[data-composer-input] on harness 0.1.2+ (a Lexical-driven
contenteditable), with the legacy composer <textarea> as the last
fallback.
- If you remove the plugin (
dsh plugin remove dsh-plugin-edit-message), the
surface disappears entirely — the tool row reverts to official chrome.
Compatibility
The plugin tracks the harness client contract, which was reshaped twice inside
the 0.1.2 line:
0.1.2-alpha split the monolithic @deepseek-ai/dsh-client-runtime into
dsh-client-store + the dsh-client-ui-* family, and moved the transcript
off SessionSnapshot (whose chat field no longer exists) onto the Chat
target published per Conversation binding, reached through the useChat
standard hook.
0.1.2-rc.1 stopped handing the composer tool row its InputZone owner
props: the responder now calls
renderSlot("conversation.input.left", {}). Session lifecycle therefore
comes from the useSession standard hook, which ui-session contributes for
every session-scoped slot on every 0.1.2 build.
| Plugin | Harness / DSH Desktop | Reads |
|---|
| 0.1.5+ | 0.1.2-alpha.1 … 0.1.2-rc.1 (Desktop 0.7.x / 0.8.x) | useChat + useSession; no owner props |
| 0.1.4 | 0.1.2-alpha.1 … 0.1.2-alpha.5 (Desktop 0.7.x) | useChat + the InputZone owner prop |
| ≤ 0.1.3 | 0.1.0-rc.x (Desktop ≤ 0.5.0) | session.chat |
Both 0.1.2 breaking changes fail the slot silently for older builds — the button
simply never appears, with the crash below in the console:
slot entry crashed in 'conversation.input.left':
TypeError: Cannot read properties of undefined (reading 'order') // <= 0.1.3 on 0.1.2-alpha
TypeError: Cannot read properties of undefined (reading 'running') // 0.1.4 on 0.1.2-rc.1
Differences from in-transcript editing (Codex style)
In-place replacement with a rewind of the log tail is a larger design
(log-truncation semantics, compaction checkpoints, session log format, dual
SDK projections) and is intentionally out of scope. This plugin provides the
interaction value — edit the text, resend — with zero blast radius.
Develop
pnpm run typecheck # tsc --noEmit (strict)
pnpm run test # vitest (logic matrix + component behavior)
pnpm run build # tsdown → lib/client.js + types
pnpm publish runs prepublishOnly (typecheck + test + build) first.
License
MIT
Friends
https://linux.do