gloss
gloss /ɡlɒs/ n. 夹注——为解释某段文字而加的短注。
A DSH client plugin: gloss passages while reading a long answer, let the notes accumulate in the composer draft, then send them all in one message. The model replies point by point, quoting each passage you marked.
gloss 把「读完长回答 → 记住想问什么 → 再打一大段字」变成:
选中一段 → 写一句 → 继续读 → 读完全部按一次 Enter 提交。
状态
- P0 / MVP,个人日常使用中。
- 在 DSH Desktop 0.2.1-rc.5(Electron 44.7.0) 上验证;依赖 DSH 的半公开客户端契约,升级后可能需要回归(见兼容性与风险)。
- 端到端真实链路已验证过一次:两条夹注 → 自动累计 → 同一条用户消息提交 → 模型按编号回应(2026-11-11)。
- 文件预览批注(右栏打开的 Markdown / 代码 / 纯文本)已实现,依赖 DSH 0.2.2-rc.1 的
sidebar.right.tab.document.actions槽位与data-textpreview-body正文容器;页面手测待做。 - 改名后的构建(
@local/gloss)还需页面手测一轮;本仓库代码 = 改名后的代码。 - 无网络请求、无遥测;批注在提交前只存在于本地输入框草稿 / localStorage。
功能
- 划词即批注:选中助手回答里的任意文字 → 选区旁出现「+ 批注」→ 写问题 / 想法 / 只标记。
- 自动累积:每条夹注自动写进输入框草稿里一个带标记的批注块;继续读、继续加,块持续累积。
- 一次提交:读完按一次 Enter,块作为一条普通用户消息发出;模型看到的是「编号 + 轮次 + 引用原文 + 批注」。
- 托盘:输入框下方「✎ 批注 N 条」,可展开、跳回原文轮次、编辑、删除、清空、切换自动同步。
- 文件预览也能批注:右栏打开的 Markdown / 代码 / 纯文本预览里选中文字,出现同一个「+ 批注」;位置自动带上「文件 + 章节」。
- 托盘区分来源:文件批注显示文件名(悬停看完整路径),点 ↗ 会滚回预览里的原文。
- 不打断阅读:保存后不抢焦点、不滚动(写入走 DSH 草稿接口,不聚焦输入框)。
- 防破坏守卫:草稿里有
/命令、@文件引用、正在发送时,不自动改写草稿,转为「待同步」。 - 可恢复:草稿就是唯一事实源;刷新、切会话、发送失败恢复后,托盘都会从草稿重新解析出来。
安装
前置:DSH Desktop(已装并至少启动过一次),Node.js 18+。
git clone git@github.com:toutoudnf/dsh-gloss.git
cd dsh-gloss
node install.mjs
install.mjs会把本目录以link:形式装进当前 profile(默认~/.dsh/profiles/desktop), 往node_modules建 symlink,并在 profile 的cordis.patch.yml追加一行带标记的insert。- 写入前会把 profile 的
package.json/cordis.patch.yml备份到.backup/。 - 换 profile:设置
DSH_PROFILE_DIR=/path/to/profile。 - 装完刷新 DSH 页面。之后改
client.js需要在 profile patch 里制造一次真实内容变化才会触发 Host 热重载,再刷新页面。
另一条官方安装路径是让 DSH agent 用 plugin_manager 的 install_bundle(需审批);本插件未验证该路径。
用法
- 选中助手长回答里的一段文字(或右栏打开的 MD 文件里的文字),点「+ 批注」。
- 选类型(问题 / 想法 / 标记),写一句,
⌘/Ctrl+Enter保存。 - 继续读、继续加。每条都会进输入框草稿,托盘显示数量。
- 读完后按 Enter 一次性提交。生成的消息示例:
====== 批注(DSH 自动收集,请按编号逐条回应)======
1) 位置:第2轮回答
类型:问题
引用:厂商口径称补贴率为 12%
批注:这里的数字是官方口径还是第三方转述?
2) 位置:第5轮回答
类型:想法
引用:可以按「投入-产出-验证」展开
批注:想看看能不能套到我们自己的方案里
3) 位置:文件 调研/2026-10-15-AI证书调研.md
章节:已知限制
类型:问题
引用:价格、政策、名额这类易变信息
批注:这里是不是应该补上调研日期?
====== 批注结束 ======
块外你自己打的字不会被插件改动;发送时一起发出。引用空白折叠并截断到 800 字,单条批注上限 4000 字, 整批上限 20 条。多行内容用「 |」续行编码,解析时还原换行。
文件批注的「位置」是相对工作区路径(拿不到会话 cwd 时退化为绝对路径),「章节」取预览里选区上方 最近的标题、截断到 60 字。旧格式的块(只有「第N轮回答」)仍然能解析。
怎么实现的(一句话版)
纯 Client 插件(Host 半只有空 apply()):shell.overlay 负责选区和输入浮层,
conversation.composer.dock 负责托盘并调用 DSH 的 inputActions.setDraft() 写草稿。
文件预览的路径来自 sidebar.right.tab.document.actions 槽位的 owner prop absolutePath(渲染成隐藏标记),
不接管 Markdown 渲染,所以预览的代码块复制、图片解析、frontmatter 等原生能力都还在。
设计取舍:草稿里的批注块是唯一事实源,托盘只是 parseBlock(draft) 的视图——
DSH 自己会持久化草稿、发送成功即进历史、发送失败自动恢复,所以不需要第二份状态。
细节(槽位、块格式、选区锚定、守卫、失败矩阵)见 docs/architecture.md。
兼容性与风险
| 依赖 | 说明 | 失效时 |
|---|---|---|
inputActions(setDraft / submit) |
会话作用域 slot 的「标准 prop」,DSH 客户端非正式 API | 托盘提示不可写,降级为「复制批注块」手动粘贴 |
[data-chat-turn] DOM 属性 |
聊天行上的轮次号,用于「第 N 轮」与跳转 | 降级为「只按引用原文定位」,不影响批注保存 |
shell.overlay 槽位 |
root 作用域的覆盖层,用于选区浮标 | 备用方案:把浮层挂到 conversation.input.overlay |
[data-textpreview-body] / [data-document-markdown] |
右栏文档预览的正文容器,用来识别「这段文字在文件里」 | 文件批注不再出现,聊天批注不受影响 |
sidebar.right.tab.document.actions 槽位 |
文档预览交给插件的头部槽位,owner prop absolutePath 是文件路径来源 |
位置降级为「文件(路径未知)」,批注仍能保存 |
DSH 版本升级后请先跑一遍「安装后验证」清单。
已知限制
- 真实页面行为仍需在每个 DSH 版本上手测:
setDraft是否滚动/抢焦点、浮层定位。 setDraft是整段纯文本重写:草稿里有@文件引用 chip 或斜杠命令时会拒绝自动写入(宁可暂存也不破坏草稿)。- 多窗口/多标签同会话:草稿各自一份,不保证同步。
- 手动改坏批注块:托盘进入「手改模式」(只读 + 复制),不再自动覆盖。
- 旧标记不兼容:本插件早期用「阅读批注」作为块首标记,改名后改为「批注」;旧草稿里的块会被当普通文本,手动删掉即可。
- 文件批注没有源码行号:预览渲染后的 DOM 不保留「行号 → 节点」映射;要精确行号只能接管 Markdown 渲染器(会丢掉代码块复制、图片解析等原生能力),暂不做,靠「文件 + 章节 + 引用原文」定位。
- 文件批注只在会话内的右侧栏预览生效:批注最终写进该会话的输入框草稿;没有输入框可写的场景仍按原有守卫降级。
- UI 文案目前只有中文:
locale/{zh,en}.json只覆盖插件管理页标题/描述。 - 尚未实现:每轮「批注 N」角标、正文持久高亮、快捷键、右侧栏面板、导出。
开发
没有第三方运行时依赖;React 从 DSH 的浏览器模块表拿。仓库自带两套离线测试:
npm run check # 语法检查(client.js / index.js / install.mjs / uninstall.mjs / tests)
npm test # 纯函数单测:块格式/解析/合并/排序/上限/完整流程
node test-smoke.mjs # 冒烟:ModuleLoader 载入 → factory → apply 注册 → 组件渲染(极简 React 替身)
CI:.github/workflows/check.yml 在 push/PR 上跑同样的检查(无需安装依赖)。
目录:
client.js # 全部插件逻辑(纯函数区 + 选区浮层 + 文件预览路径标记 + 批注托盘 + 样式)
index.js # Host 半:空 apply() + 心跳
package.json # DSH 插件清单(dsh.bundle.patch / dsh.client)
cordis.patch.yml # bundle 自带的启用 patch
install.mjs # 装进 profile(含旧名 @local/reading-notes 残留清理)
uninstall.mjs # 卸载
locale/{zh,en}.json # 插件管理页标题/描述
docs/architecture.md # 设计说明
卸载
node uninstall.mjs
撤掉 profile 里的 dependency / symlink / patch 段,并清掉旧名残留;不删 .backup/。
浏览器端数据:批注块在草稿里(随会话走);localStorage 里只有
dsh.gloss.backup.v1.<sessionId>(误删恢复备份)和 dsh.gloss.auto-sync.v1(开关)。
No comments yet. Be the first to write one.