dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
划选回答文字就地加注释:保留原文引用加自己写的备注,每条在草稿里变成一枚胶囊,多条一起随消息发出;两条以上时输入框上方会多一个胶囊用来跳回原文或全部清除。胶囊需另装 dsh-paste-chip,否则每条注释在草稿里是一行纯文本。
划选对话里的回答文字 → 就地写一句注释 → 每条进草稿成为一枚 注释 · N 胶囊,多条一起随消息发出; 两条以上时,输入框上方会多一个 N 条注释 胶囊用来跳回原文 / 全部清除。
示意图(按主题令牌渲染):划选回答里的文字 → 就地写一句批注 → 批注成为注释 · N胶囊随消息发出;两条以上时输入框上方出现N 条注释胶囊,可跳回原文或全部清除。
N 条注释 胶囊:悬停或点击才浮出详情卡(逐条删除、全部清除、点条目跳回原文),平时不占位。只有一条时不出——草稿里那枚 注释 · 1 已经说清楚了,多一个「1 条注释」只是把同一件事说两遍。N 条注释(v0.1.6)那个胶囊原本是「注释只活在面板里」时的唯一入口。现在注释都进了草稿(每枚 注释 · N 都能点开 卡片、✕ 取消),它的不可替代能力只剩两件:
能力 · 草稿胶囊能做吗 跳回原文(注释可能在上千行之上) · 不能:点开是正文预览卡 全部清除 · 不能:只能逐枚 ✕
这两件在「只有一条」时都不需要(高亮就在眼前、清空无意义),所以门槛设在 2 条: 一条不占位,两条以上才提供跳转与清空。
每条注释一行,紧跟在你自己写的文字后面:
〔注释 1〕「你要的是旧版「六根线跳动」的」|备注:这句按旧版改草稿是唯一事实来源:你在输入框里删掉这一行,胶囊里的那条也会同步消失;消息发出去之后同样自动清理。
shell.overlay(整帧浮层,压在对话滚动容器之上),高亮用 Range.getClientRects() 计算、绝对定位覆盖绘制,不改动被选中的 DOM,所以回答流式重绘时不会破坏原文。conversation.input.dock(输入框上方一整条)。inputActions.captureInsertion() / insertText(),失败时回退 setDraft(),最后 submit()。code/strong/em/b/i/span/br,其余标签降级为纯文本),所以行内代码在列表里仍然是代码样式;用户备注保持纯文本。在 Plugins 设置里停用 dsh-annotation,或从 profile 移除该 bundle。
所有状态都按发起划词的那个对话分桶,不再是一份全局单例:
状态 · 归属 · 表现 注释 / 高亮 / N 条注释 胶囊 · 选区所在会话 · 切到别的会话看不到,也数不到 评论框、选区工具条 · 选区所在会话 · 侧栏、菜单、其他列里的划词不弹工具条 旁问弹窗与旁问卡片 · 发起它的会话 · 切走即隐藏,切回仍在;不会出现在别人的对话里 侧边对话标签与写入 · 发起它的会话 · openTab 带该会话的 scope,写入前校验侧栏作用域 侧栏诊断卡 · 发起它的会话 · 只在出问题的那条对话里
会话归属不是猜出来的,也不依赖 id 字符串格式:
([data-conversation-content])。选区落在这篇正文里才认领,会话 id 一律取 slot props 的 sessionId;侧栏、菜单、别的会话里的划词不会被认领。
conversation.chat.turnTail 传入的 sessionId 决定,不是本会话就渲染 null。POST /dsh-annotation/ask 带的是真正发起旁问的会话,fork 上下文不会串。选中文字 → 点「侧边对话」→ 把选中内容(含已排队的注释)复制到剪贴板,并直接开一个 侧边对话标签页(调用 betterSidebar.openTab({ type: 'sidechat' }, { sessionId }), 线程由 better-sidebar 自己创建),随后把选中内容(含注释)直接写进它的输入框。
写入方式:等待侧栏挂载后,只在本文会话作用域内找 class 含 sidechat 的 contenteditable(右栏还挂着编辑器页、以及其他会话停靠的标签,不能按全页抓第一个), 聚焦后用 execCommand('insertText') 写入;若编辑器拒绝,则退化为派发一个 paste 事件。 两条都失败时剪贴板里仍有内容,手动粘贴即可,诊断卡落在发起它的那条对话里。
为什么不能用接口写入:dsh-better-sidebar 的服务只暴露 openTab / closeTab / registerTab 这些面板管理方法,线程创建与发消息走它内部的 ctx.connection RPC, 没有对外接口,插件无法代发。
选中文字 → 点「旁问」→ 弹出模态:标题「旁问这段内容」、可展开的「引用原文」、 「你想了解什么?」输入框,底部是 取消 / 解释一下 / 发送旁问。
发送后模态关闭,回答以卡片形式出现在消息流里(挂在 conversation.chat.turnTail),不是浮在角落:卡片头部是问题、可折叠引用、 下方正文按增量流式追加(POST /dsh-annotation/ask 返回 NDJSON,每帧 {delta},收尾 {done})。卡片只属于发起旁问的那个会话。
host 侧用 subagents.getProvider('fork') 起一次性子会话、下 tools.restrict({allow: []}) 禁用全部工具,回答完即 dispose,不写主会话历史。 这条 fork 流水线参考 @michengai/dsh-btw(Apache-2.0),见 NOTICE。
# 在 DSH 里以本地 bundle 安装(会写进当前 profile 并即时生效)
plugin_manager install_bundle /绝对路径/dsh-annotation安装后划选任意回答文字即可看到工具栏。
注入 dsh-paste-chip 时,每条注释是一枚自己的胶囊(标签 注释 · N),正文存在 paste-chip 里,发送时展开成 〔注释 N〕「…」。多条注释各自一枚,互不覆盖。
两条通道的存活判据不同,别再混用(混用就是 v0.1.2 的「新增一条,前一条就没了」):
通道 · 块正文在哪 · 存活判据 · 改编号 · 删单条 胶囊(有 ref) · paste-chip 存储 · 草稿里还有这枚 ref · paste-chip.replace 改正文 + 整份草稿改标签 · 整份草稿重写,去掉这一枚 纯文本(没装 paste-chip) · 草稿文本 · 草稿里还有这段正文 · 文本替换 · 文本删除 被动折叠(有 paste-chip 但通道失败) · paste-chip 存储,无 ref · 标签里的正文前 12 字 · 改不动,保留旧编号 · 按标签找到那枚再重写
取胶囊服务必须走 ctx.get('pasteChip'):cordis 里直接读没在 inject 声明的服务会抛 cannot get property ... without inject,ctx.pasteChip 永远是 undefined(v0.1.2 的通道 其实一次都没生效过,全部退回纯文本再被 paste-chip 被动折叠)。
插入点要换算成 detect 坐标:胶囊在 clipboard 投影里是整段显示文本,在 detect 投影里只占 1 个字符,直接拿 draft.length 当插入位置会越界。
工具条原来固定落在选区下方 top = end.bottom + 12。选中对话最下面那几行时,它掉到输入框 下面(被输入框盖住或直接出视口),表现是「这个高度选不了、注释不了」。
现在先算一条可用下界:视口内、选区下方、横向与选区重叠的输入框顶边(取不到就退到视口底线), 再决定落点:
情况 · 落点 选区下方放得下 · 选区下 10px(原行为,避免和另一条停在选区上方的工具栏打架) 下方被输入框/视口挡住 · 翻到选区上方 10px 上下都放不下(视口极矮) · 夹进可用区间,不跑出屏幕
输入框里那枚 注释 · N 胶囊,点一下打开的是 dsh-paste-chip 的常驻预览卡片(正文 + 字数 + 「复制全文」)。卡片右上角现在有 ✕,点它就是取消这条注释:对话里的高亮、草稿里的 这枚胶囊一起消失,剩下的注释重新编号。
只认 ✕。这三种都不是「关闭」,注释留着:
动作 · 事件 reason · 结果 点 ✕ · close · 删掉这条注释(高亮 + 草稿胶囊),并弹一条「已取消这条注释」 Esc / 点卡片外部 · dismiss · 只收起卡片 点另一枚 注释 · N 的卡片 · switch · 换预览,旧的注释不动 插件自己删掉注释 · removed · 顺手收掉卡片,避免留一张写着已删内容的卡
订阅走 ctx.get('pasteChip').watchPreview(fn):服务必须用 ctx.get 取,cordis 上下文里 直接读没在 inject 声明的服务会抛 without inject。服务实例换了(热更新)会自动退旧订新。
setDraft({ text, references }):setDraft(纯字符串) 会把草稿里已有的胶囊全部抹掉(Host 的语义),包括用户自己粘贴的那些。
让注释被当成已删除要好)。
activation.result 只给最终结果。node test/boot.test.mjs 验证模块求值、slot 装配、✕ 关闭即取消这条注释,并用一个按 Host 语义写的paste-chip 替身跑「两条注释并存 → 逐条删除 → 编号跟随」和降级通道;真实渲染与交互 仍需重载 DSH 后人工验收。
本项目以 Apache License 2.0 发布,见 LICENSE。
lib/index.js 的旁问 host 流水线改编自 @michengai/dsh-btw (Copyright 2026 MichengAI,Apache-2.0),其许可原文见 LICENSE-dsh-btw, 改动说明与署名见 NOTICE。依 Apache-2.0 第 4 条,这两份文件必须随代码一起分发。