DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-edit-regen

i

dsh-edit-regen

Manifest valid

编辑重发:在用户消息气泡上多一个「编辑」,改完从那条消息重新生成

UI (client)hasBundlePatchMachine translated

dsh-edit-regen

DeepSeek Harness 的编辑重发插件:用户消息气泡上多一个「编辑」,改完从那条消息重新生成; 保留的图片与文件随行重传,新会话继承原会话的模型选择。

一个包,两半:

半端文件作用
宿主lib/index.js注册 editRegen 会话动作:授权读回文件字节、定位分叉边界、清理空壳会话
浏览器lib/client.js遮蔽官方 user 消息渲染器,加「编辑」入口与内联编辑器;自己把 remote.editRegen 挂到共享 remote 服务上

不依赖任何 Agent 管理能力:Remote 命名空间由本插件自己的浏览器半端 $mount, 所以单独装它就能用。

安装

项目根目录本身就是可安装的包(lib/ 就在根上),所以两种装法都可以:

# 直接装目录(开发时最省事,link 过去的改动重启即生效)
dsh plugin --profile <名字> add E:/Plugin/发布版/dsh-edit-regen

# 或者打成 tarball 装(发布/给别人的形态)
pnpm pack
dsh plugin --profile <名字> add ./istarry-dsh-edit-regen-0.1.0.tgz

装完重启 dsh 宿主进程并刷新页面——客户端 bundle 在启动时组合。

要求 DeepSeek Harness 0.1.7-rc.2 / 0.2.x(宿主半端只依赖 @deepseek-ai/dsh-typert-protocol、 dsh-session、dsh-attachment,全部作为可选 peer,实例一律来自 dsh 安装本身,不在插件里复制)。

用起来是什么样

  1. 鼠标移到自己的某条消息上,气泡下面多一个铅笔图标;
  2. 点开变成内联编辑器:原文已在里面,光标在末尾,⌘/Ctrl+Enter 确认、Esc 取消;
  3. 上方的图片缩略图与文件卡片可以逐个移除,+ 或拖拽可以补充新文件;
  4. 确认后:会话在这条消息所在的轮次之前分叉 → 留下的附件在子会话里重新落盘 → 模型选择继承过来 → 发送改写后的内容 → 视图切到子会话。

原对话不会被动过,那条消息之后的内容也不会保留(这就是「重发」的语义)。

实现要点(改代码前必读)

分叉切点(改这里之前先读完)

rewriteBoundary 只有一个合法切点:前一个轮次自己的 turn/end。

  • 不能在「下一个 turn/start 减一」处切;
  • 也不能在「seq 减一」处切;
  • 这条消息之前没有已完成的轮次时(它本来就是第一条消息)必须返回 null, 让客户端走「干净新建」。

原因:那条消息之前的空隙里不只有会话开场事件,还有用 queue 模式发消息时写下的 agent/inbox/spliced——它承载着源会话自己的待发消息。在空隙处分叉会把它们原样搬进 子会话的收件箱,子会话的下一轮再把它们当成注入的用户消息发一遍。

症状:编辑第一条消息重新生成,会连着发两次。

这个坑踩过两次:套件里 agent-preset-authoring 的那份 rewriteBoundary 早就改成 lastTurnEnd ?? null 了,而同一份代码在从未被挂载过的独立宿主包里还是老的 openTurnStart - 1 / seq - 1 兜底——独立插件直接复用了后者,于是修复丢了。 两处实现分叉是根因,改语义时两处必须一起改(本插件只有一处,别再分叉)。

附件为什么要重传

文件收据(receiptId)是按会话签发的,不能搬到子会话。所以:

  • 留下的图片:走会话授权的 readAttachment 拿到字节,作为新的 image 内容块发出去;
  • 留下的文件:宿主 readFileAttachment 读回原始字节(用会话事件日志做授权)→ 官方上传通道 remote.fileUploads 在子会话上换一张新收据;
  • 新挑的附件:直接从浏览器上传。

发送被拒就丢壳

分叉出来的子会话只是进了目录、没有被持有。发送失败时会尽力 discardSession 清掉, 所以一次失败的编辑不留痕迹。在会话存储不支持删除的运行时上(比如 0.1.7-rc.2 的 SessionPersistence 就没有删除 API),这一步会返回 edit-regen/remove-unavailable, 前端降级为「留下一个空会话」——功能不受影响,只是多一条空对话。

宿主半端的服务一律用 ctx.get 软取

this.ctx.sessions 这种属性访问是按 fiber 注入检查过的:本插件只 inject 了 attachments,读别的服务会当场抛

cannot get property "sessions" without inject

而且它会被网关包成 gateway/internal 抛到前端,看起来像「远端挂了」。所以除了 attachments 之外一律 this.ctx.get('sessions') / get('sessionQuery') / get('sessionPersistence') 软取。

别在宿主半端声明浏览器服务

客户端包(dsh.client)的宿主行不许 inject slots / locale / workspaces / uiWorkspace / remote——那些服务在浏览器平面上,宿主行永远等不到,插件页就会显示 「等待依赖」。本插件的宿主行只 inject attachments。

仓库结构

四层分开,别混:

dsh-edit-regen/
├── package.json           发布清单(dsh.bundle.patch + dsh.client 都在这里)
├── cordis.patch.yml       挂载补丁:一行 insert
├── icon.svg / locale/     插件页的图标与文案
│
├── src/                   ① 手写源码
│   ├── index.ts           宿主半端:editRegen 服务
│   ├── types.ts           线上请求/返回值类型
│   └── client/            浏览器半端:index / actions / EditRegenView / locales / css
│
├── vendor/typert/         ② 预生成的线上契约(host.js / remote.js,别手改)
│
├── build.mjs              ③ 构建
├── build/                 client / host / platform / tsdown 预设
├── tooling/               构建工具链(独立安装,见下)
│
└── lib/                   ④ 产物(git 不跟踪,构建生成;这个包的运行时入口)

lib/ 是产物:.gitignore 里已经排除,仓库里不留;但本地必须有它才能跑 (main、exports、dsh.client 都指向它)。随时可用 npm run clean 删掉、 node build.mjs 重建。

不要另建 dist/:main、exports、dsh.client 全部按「包根 = 本目录」写的。 以前产物放在 dist/ 时,dsh plugin add <项目根> 会把一个没有 lib/ 的 package 装进去—— 插件页显示「已安装」,两半却都加载不到,气泡上自然没有编辑按钮。

构建

cd tooling && pnpm install     # 首次
cd .. && node build.mjs        # 全量:tsc → 三个 tsdown 目标 → 校验 → 写 lib/
node build.mjs --check         # 只构建 + 校验,不写 lib/
node build.mjs --staging       # 产物留在 .build/out,不动 lib/
npm run clean                  # 删掉 lib/ 与 .build/(回到纯源码状态)

构建做了四件事,顺序不能变:

  1. tsc 预编译宿主:src/index.ts 用了标准装饰器(@Remote(…))和 using,rolldown 只认 legacy 装饰器,直接喂 TS 会把 @Remote 原样留在产物里——Node 解析不了。
  2. lib/index.js:从 tsc 产物打包,清单里声明过的 peer 留成 import,其余内联。
  3. lib/typert.host.js / lib/typert.remote-client.js:把预生成的清单打成自足 文件(连 zod 一起内联)。typert loader 在宿主启动时直接 import() 它,那里没有 node_modules 可依赖。
  4. lib/client.js:CJS 工厂壳 + lightningcss 编译的 CSS Modules,只把模块表里的 名字留成 require()。

校验闸(build.mjs 的 validate()):产物语法(node --check)、宿主只 import 已声明的包、浏览器只 require 平台模块表里的名字。这三种故障都只在部署后暴露。

typert 清单是预生成文件

vendor/typert/host.js / remote.js 由 @deepseek-ai/dsh-typert-generator 从宿主源码生成, 里面硬编码了包名与三个方法名。改了 editRegen 的方法签名或增减方法,必须重新生成, 否则启动时报:

typert-loader: TYPERT manifest names package ... must be owned by the package that exports it

或者网关按旧 schema 校验参数、把新参数判成 gateway/argument-invalid。

工具链单独装在 tooling/

package.json 是要发出去的清单,里面不能出现 workspace: / file: 之外的构建依赖; 所以 tsdown / typescript / lightningcss / zod / @types/* 单独装在 tooling/。 build.mjs 每次会把 zod、@types/* junction 到 node_modules/(rolldown 要从导入方 所在目录解析 zod,编辑器的 @types 也需要)——junction 指向物理目录,指向 pnpm 的符号链接在 Windows 上解析不到东西。

排错

现象看哪里
插件页显示「已安装」,气泡上却没有铅笔先确认 node_modules/@istarry/dsh-edit-regen/lib/index.js 真的存在——装成了没有 lib/ 的目录就是这样:两半都加载不到,但插件页不报错
插件页显示「等待依赖」宿主行 inject 了浏览器服务,或者 attachments 服务没起
页面空白 / 插件不出现node build.mjs --check 看产物;浏览器控制台里 web boot: … did not activate 才是真因
气泡上没有铅笔图标会话在运行中或是子智能体会话(两者都禁用编辑);或官方改了 conversation.chat.node 的注册契约
点了「重新生成」报 editRegen remote is unavailable浏览器半端没有挂上命名空间:确认 lib/typert.remote-client.js 存在,且 dsh.client 行是「运行中」
点了「重新生成」报 cannot get property … without inject宿主半端直接读了 ctx.<服务>,改成 ctx.get('<服务>')
重发报 attachment-invalid那条消息里的文件不再被该会话引用,或超过 128MB 读回上限
报 edit-regen/remove-unavailable运行时存储不支持删除会话(0.1.7 就是),属预期降级

许可

MIT,见 LICENSE。

Comments

Loading…

Similar plugins

dsh-message-edit

by lxl8182

DSH Web 用户消息编辑重发插件:改掉某一轮提问重发,该轮之后的内容丢弃,原会话归档(新会话继承逐字节相同前缀以保住 prompt 缓存)。

Manifest valid

★ 0

MIT

JavaScript

Sep 30, 2026

dsh plugin --profile web add dsh-message-edit

by huangmiuXyz

Right-click any user message to edit it and retry from that point — a client-side plugin for DeepSeek Harness (DSH). · 右键编辑任意一条用户消息并从那里重试。

Manifest valid

★ 0

MIT

JavaScript

Oct 21, 2026

dsh plugin --profile web add dsh-edit-retry

by Arbeiter-bit

Double-click any of your own messages to rewrite it and resend from that point; the original conversation is untouched.

Development & InfrastructureTerminal & ClientsSessions & MessagesManifest valid

★ 1

MIT

JavaScript

Oct 10, 2026

dsh plugin --profile web add dsh-reedit

by Moeblack

DSH 插件:分支式消息编辑、重掷、重试与版本时间线 | DSH plugin: branch-based message editing, reroll, retry, version timeline

Sessions & MessagesManifest valid

★ 53

↓ 418/wk

TypeScript

Aug 16, 2026

dsh plugin --profile web add dsh-message-edit

by SpookySandwich

DSH 消息编辑插件:编辑已发送的消息并从该处分叉对话,气泡下方带版本计数与树状视图。Edit a sent message and branch from that point — version counter, tree view, placement presets.

Sessions & MessagesManifest valid

★ 25

↓ 686/wk

NOASSERTION

JavaScript

Oct 5, 2026

dsh plugin --profile web add dsh-plugin-message-edit

by zouxiaoyang

Codex 风格消息原地编辑 DSH 插件:hover ✎ 编辑 → 同会话截断并重新生成回复(surface replacement)

Development & InfrastructureManifest valid

★ 0

MIT

JavaScript

Sep 5, 2026

dsh plugin --profile web add dsh-message-rewrite