DSH Plugins Marketplace

DSH Plugins

Plugins

/

UI & Experience

/

dsh-recall-unread

h

dsh-recall-unread

Manifest valid★ 51

DeepSeek Harness (DSH) Plugin: Recall sent-but-unread text messages before the model reads them, supporting recall of individual or all messages. A DeepSeek Harness plugin that recalls sent-but-unread text messages before the model reads them — one-by-one or all at once.

UI (client)hasBundlePatch

dsh-recall-unread

DeepSeek Harness (DSH) plugin: recall text messages that have been sent but not yet read by the model.

When you send text while the model is running (interjection send), the message appears as a "pending" bubble at the end of the conversation — before the model claims (reads) it, you can recall it with one click.

Screenshot placeholder: you can save an actual screenshot of the effect as docs/screenshot.png and uncomment the ![screenshot] above.


✨ Features

  • Effective on enable: after enabling this plugin in the plugin market (dsh-market) or the plugin management page, the "unread messages" strip takes effect immediately; disabling it unloads it entirely. No launcher menu dependency.
  • Unread messages strip: lists all sent-but-not-yet-read interjection messages (placement: 'steering') above the input box (in the conversation.input.dock slot).
  • Recall one: each message shows preview text plus a "Recall" button; clicking it removes the message from the conversation and displays the notice "Recalled one message".
  • Recall all: when multiple unread messages exist, a "Recall all" one-click action is provided.
  • Read-only semantics: once a message is claimed by the model (reading has started), it automatically leaves the strip and can no longer be recalled — strictly enforcing "only unread messages are recallable".
  • Graceful degradation: when a recall fails (the message has already started being sent), a clear notice is shown and the session is not corrupted.

🔍 How It Works

In DSH, a "sent but unread" message = a message still sitting in the Agent inbox (pending queue), i.e. a pending item in the ConversationSnapshot.queue snapshot. It has two placements:

placementMeaningCurrent official UI
queuedQueued while running, waiting for the next roundThe official queue dock already has a "delete" button
steeringInterjection sent while running, shown as a pending bubble at the end of the conversationNo recall entry point at all ← this plugin adds one

Recall in two versions:

  • Static version (recommended): the Client directly calls the official session RPC session.updateQueue(itemId, { kind: 'remove' }) (same implementation as the official queue dock's "delete").
  • Dynamic version: uses a private in-package RPC:
Client  (撤回按钮)
   │  host.call('recall', { sessionId, itemId })
   ▼
Host    harness.handle('recall')
   │  agents.get(sessionId).inbox.remove(itemId)
   ▼
效果   消息从 inbox 移除 → session/queue 快照更新 → 气泡与条带同步消失

The Host-side logic is consistent with the internal implementation of kind: 'remove' in the official session.updateQueue (agent.inbox.remove).

📁 Directory Structure

dsh-recall-unread/
├── README.md                  # 本文件
├── LICENSE                    # MIT 许可证
├── .gitignore                 # Git 忽略规则
├── package.json               # 项目元数据(GitHub 展示用)
├── plugin.json                # 插件清单(名称 / ID 前缀 / 代码来源)
├── src/
│   ├── host.js                # Host 半端源码(动态版,可直接作为 code.host)
│   └── client.js              # Client 半端源码(动态版,可直接作为 code.client)
├── plugin/                    # 静态 web profile 插件包(安装后随 DSH 加载,推荐)
│   ├── package.json           # 安装包元数据(含 dsh.client 声明)
│   ├── host.js                # Host 半端(空实现占位,撤回走客户端官方 RPC)
│   └── client.js              # Client bundle(__ModuleLoader__ 注册)
└── docs/                      # 截图等附加资源(可选)

🚀 Installation & Activation

Option 1: Static Installation (Recommended — loads with DSH, persists across restarts)

Install the plugin/ directory as a static plugin for the DSH web profile:

  1. Copy the entire plugin/ directory into the web profile's node_modules:
    ~/.dsh/profiles/web/node_modules/dsh-recall-unread/
    
  2. Append a load entry at the end of ~/.dsh/profiles/web/cordis.patch.yml:
    - insert:
        - id: recall-unread
          name: dsh-recall-unread
    
  3. Restart DSH. Once the plugin is enabled, the "unread messages" strip is active. You can disable/enable it at any time from the plugin marketplace (dsh-market) or the plugin management page.

Note: The static version directly calls the official session RPC session.updateQueue(itemId, { kind: 'remove' }) on the Client side (the same implementation as the "remove" action in the official queue dock). No dynamic RPC is needed, and behavior matches the official UI exactly. The plugin does not depend on Amadeus.

Option 2: Dynamic Plugin (Temporary — does not survive restarts)

This project can also be tried temporarily as a DSH dynamic Cordis plugin (process-level definition):

  1. Open DSH and enter the Cordis plugin development flow (cordis_define) in a conversation.
  2. Create a new plugin:
    • idPrefix: recall
    • code.host: paste the full contents of src/host.js
    • code.client: paste the full contents of src/client.js
    • name: Recall Sent Unread Messages
    • purpose: a one-line description of the use case
  3. Use the returned pluginId / packageId to call cordis_run and activate it, then approve the run in the UI.
  4. After activation, send an interjection message while the model is running to see the "unread messages" strip and the "Recall" button above the input box.

Note: dynamic plugins are process-level and temporary — redefine after DSH restart. For long-term use, prefer the static install in Option 1.

⚙️ Configuration

This plugin is zero-config and ready to use out of the box — no setup required. If you need to fine-tune it, modify src/client.js and re-define it (cordis_define). Common tunables:

ItemLocationDescription
Strip orderingslots.register(…, order: 30)A larger number places it further back; adjust to control how close it sits to the input box
Toast dwell timectx.timeout(() => setStatus(null), 2500)How long the recall result toast is shown before auto-dismissing (milliseconds)

📖 How to Use

  1. Ensure plugin is enabled (default on after install; toggle in marketplace/management page).
  2. While the model is running, use interjection send to send a text.
  3. The message appears at conversation end (marked "pending"), and the "unread messages" strip shows above the input box.
  4. Click "Recall" next to the message — bubble and strip vanish; toast: "one message recalled".
  5. For multiple unread, click "Recall all" to clear at once.

⚠️ Limitations & Known Issues

  • Only messages not yet read by the model (still in inbox) can be recalled; once claimed, it's final.
  • Queued messages (queued) already have delete in the official queue dock; not duplicated here.
  • No official "bubble-level" slot exists, so the recall control is in the strip above the input box.
  • Dynamic plugins don't persist; static install (Option 1) auto-loads with DSH and survives restarts.

🔒 Anti-Lockout Mechanisms (Important)

DSH web startup is fail-loud: if any plugin fails to load, the whole screen shows Failed to load plugins, preventing DSH from opening. This plugin previously triggered a startup lockout with ReferenceError: module is not defined because the bundle referenced module.exports. This is now hardened at three levels:

1. Bundle Structural Fix (In Effect)

The factory in DSH's window.__ModuleLoader__.load only injects require, not module / exports. plugin/client.js no longer references module / exports at all — the factory simply return { inject, apply } (the return value IS the module export). No matter how it is modified or re-wrapped, module is not defined cannot recur. A detailed warning comment is included at the top of the file.

⚠️ Do NOT remove 'timer' from inject: Cordis's ctx is a Proxy; accessing a service property that was not injected throws cannot get property "timer" without inject directly, causing the apply phase to fail. The client-side timer service is provided by the core plugin @deepseek-ai/dsh-cordis-client-runner (ctx.interval / ctx.timeout are mixed into the Context prototype and cleaned up automatically with the fiber); both polling and auto-dismissing toasts depend on it. Similarly, the Host half keeps inject: ['timer'] (the Host-side timer is guaranteed by @deepseek-ai/cordis-plugin-timer, which is auto-loaded at profile startup).

2. Git Hook: No Committing a Broken Bundle (Install Once)

pwsh -NoProfile -ExecutionPolicy Bypass -File tools/install-hooks.ps1

After installation, every git commit automatically runs tools/check-client-bundle.ps1:

  • node --check validates the syntax of plugin/client.js / plugin/host.js;
  • blocks any non-comment reference to module / exports (i.e., the pattern that would lock out DSH).

A failed check rejects the commit outright, preventing regressions at the source. You can also run it manually: pwsh -NoProfile -ExecutionPolicy Bypass -File tools/check-client-bundle.ps1.

3. Emergency Switch: If It Breaks Again, Get Into DSH With One Click

If the plugin breaks startup again, no config change needed — just disable it:

# 禁用撤回插件(自动备份 cordis.patch.yml),然后重启 DSH
pwsh -NoProfile -ExecutionPolicy Bypass -File tools/recall-killswitch.ps1

# 恢复撤回插件,然后重启 DSH
pwsh -NoProfile -ExecutionPolicy Bypass -File tools/recall-killswitch.ps1 -Action enable

How it works: add/remove disabled: true on the recall-unread entry in ~/.dsh/profiles/web/cordis.patch.yml (the loader skips disabled entries and does not import that plugin).

After modifying plugin/client.js, remember to redeploy it to ~/.dsh/profiles/web/node_modules/dsh-recall-unread/ and restart DSH.

📦 Changelog

  • v1.1.0 (2026-08) Removed the Amadeus launcher dependency: deleted the 🧩 menu entry and the client-side Amadeus polling; the plugin is now active as soon as it is enabled (the enable/disable toggle in the plugin marketplace/management page controls loading).
  • v1.0.1 (2026-08) Anti-lockout hardening: the bundle completely removed module/exports references (the factory now returns the export directly); added a ?.load registration guard; kept inject as ['slots','timer'] with a Proxy access warning; added a git hook validation and a one-click emergency switch script.
  • v1.0.0 (2026-08) First runnable version: Host RPC recall + Client unread message strip.

📄 License

MIT

Compatibility

DSH 0.1.5-rc.2: worksDSH 0.2.1-rc.3: failedDSH 0.2.1-alpha.3: failed

Versions

Latest versionPublishedSize
1.1.0——
1.2.0——

Comments

Loading…

Similar plugins

dsh-message-recall

by kyle123740

每条消息可撤回 / 删除 / 删除此处及之后 —— DSH 插件(append-only 墓碑,模型上下文与界面同步)。Per-message recall & delete for DeepSeek Harness. Requires dsh >= 0.1.7.

Development & InfrastructureSessions & MessagesManifest valid

★ 3

↓ 37/wk

MIT

JavaScript

Oct 23, 2026

dsh plugin --profile web add dsh-message-recall

by viplocco

DeepSeek Harness 消息级删除插件,用于避免用户误发或错误的助手消息污染会话上下文。

Development & InfrastructureManifest valid

★ 3

↓ 58/wk

MIT

JavaScript

Sep 9, 2026

dsh plugin --profile web add dsh-delete-message

by mbj733

DeepSeek Harness (DSH) plugin: edit sent messages and resend (stop an in-flight reply, edit, resend), plus branch-based edit / reroll / retry and a version timeline.

Manifest valid

★ 4

↓ 35/wk

MIT

TypeScript

Sep 9, 2026

dsh plugin --profile web add dsh-edit-resend

by EvannZhongg

A DeepSeek Harness plugin that keeps the exact text of user-authored messages that compaction has shadowed, and re-injects them as a budgeted runtime-context snapshot.

Manifest valid

★ 0

MIT

TypeScript

Oct 18, 2026

dsh plugin --profile web add dsh-lossless-anchors

by tianyaojiudi-prog

DSH(DeepSeek Harness) 插件:把一段可在设置页随时改写的文字,作为全局系统提示词段注入到所有会话,含子代理与工作流内部子代理;文本与开关即时生效,无需重启。

Tools & CapabilitiesManifest valid

★ 9

MIT

JavaScript

Oct 4, 2026

dsh plugin --profile web add dsh-djy-xttsc

by XSJUSTC

DSH (DeepSeek Harness) conversation rewind plugin - rewind to any user message, interrupt a running turn, hide the tail from chat view and model context, cancel freely before sending.

UI & ExperienceManifest valid

★ 11

MIT

JavaScript

Sep 22, 2026

dsh plugin --profile web add @xsj/dsh-rewind