Introduction¶
When performing agent conversations in DSH’s Web UI, you often encounter the need to remove a specific turn of user messages and all subsequent content (agent replies, sub-agent instructions, compression, retries, workflows, etc.) after sending a message. However, you do not want to rollback any code or file changes that have already occurred.
dsh-recall provides this capability for DSH Web UI: recall a message and all content following it, ensuring it persists after restarts via a persistent tombstone event in the append-only log. DSH’s plugin ecosystem emphasizes “everything is a plugin”; below is an introduction to this client plugin’s features, usage, and implementation boundaries based on the documentation. The community directory is an independent site and should not be interpreted as an official app store.
What is this¶
dsh-recall is a client plugin for DSH, licensed under MIT. The repository path is Mongfayi/dsh-recall, and the maintainer information in the documentation is recorded as Mongfayi.
It solves the problem of removing a user message and all content after it from the conversation—no longer displayed in the interface, no longer visible to the model—but never rolling back any code/file changes. Recall is not a simple deletion of interface elements; it is implemented via a persistent tombstone event in the append-only log, which remains effective after restarts.
Core Features¶
- Full-Turn Recall: Click the undo button next to the user message to recall that turn of conversation and all subsequent content. The recall scope includes the user’s question, the agent’s reply, and sub-agent instructions, compression, retries, workflows, etc., in long conversations.
- Restore Editing: After recall, the text and images of the recalled user message are restored to the input box as a whole, allowing for modification and resending.
- Non-Destructive Interface: The recall button is on the same line as the framework’s copy button and does not overlap; message bubbles, copy keys, reference tags, and image galleries remain as per the framework; messages containing images always display images normally.
- Persistent and Traceable: The recall record is a persistent tombstone event, persisted with the session log’s
flush, and remains effective after restarts; the log records it without deletion. - Real-time Update: Upon the tombstone arriving at the real-time session, the session assembly rebuild is triggered, causing the recalled line to disappear immediately without refreshing the page.
- Host-side Routing: Provides a
POST /recallroute, supporting{sessionId, messageId}or{sessionId, boundary}, completing the recall based on existing session protocols.
Typical Usage¶
-
When the session is idle, click the undo button (to the left of the copy button) next to the user message.
-
After confirming the popup, that turn of conversation and all subsequent content is recalled.
-
A “Recalled Message” prompt is displayed at the recall position.
-
The text and images of the recalled message are restored to the input box, allowing for modification and resending.
Note: The undo button is disabled while the agent is running; you must stop the current turn before recalling.
Installation and Enablement¶
The documentation does not provide an official installation command, so no concatenated installation command is added here.
The plugin depends on @deepseek-ai/dsh-session: the plugin’s node_modules/@deepseek-ai/dsh-session is symbolically linked to packages/core/session in the dsh source code deployment, sharing the same module instance and version with the host. The README provides the following command to rebuild the symbolic link so the plugin points to the same session module:
ln -sfn ../../../../deepseek-harness/packages/core/session node_modules/@deepseek-ai/dsh-session
Since the plugin registers host routes and overrides the client renderer, it is recommended to read the source code before installation to confirm the MIT license and behavior meet expectations. The plugin runs with the current dsh process permissions; the deployment environment should be treated as a production component.
How it Works¶
Host-side¶
The host-side provides a POST /recall route; the request body can be:
{ "sessionId": "...", "messageId": "..." }
or:
{ "sessionId": "...", "boundary": "..." }
The recall process is divided into three steps:
-
Validate Boundary: The boundary must be an active message node on the current
surface; if that boundary is already recalled or obscured,recall-rejectedis returned. -
Append Tombstone: Append a persistent tombstone in the form of an
assistant/messagewith empty content, wheresurfaceOpis{op:'replace', start: boundary, end}andsourceEventSeqscovers all obscured nodes. This empty content assistant message does not derive any messages, shrinking the model-visible history to beforeboundary. -
Mark and Persist: Record the tombstone marker in
data.recall = {boundary, end}for client-side node hints; then persist it with the normalflush.
Related error codes include:
session-not-found
subagent-owned
agent-busy
message-not-found
recall-rejected
Browser-side¶
The browser-side completes button, hiding, hints, and input box restoration via the client script.
The recall button overrides the user keyed renderer of conversation.chat.node with priority: -1 and delegates to the framework’s own user renderer. This ensures that message bubbles, copy keys, reference tags, and image galleries remain as per the framework; the undo button is positioned on the same line as the framework’s action row, to the left of the copy key, avoiding overlap.
Image rendering always goes through the framework’s image slot renderMessageImages. Session authorization, tags, and lightboxes remain as per the framework, not relying on the plugin’s built-in gallery loader.
Full-turn hiding occurs during assembly. Implementation-wise, it uniformly wraps the buildViewNode defined by each framework conversation: after calling the original builder, if the row’s anchor seq falls within the recalled interval, null is returned. The involved anchor fields include anchorSeq, data.seq, data.finalNode.seq, and data.closing.finalNode.seq. The documentation lists the covered node types as steering, context, assistant-step, command, manual-compaction, compaction, model-retry, turn-error, turn-max-tokens, turn-tail, unknown, command-input, tool-call, and workflow-run.
The “Recalled Message” hint is registered by matching tombstone events (assistant/message + data.recall) defined by recall.
Regarding real-time updates, after the tombstone arrives at the real-time session, the plugin’s recall definition is re-registered, triggering a session assembly rebuild, causing the recalled line to disappear immediately without refreshing the page.
When restoring the input box, the text is written back via conversation.input.for(scope).setDraft(). Images are retrieved as bytes via the session remote sessions.binding(sessionId).session.readAttachment(), then registered as draft images via conversation.createDraftImages() and hung onto the image track using addImages(). The recalled attachments remain in the append-only log, so restoration has a real data source; a single image restoration failure does not affect other restorations and does not rollback the completed recall.
Compatibility and Use Cases¶
dsh-recall does not require the session/recall event type, Session.recall, or client window filtering; it is based on the framework’s existing surface replacement protocol and keyed Chat Node seat.
It has been adapted and verified for DSH 0.1.1-rc.1, 0.1.1-rc.2, and 0.1.2-alpha.1. The 0.1.2 adaptation points listed in the documentation include:
- Definition registration service changed from
conversationEventstouiConversation.events; - Sub-agent ownership check (originally
hasApiRemoteSubagentOwnerfrom@deepseek-ai/dsh-api-remotes) has been inlined into the plugin; - Image restoration now uses session remote
readAttachment(originallyconversation.resolveImagehas been removed); - Client bundle now goes through the
/plugins/??<id>/client.jscombo URL service.
The applicable scenario is in DSH Web UI where you need to recall a turn of conversation and subsequent nodes while retaining code, files, or other side effects. If the conversation contains sub-agent instructions, compression, retries, or workflow nodes, and you want them to disappear together from the subsequent model-visible history, this type of plugin directly corresponds to this requirement.
Notes:
- The recall boundary must be an active message node on the current
surface, otherwiserecall-rejectedmay be returned; - The undo button is disabled while the agent is running; you must stop the current turn before recalling;
- Recall does not rollback code or file changes, but it does change the scope of the model-visible history in subsequent conversations;
- The documentation does not provide an official installation command; before deployment, handle it according to the project’s own plugin installation process and check the source code and license.
Links¶
The directory page clue provided in the documentation is: https://www.skillhub.cn/plugins/Mongfayi/dsh-recall
GitHub: https://github.com/Mongfayi/dsh-recall