DSH Annotation
包名:dsh-annotation
English
审阅一段很长的 AI 回复时,最麻烦的往往不是提出意见,而是反复复制原文、解释“我说的是哪一句”。dsh-annotation 让每条意见直接留在对应句子旁边:选中原文、就地写下注解、攒齐多条注解,再通过 DSH 官方输入框一次发送;模型会按“注解 N”逐条回答,并可在回复原有的“注解 N”标签上查看注解摘要。
**交互来源说明:**本插件独立、非官方地复刻了 ChatGPT 的正文注解功能,并将这套体验带到 DeepSeek Harness。复制的是使用流程,不是 OpenAI 的源码、素材、API 或品牌;本项目与 OpenAI 无隶属或官方合作关系。
市场定位:会话与消息。 本插件用于审阅一个 Session 内的助手消息,并通过官方输入框提交带注解的用户消息;它不是主题或通用外观插件。
**宿主要求:**插件 0.9.0(尚未发布)需要 DSH Web 0.1.6-alpha.2。发行包通过 engines.dsh 和同版本线 @deepseek-ai/dsh-* peer 声明这一精确要求;桌面客户端也必须内置该版本。DSH 仍处于预发布阶段,升级前请阅读兼容性说明。
**实现兼容性:**DSH 当前没有助手正文内部 Slot,本插件会原地装饰已有助手渲染器,不占用 assistant-step;用户与 steering 消息仍使用优先级覆盖。
界面预览
整个流程都留在对话里:选中原文、添加一条或多条编号注解、检查草稿,再从熟悉的 DSH 输入框发送。
dsh-annotation 的编号注解、就地编辑器和输入框草稿列表总览
选中真正想讨论的文字,浏览器原生选区仍然保留,随时可以复制。
选中的助手回复原文及添加注解、复制操作
趁上下文还在眼前,直接在原文旁写下意见。
助手回复旁的正文注解编辑器
发送前可以集中检查和调整所有本地草稿。
带原文引用的正文注解草稿列表
暂时不想使用注解时,可在 设置 → 注解 中关闭功能,已有草稿不会丢失。
独立的主设置页面包含功能开关、自动附着、紧凑注解汇总、会话内容隐藏和可选的 Market 更新操作。
DSH 主设置面板中的注解配置
功能
- 在一条已完成的助手回复内选中文字后,弹出带“添加注解”和“复制”两个按钮的小浮条;即使拖选结束、松开鼠标时指针已在正文区域外,浮条也会照常出现。蓝色选区保持不消失,随时可以按 Ctrl+C 复制;点击其它地方或按 Esc 浮条消失。
- 在选区旁直接显示紧凑输入框,右侧只有取消和保存图标。空内容点击外部会关闭;有内容点击外部会保持打开、显示红边并震动,直到选择一个图标操作。
- 输入停止 400ms 后自动保存编辑中内容并显示本地保存状态;刷新后可恢复,但不会因此变成已提交注解。
- 编辑器完整处理中文输入法:组合输入期间的 Enter 只完成选词,组合刚结束产生的同一次 Enter 不保存,普通 Enter 保存,Shift+Enter 换行,组合期间的 Escape 不关闭编辑器;组合输入事件不会传到官方输入框。
- 新增注解保存成功后,等一次微任务加一帧渲染,把焦点和原光标位置交还官方 Lexical 输入框;只有同一输入框的可见文字未变、用户未主动转移焦点时才恢复。保存失败、取消编辑、会话切换、编辑已有注解时不抢焦点,也不覆盖输入框已有文字或文件引用芯片。
- 将两行注解记录分成“待附着”“确认结果/待重试”“权威队列”“已发送”四类,并复用 DSH 官方按钮、状态点、图标、Tooltip 和 Toast。
- 新注解保存成功后默认附加到官方输入框;也可以在插件配置中关闭自动附加,或随时点击标题栏回形针手动切换。切换不会展开列表,也不会立即发送;已附加时,未发送集合会随编辑、删除和新增实时变化。
- 官方输入框是唯一任务输入和发送入口。文字、注解、图片和文件可以一起提交;只有注解时也使用同一发送流程。
- 文字、注解和附件合并发送:内部命令声明
attachments = true,Client 通过带 Session ID 的 commands/execute Remote 发送 DSH 标准图片、文件附件,Host 按附件顺序把持久化图片块和文件块放入同一条用户消息。附件字节和临时文件上传凭据不进入注解 JSON 或命令字符串。
- 发送成功后清空文字和附件并把注解标记为已发送;失败时文字、附件和注解全部保留,重试沿用同一个 submissionId,Host 对相同 submissionId 只采用首次成功结果。
- outbox 只保存附件数量、类型顺序,以及图片的媒体类型和名称,不保存附件字节或临时文件上传凭据。页面刷新后,需要重新选择原附件;重试保留原批次的附件数量及类型顺序,增删附件需要放弃旧记录后重新发送。旧版只记录图片的重试数据仍可读取。
- 斜杠命令自动放行:附着状态下输入以
/ 开头的内容时,插件暂时释放官方输入 claim 并移除零宽占位符,/goal、/model 等命令正常走官方管线;离开命令状态后自动重新附着。claim.submit() 内会再次检查斜杠命令,竞态时直接走带 Session ID 的官方命令 Remote,不创建 outbox、不发送注解、不把注解标记成已发送;命令失败时命令文字、附件和注解全部保留。
- 模型回复逐条对照:Host 提示词要求模型按注解顺序逐条回答、每段以“注解 N:”开头、不合并注解,并在每段前输出隐藏的
dsh-annotation-reply 关联标记、结尾输出 dsh-annotation acknowledgement 标记。Client 保留原有“注解 N”文字,不复制或覆盖,只在能够可靠定位的文字边界内添加透明交互层;标记间的多余空行和同一回复内多批重复编号不会使后续标签错位,同一标记区间内最先匹配的完整标签有重复时则保留普通原文。悬停 300ms 或键盘聚焦显示编号、原文和注解摘要,不阻挡拖选与复制;激活标签会定位原文。
- 回复标记只控制显示:只识别当前会话真实存在的 submissionId + annotationId,未知、重复、伪造和格式错误的标记直接忽略;模型未按格式输出时保留普通“注解 N”文字;acknowledgement 标记才更新“已处理”状态。
- 自定义用户与 steering 节点同时显示总体要求、注解汇总框,并按原顺序展示图片和文件;文件与技能引用保留官方打开操作,图片使用官方缩略图与查看器,文件显示类型图标、名称和大小。
- 支持空内容注解(仅标记原文):选中原文后可以不填内容直接保存,只包含空格/换行时同样按空内容处理;编辑器提示“注解内容可留空,留空表示仅标记原文”,保存按钮在空内容时仍然可用,注解列表、紧凑概览和回复芯片显示“仅标记原文”而不是空白;清空已有注解后保存表示转成“仅标记原文”,删除仍必须使用删除操作;仅标记原文同样计入附着数量并参与发送、重试、已处理确认和逐条回复。
- 汇总条默认开启“紧凑注解汇总”:折叠时靠右、宽度随内容自适应并隐藏最左图标;关闭并保存该设置恢复原长条,回形针和展开按钮仍保留。已附着时显示“注解 ×N”,只统计当前会话下一次发送会携带的注解;新增、删除、附着、取消附着与发送结果实时更新计数,未附着时保留标题与状态。悬停或键盘聚焦折叠标签可查看编号、原文、注解及其状态的只读概览;向上展开后,完整列表与底部汇总控制行扩展为相同的安全宽度,通过 1px 接缝组成一张连续卡片,控制项靠右,概览不再重复显示。展开按钮复用同一个平滑旋转的箭头,列表从右下锚点淡入;减少动态效果时禁用动画。按 Esc 收起列表会把焦点还给汇总标签。窄屏、CSS zoom、内部滚动以及注解、发送和编辑状态均保持不变。
- 模型协议跟随 DSH 中英文环境:创建待发送记录时按 DSH 当前 locale(zh/en,无法识别时回退英文)冻结
protocolLocale,首次发送与重试使用相同语言,重试期间切换界面语言不改变已生成内容,旧待发送记录与已发送历史继续按旧英文协议处理;回复解析同时识别“注解 N:”“注解 N:”“Annotation N:”等格式,实际关联以隐藏的稳定注解标识为准。
- 可选兼容 dsh-focus-chat:未安装时插件正常启动、不等待任何服务;安装后聚焦视图切换时,隐藏消息的原文标记与回复芯片暂停测量、消息重建后自动恢复并按消息标识去重,注解草稿与已发送记录不丢失;兼容逻辑单独封装,适配失败只关闭聚焦增强,不影响核心功能。
安装
要求
- DSH Web
0.1.6-alpha.2(精确版本;运行 dsh --version 检查,桌面客户端还要检查其内置宿主版本)
- Node.js
^22.19.0 或 >=24.0.0
web Profile
如果 dsh --version 与要求不一致,请按下方版本映射选择对应插件发行版,或切换到要求的宿主版本;不要通过强制安装或关闭 peer 检查绕过版本约束。
安装 GitHub Release(推荐)
已发布的 GitHub Release 提供无需本地构建的预构建 Tarball。以下稳定别名指向最新已发布版本,不代表尚未发布的 0.9.0;安装前请核对 Release 的宿主要求。验证 0.9.0 请使用下方源码构建流程:
curl -fL -o dsh-annotation.tgz https://github.com/ruisenbai/dsh-annotation/releases/latest/download/dsh-annotation.tgz
dsh plugin --profile web add ./dsh-annotation.tgz
dsh web
如果 DSH Web 已在运行,请在安装后重启。0.9.0(尚未发布)的目标是 DSH 0.1.6-alpha.2。历史版本映射:v0.8.0 适配 DSH 0.1.5-alpha.1;v0.7.0 适配 DSH 0.1.3-alpha.2;v0.6.0 适配 DSH 0.1.3-alpha.1;v0.5.2、v0.5.1 和 v0.5.0 适配 DSH 0.1.2-rc.1;v0.4.0 适配 DSH 0.1.2-alpha.3;v0.3.0 适配 DSH 0.1.2-alpha.1;v0.2.4 适配 DSH 0.1.1-rc.2。
从源码构建
源码构建需要完整的 DSH 0.1.6-alpha.2 依赖,请先按开发指南准备匹配的依赖并完成检查。未发布到 npm 的依赖必须来自可核验的官方源码或官方产物,并在独立目录中构建、安装;不要把本机 file: 路径或临时锁文件写入发行清单。
打开 DSH Web 页面,在一条已完成回复中选中文字,会出现带“添加注解”和“复制”的小浮条;选区保持可选,Ctrl+C 也能复制。点击“添加注解”打开紧凑输入框,填写意见后按 Enter 或点击对号创建草稿。草稿会出现在官方输入框上方,并默认附加到官方输入框;填写可选任务文本、附加图片或文件后,按官方 Enter 或点击发送按钮,会把文字、注解和附件一起发送。若不想自动附加,可在插件配置中关闭对应开关,之后仍可用标题栏回形针手动附加。附着状态下输入斜杠命令时,注解会暂时让路,命令正常执行,注解不丢失。
设置
独立的 设置 → 注解 页面提供配置表单。“启用 DSH 注解”(enabled)、“新增注解后自动附着到输入框”(autoAttach)和“紧凑注解汇总”(compactSummary)三个注解开关默认开启;下方的会话内容隐藏开关默认全部关闭。修改会先在表单中暂存,点击“保存”后写入 Host 的 dsh-annotation 设置 namespace,并对这个 Host 提供的所有 Session 生效。关闭插件后会拆掉助手渲染器外面的注解层,并恢复用户消息渲染器;选区操作条、数字标记、注解列表、注解操作、隐藏传输视图和输入框附加状态都会移除,同时保留输入框中的可见文本。草稿、编辑中内容、Outbox 状态和已提交历史都不会删除;重新开启后会恢复。关闭自动附加后,新注解只保存为本地草稿,标题栏回形针仍可手动附加。关闭并保存“紧凑注解汇总”只恢复长条布局与最左图标,不改变注解、发送或编辑状态。
“恢复默认”会分别清除对应字段的用户层覆盖,并采用该字段声明的默认值;隐藏开关恢复为关闭。所有设置由 DSH 的 settings provider 持久化。已保存的 localTools 用户层覆盖值被忽略,插件不删除或迁移该值,也不清空已有注解数据。升级时会把旧 inline-comments 设置 namespace 中的用户值迁移到新 namespace,成功后才清除旧值。0.1.3 首次启动时会保留并迁移有效的旧版浏览器启用开关,Host 接受后才删除旧 key。每个 Session 的注解草稿仍按隐私与持久化所述保存在浏览器中。
同一表单的“插件更新”区域只调用 dsh-market dsh-market/update-api/v1 公开同源 API。首次点击“检查更新”时先发现 Market 能力,再检查 dsh-annotation;只有 Market 声明支持时才显示安装、回滚或 Host 重启操作。Market 要求等待新发布版本时,普通更新失败后才提供“仍要更新”。实时激活完成后可刷新页面;由桌面端或运维管理生命周期的 Host 不显示重启按钮。未安装兼容的 dsh-market 时,卡片只提示前往 设置 → Plugin Market,不会调用旧版私有更新路由。
会话内容隐藏
以下 18 个开关默认全部关闭,点击“保存”后生效。它们在主设置面板中使用自适应双栏网格,空间较窄时自动收为单栏。开启后,对应详情不再渲染,只保留不可展开的次数摘要,例如 think x 3、读取 x 2、Grep x 1、Bash x 2;点击、键盘操作或浏览器查找都不能展开隐藏详情,必须关闭对应开关并保存才能恢复。“隐藏全部工具调用与结果”覆盖下方按工具类型的开关;“隐藏其他工具”覆盖其余内置、第三方、MCP 或未知工具名。
| 开关 | 设置字段 | 隐藏内容 |
|---|
| 隐藏思考 | hideReasoning | 助手思考内容 |
| 隐藏全部工具调用与结果 | hideTools | 所有工具参数、结果及嵌套子调用详情 |
隐藏 read / read_image | hideToolRead | 文本和图片读取工具的调用与结果 |
隐藏 glob | hideToolGlob | 文件名匹配工具的调用与结果 |
隐藏 grep | hideToolGrep | 文本搜索工具的调用与结果 |
隐藏 bash / pwsh | hideToolBash | Shell 工具的调用与结果 |
隐藏 edit | hideToolEdit | 文件编辑工具的调用与结果 |
隐藏 write | hideToolWrite | 文件写入工具的调用与结果 |
| 隐藏其他工具 | hideToolOther | web、subagent、workflow、skill、todo、job、第三方和未知工具 |
| 隐藏上下文 | hideContext | 注入上下文与系统提示 |
| 隐藏命令结果 | hideCommandResults | 命令结果消息 |
| 隐藏上下文压缩 | hideCompaction | 自动和手动压缩摘要 |
| 隐藏重试 | hideRetries | 重试通知及原因 |
| 隐藏失败与长度限制提示 | hideErrors | 错误、截断与中断提示 |
| 隐藏图片与文件 | hideAttachments | 消息中的图片和文件附件,不改写正文中的 Markdown 图片 |
| 隐藏已提交注解详情 | hideAnnotationHistory | 用户消息中的注解详情列表,不删除草稿或历史 |
| 隐藏回复统计与操作栏 | hideTurnDetails | 已完成回复的统计及复制、分叉、注解等标准操作;扩展专用操作保留 |
| 隐藏其他详情 | hideOther | 未知内容块和工作流详情 |
助手活动按当前已加载的同一轮合并:每个思考块计一次,每个工具调用(含子调用)按调用 ID 去重后按名称计数,重试按尝试次数计数。按名称隐藏工具时,匹配的工具头部和结果会消失,可见的同级调用仍保留;如果匹配的是拥有子调用的根调用,则隐藏整张根卡片,并在摘要中保留所有被隐藏调用的计数。摘要随流式输出和历史加载更新;用户消息的附件、注解以及轮次外消息的摘要保留在原消息旁。正常用户文字、追加指令和助手正文不会被这些开关删除。
只要任意隐藏开关生效,Chat 临时采用完整正文布局,避免原有 Compact 模式同时隐藏中间正文;关闭全部隐藏开关后恢复当前的 Chat 显示偏好,不修改该偏好的持久化值。这些开关只改变 Chat 展示,不修改会话记录、模型输入或已有注解数据。授权、提问、计划确认、运行状态和历史加载控件保持可用。
任务状态与发送方式
自动附加默认开启,因此新注解保存成功后,回形针会直接进入已附加状态。未附加时,注解保持在浏览器本地并继续可编辑;已附加时,未发送集合会实时跟随编辑、删除和新增,直到官方输入框通过 Enter 或发送按钮提交。提交事务会冻结一份不可变提交内容,只有在命令成功后才清空官方输入框,之后新增的注解归属于下一次任务。点击回形针可手动附加或取消附加,不改动文本、光标或列表展开状态。
插件不会把传输已接受直接显示成已排队。只有独立订阅的 session.projections.faceOf('inbox') 中,next-turn 项的 id 匹配稳定消息 ID 后才显示“已排队”Toast 和撤回操作;next-step 不属于可撤回队列。投影为 undefined 表示尚未同步,不按空队列处理,也不据此推断已排队项目离开。Chat 目标中出现持久化 user/message 后改为“已发送”并移除撤回。失败的事务会保留官方输入框内容、图片和文件、附加状态、不可变提交内容和提交 ID,供稍后安全重试。
无论自动附着开关处于什么状态:斜杠命令都不携带注解,输入法选词都不触发发送,发送失败都不丢失数据。
移除的插件内“整体要求”已有内容,会在第一次成功附加时一次性迁移进官方输入框;只有官方输入框接受附加后,插件存储中的旧值才会被清除。
状态定义
- **草稿:**仅在浏览器中,可编辑。
- **已排队:**已观测到 DSH Inbox 的
next-turn 项,尚未写入模型历史。
- **已发送:**由持久化的注解
user/message 事件重建。
- **已处理:**模型回复明确携带提交 ID 和注解 ID 后才设置。
插件不会根据等待时长、轮次结束或界面时序推测“已处理”。
注解类型
- **普通注解(note):**内容非空,模型根据用户填写的内容回应。
- **仅标记原文(highlight-only):**内容为空或只有空白字符,模型直接检查并回应被标记的原文;不允许因为注解内容为空而跳过该项。旧数据缺少类型时按内容是否为空推断,已发送历史不重写。
配置
Bundle 会插入一个 dsh-annotation 行。可在当前 Profile Composition 中覆盖:
| 配置项 | 默认值 | 作用 |
|---|
commandName | annotation_submit | 浏览器到 Host 的内部传输命令名 |
maxPayloadBytes | 524288 | 解码后 JSON 批次上限;超限拒绝,绝不截断 |
maxAnnotationsPerSubmission | 100 | 单批注解数上限 |
warnSelectionChars | 12000 | 长选区需要额外确认的阈值 |
locateHistoryPages | 20 | 定位原文时最多加载的历史页数 |
Host 与 Client 共享同一个 Cordis 行配置,因此修改 commandName 时两端会保持一致。升级前留下的旧内部命令(inline_comments_submit、inline_annotations_submit)由不可见的兼容别名转发给新处理器,不保留两套业务代码。
协议与兼容
新提交只生成 v2 协议(protocolVersion: 2、source: "dsh-annotation"、注解字段为 annotation、kind 与 protocolLocale);旧 v1 数据继续读取,旧 comment 字段读取后转换成新的内部模型,缺少 kind 时按内容是否为空推断,缺少 protocolLocale 时按旧版英文协议处理。历史消息不重写;旧版 acknowledgement 和回复标记继续识别,新消息只生成 dsh-annotation-* 标记。本地存储使用 dsh-annotation:v1:<session-id> 命名空间,启动时优先读取新存储,否则迁移并校验旧存储,迁移成功后才删除旧数据。详见兼容性说明和数据模型。
隐私与持久化
未发送原文、注解、编辑中内容和重试记录保存在 dsh-annotation:v1:<session-id> 对应的 localStorage 中。当前键不存在时,会把 dsh-inline-comments:v1:<session-id> 或 dsh-inline-annotations:v1:<session-id> 下的有效数据校验、转换、写入新键,成功后才删除旧键。可见存储键继续使用 v1,其中经过校验的数据值采用 storageVersion: 2,旧版值会在读取时迁移。用户通过官方输入框提交前不会发送到 Host 或模型。提交后,原文和注解会进入当前 Session 日志和模型上下文。图片和文件走 DSH 官方附件通道持久化,注解数据中不保存附件字节或临时文件上传凭据。插件不包含分析、遥测或外部网络客户端。详见隐私说明。
模型体验
- **提交前:**不产生 Prompt、Token 或 KV Cache 影响。
- **提交时:**写入一条标准用户消息,包含官方输入框文本、完整批次、稳定 ID、原文、注解、注解类型、结构坐标、协议语言和官方图片、文件附件。
- **逐条回答:**提示词按 DSH 当前语言生成中文或英文协议:中文要求每段以“注解 N:”开头,英文要求每段以 “Annotation N:” 开头,并先输出隐藏关联标记;“仅标记原文”明确要求直接检查并回应对应原文,不允许跳过。Client 渲染前隐藏机器标记,保留可见回复标签,并为能可靠定位的标签提供透明交互层。
- **处理确认:**消息要求模型在确实处理后返回一个列出注解 ID 的 acknowledgement 标记。Client 渲染前隐藏标记,但原始模型文本仍可重放。
- **Token:**成本随完整选区和注解增长;插件不做静默截断。超出字节限制会在入队前拒绝。
- **KV Cache:**Steer 或 Follow-up 与普通用户消息一样改变后续模型上下文。
开发
pnpm typecheck
pnpm lint
pnpm test
pnpm exec playwright install chromium
pnpm test:browser
pnpm test:coverage
pnpm build
pnpm test:profile
pnpm verify:bundle
pnpm publint
pnpm pack
CI 会在 Node 22.19 与 24 上执行类型检查、Lint、单元测试、生产构建、Bundle 验证和 publint。Node 24 任务还会运行 Chromium fixture 回归和独立的真实 profile smoke,并创建包产物。pnpm test:profile 需要先由 pnpm build 或 pnpm verify 生成插件产物;这些是检查要求,不是 0.9.0 已通过验证的声明。更多信息见开发指南、架构和数据模型。
已知限制
- DSH 暂无助手 Markdown 内部 Slot。本插件通过
ctx.slots.entries() 原地装饰现有 assistant-step 组件并合并其 inject,不新增该 keyed 单元,因此与 dsh-smooth-stream 等同类装饰可以组合;user 与 steering 仍以优先级 -100 覆盖。Slot 条目结构变化时需要重新兼容验证。
- 未发送草稿只存在当前浏览器,不会跨设备同步;已发送批次可从 Session 日志恢复。
- 模型确认属于协作协议。模型遗漏或破坏标记时,状态保持“已发送”,不会猜测为“已处理”;模型未按格式输出时,回复中的“注解 N”保持普通文字。
- 页面刷新后,官方输入框中的未发送附件无法恢复;需要按原类型顺序重新选择原图片和文件,或放弃该条待发送记录。
- 归档任务没有活跃输入框,无法附加注解;请在可编辑任务中创建注解。
- CSS Custom Highlight 取决于浏览器支持;不支持时仍可使用编号标记和时间线定位。
- 一次选区必须位于同一条助手回复内,跨消息选区会被拒绝。Markdown 文件链接文字可参与选区与恢复,但识别依赖当前宿主的 DOM;升级时需重新验证,详见兼容性说明。
- DSH 暂无私有命令注册标记,因此经过严格校验的内部传输命令可能出现在斜杠命令目录中;旧命令别名不显示在插件设置页中。
社区
项目采用 MIT License。