Skip to content

feat(message-edit): 编辑已发送的消息并重新发送(关联 #319) - #320

Draft
JunieXD wants to merge 1 commit into
ECNU:mainfrom
JunieXD:feat/message-edit
Draft

JunieXD wants to merge 1 commit into
ECNU:mainfrom
JunieXD:feat/message-edit

Conversation

@JunieXD

@JunieXD JunieXD commented Nov 14, 2026

Copy link
Copy Markdown
Contributor

问题与修改

关联 #319。DSH 不支持编辑已发出的消息:会话记录只能追加,用户消息的按钮行也没有插件扩展位。本 PR 新增公共插件 @eduwork/dsh-message-edit(packages/dsh-message-edit),不修改 DSH 的 Runtime 或界面 bundle:

  • 入口:用户消息的复制按钮旁加铅笔按钮。DSH 没有给这一行留扩展位,插件通过 conversation.chat.user.before 入口找到所在行,再把按钮挂进这一行的按钮栏。点击后,消息气泡原地换成编辑框:Enter 发送,Shift+Enter 换行,Esc 取消,输入法选词时不抢键。
  • 重发:从这条消息所在轮次之前分叉(切点沿用 DSH 主机省略切点时的规则),清掉切点前继承的排队消息,再把改过的消息作为新对话的下一轮发出。成功后新对话接替原对话:用户改过的标题带过去,置顶的继续置顶,正在看原对话的跳到新对话,原对话移进归档。分叉后发送失败时,归档这个空的新对话;连接中断、无法确认是否已发出时,保留新对话并提示用户。
  • 附件:原消息的图片和文件可以逐个移除,也可以选择、粘贴或拖入新附件。新附件先上传到原对话,和原生输入框一样先校验,校验不过时还没有分叉。发送时,主机端 Remote eduworkMessageEdit/stageAttachments 在主机内把附件登记成新对话的上传凭证,内容不经过浏览器。存储引用按 DSH 自己读附件的规则处理(session/attachment 也是按引用读、不查历史),这次调用读原对话、写新对话,所以访问控制两个对话都检查;owner 以外的调用方需要访问策略明确放行这个方法。
  • 引用其他对话:DSH 存消息时只留 @标题 文字,被引用对话的快照另存一条,直接重发会丢掉引用。编辑框按位置跟踪每个引用,发送时还原成 DSH 的引用格式,让新对话重新抓快照。规则是拿不准就去掉:改动、删除或用同样文字覆盖了引用,引用就去掉,不会把用户删掉的引用发出去。编辑框下方显示“引用会话 · …”。
  • 插话:插话是生成过程中加入的,那时可能已经执行了工具,没法从中间重来,所以不能单独编辑。插话下方显示不可点的铅笔,提示去编辑这一轮开头的消息;编辑开头那条时,编辑框提示“这一轮还有 N 条插话,发送后会一起替换”。DSH 的插话行不渲染上面那个入口,这个铅笔由常驻的 shell.overlay 组件找到插话行再挂上去。
  • 草稿:放在 React 外面保存,因为对话列表是虚拟滚动,行滚出视野会卸载。滚动、切换对话后草稿和上传都在。同一对话可以同时开多个编辑框:发出一条后,新对话里仍有的消息,草稿(包括还在上传的附件)跟着搬过去,其余关闭。同一对话一次只发一条,其他编辑框提示等待。
  • 生成中、子代理对话、没有分叉或发送权限时,铅笔不可用或不显示。
  • 包维护脚本、CI 和 docs/PACKAGES*.md 加入这个包。构建和测试通过 EDUWORK_MESSAGE_EDIT_RUNTIME 使用锁定的 DSH 0.2.2-rc.1 Runtime。

已实现:上面这些。计划(不在本 PR):npm 发布后另开 PR 接入桌面装配;用户消息按钮行的扩展位可以向 DSH 上游提议(MessageIconActions 已有 extraActions 参数),有了以后改用正式入口。

验证

  • node scripts/packages/manage.mjs check dsh-message-edit(Node 24.22.1,锁定 Runtime):16 项通过。覆盖分叉切点、引用的定位和跟随编辑(结果交给 DSH 自己的引用解析器核对,含转义、前缀重名、粘贴覆盖、删除方向、撤销等),以及附件重新登记、错误转换、两个会话的资源声明。

  • node --test tests/package-maintenance.test.mjs tests/ci-changes.test.mjs tests/eduwork-source-audit.test.mjs:22 项通过;pack dsh-message-edit 归档检查通过。

  • node scripts/browser-test.mjs(包内本地验收,不进 CI):在锁定 Runtime 上起独立的 DSH 网页版,接入合成模型,DSH 数据、HOME 和默认工作区都放在输出目录。23 项通过,控制台无报错。覆盖:

    • 编辑中间消息后,新对话只保留它之前的历史,原对话在工作区归档列表里,记录仍在;
    • 生成中铅笔不可用,插话铅笔和提示,插话随所在轮次一起被替换;
    • 移除原图片、保留原文件、新增文件;
    • 引用保留和删除;
    • 三个编辑框(发送中其他编辑框等待、草稿搬移和关闭);
    • 同一时刻点两次发送只新建一个对话;
    • 刷新后每条用户消息都有铅笔。
  • 本机真机验收(本地 QA 应用 0.4.12,DSH 0.2.2-rc.1,学校模型):用原型做过 8 组真实发送,都通过:

    • 编辑后再编辑;
    • 改中间消息保留前面的上下文;
    • 新增文件和图片被模型读到;
    • 生成中不可编辑;
    • 停止生成后编辑;
    • 保留标题和置顶;
    • 编辑带引用的消息后,模型直接用快照答对。

    搬进 packages/ 后,主机 Remote 增加了原对话参数;本 PR 的构建已注入 QA 应用做过冒烟检查(铅笔、编辑框、无报错),没有再做真实发送。

  • 未执行:Windows 和桌面装配验收(本 PR 不改装配)。

兼容性与后续事项

  • 新包,peer 范围 DSH >=0.2.2-rc.1 <0.2.3-0,只在 0.2.2-rc.1 上验证过。
  • 依赖 DSH 的几处页面结构:conversation.chat.user.before 所在行的 [data-clock] 按钮栏、data-chat-flow-kind="steering"。DSH 改了这些时,铅笔可能不显示,不影响对话本身。
  • 与 feat(auto-approval): 越界申请的自动审批插件(关联 #283) #317 都修改了包目录、CI 和包数量的断言,后合并的一方需要同步一次。

Add @eduwork/dsh-message-edit. A pencil next to each user message opens
an editor; sending forks the conversation just before the message,
sends the edited message as the branch's next turn, and lets the branch
replace the original, which is archived unchanged.

The editor keeps the message's attachments, removable one by one, and
accepts new ones, uploaded before any branch exists. A Host Remote
re-stages stored attachments into the branch, with access control
checking both conversations. References to other conversations follow
the user's edits. Steered messages show an unavailable pencil, and
editing their turn says they are replaced too.

Register the package for checks and publication. Its build and tests
resolve DSH packages from the locked 0.2.2-rc.1 Runtime; a local
browser acceptance runs the main scenarios against a synthetic model.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant