# 更新日志 ## 说明 - 本项目自 **1.6.3** 起把版本历史集中到本文件;此前的历史散落在各版本的 `RELEASE-NOTES-v*.md`(仓库外)与 git 提交里。 - **`v1.6.0` 与 `v1.6.1` 没有对应 tag**:npm 上从 1.5.5 直接跳到 1.6.2。这两节的内容 来自它们各自的发版说明,日期无从查证,故照实省略。 - `package.json` 的 `version` 与 `client.js` 的 `PLUGIN_VERSION` 必须相等,自检 (`npm test`)会强制这一点。 - 版本日期取该 tag 的提交日期(`git log -1 --format=%ad --date=short `);取不到就 省略日期,绝不编造。因此 1.6.0 / 1.6.1 两节没有日期。 - 1.5.0 之前的版本没有发版说明,条目只能从 git 提交信息归纳,故较简。 ## [1.6.5] — 2026-10-18 ### 文档 纯文档版本:把修正后的 README 推到 npm(registry 不能事后改已发布版本的 README, 只有发新版才会更新包页与包内文件)。代码无改动,只有版本号跟着走。 - **修正桌面端安装说明**:旧文档让读者把 `--profile web` 换成 `--profile desktop` 再跑 `dsh plugin`,但桌面端 profile 由应用独占管理,命令行一律被拒 (`profile "desktop" is managed exclusively by the Electron application`)。现在改成 应用内安装:侧栏 **插件** → **添加插件**,把包名填进「包名或地址」,点 **安装**, 装完彻底退出并重开应用;附两张界面截图(`docs/images/desktop-add-plugin.png`、 `docs/images/desktop-plugin-market.png`)。`web` profile 的命令行安装保持不变。 - 常见问题补一条该报错的解释;「设置页不见了」「卸载」补桌面端分支。 - 页首徽章行加 Awesome DSH Plugin 徽章(本插件已收录于 [awesome-dsh-plugin.com](https://awesome-dsh-plugin.com/p/hawkongz/dsh-task-reminder/)) 与 powered by dsh 徽章;「开发与相关文档」补一行收录说明。 - 删掉解释性噪音:不再在安装段解释 profile 归属机制,只留做法。 ## [1.6.4] — 2026-10-17 ### 修复 - **不再把"日志还没落盘"误报成完成**:停止分类改成三态——拿到本次回合 `turn/end` (closed)、只看到比它更新的 `turn/start` 说明本次结束还没落盘(unclosed)、完全读不到 (unreadable)。unclosed 会等会话事件流把 `turn/end` 送上来;到截止仍等不到就**不弹窗、 不响提示音**(只记 `stats.suppressedUnclosed`),不再猜成完成。只有 unreadable 才走 完成兜底。 - **兜底之后迟到的分类会纠正**:unreadable 先按完成报之后,迟到的 `error` 仍会替换成 错误通知(原有);迟到的 `aborted` / `blocked` / `interrupted` 现在会**撤掉那条兜底 完成通知**、不补错误(1.6.4 起),不再留一条"其实已经被取消"的完成弹窗。 - **修「上一轮刚停、新回合马上开始」时的新回合双弹**:分类三态、在途守卫与回合号判据的 交接重新对齐,同一个停止不会在慢路径与事件重放之间各报一次。 - **修当前 DSH 上一键升级必然失败**:当前宿主(0.2.1+)在 HMR 存在时对已安装的包拒绝普通 `installBundle`(already-installed),官方升级路径是 remove+install。插件现在先 install, 遇 already-installed 自动走 `removeBundle → installBundle`;两步都失败时会尝试装回当前 版本,尽量不让 profile 停在"删了没装回"的状态。 - **修自定义音效「清除」失败时假装成功**:IndexedDB 删除失败会如实提示,不再出现"设置页 显示已清除、下次启动文件又回来"。 - **修同一毫秒内两条通知互相替换**:通知 tag 加了单调序号。同一毫秒里连发的两条不再共用 tag,避免 Windows 上后一条替换前一条、而被替换的那条点不动(electron#29461)。 - **同类型多条通知都保住点击**:页面级保活表以前按类型只留最近一条,同类型第二条到达后 第一条失去强引用、点击送不到页面。现在按对象身份逐条保活(上限 20 条),点击 / 关闭 / 等待消散时按身份释放;卸载时还会按 tag 收掉带按钮的审批通知。 - **修通知权限提示与真实状态脱节**:文案不再假设"已经发过申请",只说明尚未授权、点按钮申请。 - **清理等待类 / 审批通知的残留**:插件热重载、等待消散、会话消失时,页面级保活表与通知 中心里的陈旧条目收得更干净。 ### 变更 - **停止边沿快路径(0-RPC)**:会话正被 DSH retain(用户正在看)时,直接同步读事件窗口, 弹窗与提示音在停止边沿的同一个同步段里发出,不再先等一次 RPC。 - **未 retain 时改为事件驱动**:一次 `sessions.using` 拿到绑定后订阅会话事件流等 `turn/end` 落盘,去掉原来 3×120 ms、最多 4 次 RPC 的轮询重试。 - **卸载回收加固**:热重载 / 停用后,在途分类、等待落盘的订阅、兜底定时器都不会再往已经 卸载的实例上弹窗、放音。 - **宿主定时器与 helper 清理**:唤醒补发的定时器与 PowerShell helper 子进程在卸载时统一 收掉,不再留孤儿进程 / 定时器。 - **检查更新增加总超时与响应体大小上限**:某个源挂住、或回了异常大的页面时,整次检查有 界,失败如实写原因;升级结果无论记成 `restart-required` 还是 `applied`,设置页文案都 不变(仍是「重启 DSH 后生效」)。 - **新排障计数**:`stats.suppressedUnclosed`(判断为 unclosed、等到上限仍静音的停止数)、 `stats.lateCorrections`(兜底之后被迟到分类纠正的次数)。 - **提示音生命周期加固**:卸载后 `chime` 置 closed,迟到的解码 / 播放路径不再新建 AudioContext、不再排音;用户手势预热只 resume 一次(旧实现两次);`touchend` 也算手势。 - **设置页与更新状态机的小修**:更新请求有总超时(15 s)与「200 但非 JSON」的可读兜底、 在途重复点击不再发第二个请求;自定义音效写盘与解码试听并行(解码成功即可先试听,写盘 失败保留旧文件继续用);清除失败保留原文件继续播放、只如实提示;音量按 5 的步进对齐; 点「通知语言」里已选中的档不再把 auto 静默钉住。 - **代码收敛**:按钮样式抽公共基座、设置页订阅抽 `useStore`、权限申请抽 `requestNotifyPermission`、更新动作抽 `runUpdateAction`、`switchRow` 支持可选说明; 删除无读者的 `NOTIFY_KIND_ERROR` 诊断出口、客户端 `UPDATE_IDLE.registry`、音效表里的 `id` 与 `customMeta` 的死分支。三套自检共 **673 条断言**(契约 20 + 浏览器半侧 551 + 宿主半侧 102)。 ### 文档 - `docs/how-it-works.md`:第 3 节重写分类三态 / 快路径 / 迟到纠正,第 8 节补提示音与 分类的关系,第 11 节补两步升级与 already-installed,第 12 节更新「有意保守」的说法。 - 修正一处文档错误:「本地开发安装」「没有插件管理服务」两态的按钮实际会退化为「检查 更新」(只再查一次),不是「无按钮」。 - README(中英)只同步「检查更新与一键升级」与「一次停止只提醒一次」的新语义,不改编排。 ## [1.6.3] — 2026-10-08 ### 文档 - README 重写为面向用户的中文版;原英文 README 移为 `README.en.md`;删除重复的 `zh-CN/README.md`。 - 新增 `docs/how-it-works.md`:把实现细节从 README 搬过去(停止分类、三通道检测、 回合号去重、点击落点、通知标签、审批按钮桥、自定义音效存储、检查更新的双源双传输、 桌面端唤醒策略、设置持久化键),信息只搬家不删除。 - README 配图用**真实弹窗截图**(`docs/images/`,中英各三张:完成通知、审批通知带「同意 / 拒绝」、一直挂着的通知),不用示意图。 - `CONTRIBUTING.md` 新增「自检」一节(接手原 README 的自检说明,含 Linux 上模拟 Windows 链路的办法)。 - `package.json` 的 `files` 同步:加入 `README.en.md`、`CHANGELOG.md`、`docs/how-it-works.md` 与 `docs/images`,去掉 `zh-CN/README.md`。 - 新增本文件。 ## [1.6.2] — 2026-10-08 ### 修复 - **通知 tag 回到「每条独立」**(1.5.5 的行为)并去掉 `renotify`:「按类型固定 tag」会让 新横幅替换掉上一条,而被替换的那条在 Windows 通知中心里点不动(Electron 在 Windows 上 不投递通知中心条目的 click,electron#29461),现场表现就是「点了通知窗口抬不起来」。 - **去掉「完成未读」电平补漏**:它是唯一真正依赖宿主字段 `uiSession.sessionStatus.completionUnread` 的检测逻辑。完成检测回到纯 running 边沿 (三通道共用一张表)+ 1.5.4 的回合号判据。 - **桌面壳(`dsh-app://`)里审批通知强制退回普通通知**,不走 Service Worker 转信那条点击 链路(桌面端「点通知抬窗」是命脉,普通 `onclick` 才是验证过的)。 - **修「反复抢前台」**:桌面端唤醒的补发梯子从 `0/700/1400/2400/4000ms` 五次收成 `0/700/2200ms` 三次,并改成**成功就停** —— 前台助手退出码 0 表示收尾时目标窗口已经是 前台,宿主拿到这个信号就把剩下的补发全部作废;助手动手抢之前也先看一眼是否已经在前台 (最小化的不算,照样 restore),并把 `alreadyForeground` 写进 raise 日志。 ### 变更 - 清掉恒假的 `window` / `document` 守卫,补上卸载守卫。 - CI:宿主自检在 Linux 上也能跑,发布门不再只对 Windows 成立。 ### 文档 - 对齐 1.6.2:设置表补齐、清掉已删功能的描述、版本号示例刷新。 ## [1.6.1] ### 修复 - **审批通知正文改为「工具名 + 理由」**:宿主侧审批交互(`PendingApproval`)不带 `questions` 列表(那只有提问 / 方案待确认的 `PendingQuestion` 才有),详情在 `toolName` / `reason` / `displayReason` 上,旧代码只认 `questions[0].question`,于是正文恒等于会话名。 现在 `displayReason` 按**通知语言**取对应键(取不到退回 `en`,再退回未本地化的 `reason`),拼成 `工具名:理由`(中文用全角冒号,English 用半角冒号 + 空格);工具与理由 都拿不到才退回会话名(它只是兜底)。 - 所有等待类正文按固定字数(160)截断并加省略号,截痕可控。 ## [1.6.0] ### 新增 - **审批通知上直接裁决**:审批弹窗带「同意 / 拒绝」两个按钮,点一下调审批对象自己的 `answer('allowed-once' | 'rejected')`(与审批卡片同一个方法,「同意」=「允许一次」), 裁决时不把窗口拽到前台。带按钮的通知只能由 Service Worker 弹,因此这份 `client.js` 同时 被注册成插件自己的 worker(脚本 URL 取自 `window.__DSH_BOOT__.entries`),文件顶部新增 双上下文外壳。 - **通知语言开关**:设置页新增「通知语言」,只有简体中文 / English 两档,落 `dsh.task-reminder.notify-language`;「跟随界面」是默认行为、不再单列一档,且只影响通知 文案(标题、正文、按钮文字),设置页本身永远跟随界面语言。 - **完成补漏**(1.6.2 已移除):宿主在后台会话「跑完但没打开过」时亮起 `completionUnread` 电平,用它补报页面刷新 / 插件热重载期间跑完的会话,同一段未读只补一次。 - **设置页底部「检查更新」**:显示当前版本 + 一个按钮(没查过是「检查更新」,查到新版变 「更新到 vX.Y.Z」,更新完成变「刷新页面」),状态机七格(idle / checking / latest / available / updating / done / failed),不持久化。 - **升级交给 DSH 自己的插件管理服务** `pluginManager.installBundle`(不自己拼 `pnpm` 命令行),走 `restart-required`:新版本落盘、不动正在跑的树。 - 宿主半侧新增两条 Connection 精确 Fetch 路由:`POST /api/task-reminder/update-check` 与 `POST /api/task-reminder/update`(都永远回 200 + JSON,失败写在 `error` 里)。 - 新增 `test/verify-host.mjs`(31 条)。 - 新增控制台助手 `__dshTaskReminder.focusQuestion()`(不点弹窗,当场对当前会话再跑一次定位 步骤)与 `__dshTaskReminder.report()`(一行打出上次跑到哪一步 + 该步依赖的 DOM 实况)。 ### 变更 - **点通知的落点从「对话底部」改成「你这次提问的位置」**:把会话流列 `[data-chat-flow]` 里 `[data-chat-flow-kind="user"]` / `"steering"` 的最后一行对到视口顶部下方 24px(与应用 自带的「跳到第 N 轮」同一个落点);三类弹窗(完成 / 出错 / 等待操作)统一用这个落点。 - **「等你操作」按类型拆成三个标题**:审批请求 / 提问 / 方案待确认各有标题,认不出类型时 退回「等待你的回答」。 - **通知 tag 按类型固定**(1.6.2 已回退为每条独立):等待 / 完成 / 出错各占一个 tag 槽位, 带按钮的审批通知另占自己的槽位;并加 `silent: true`,声音只由插件自己那套负责。 - **设置页文案瘦身**:导语压成三句话;自解释的行不再有说明文字;弹窗时机是例外 —— 两档各 一行写清含义,且从左右并排改成上下排。 - 审批按钮不可用时如实降级:局域网 http、DSH 桌面端(`dsh-app://` 注册不了 worker)、拿不到 bundle URL 时退回不带按钮的普通通知,并在设置页说明;一次点击只认领一条,等待消散或被新 请求顶替时通知自动收掉。 - 注意:所有客户端 bundle 都在 `/plugins/` 路由下,worker 作用域是共享的 `/plugins/`, 同一个 Origin 只能有一个 —— **同类插件只装一个**。 ### 文档 - README(中英)同步:设置表新增「通知语言」、新增「在通知上直接裁决」小节、控制台助手补齐 `test('question' | 'plan-review' | 'approval' | 'error')`、自检说明补齐新用例。 ## [1.5.5] — 2026-10-02 ### 文档 - 新增「全屏时看不到横幅」排障条目:前台有全屏应用时 Windows 会隐藏通知横幅(**连优先级 通知一起隐藏**),提醒只进通知中心且退出全屏不会补弹;关掉「设置 → 系统 → 通知 → 请勿打扰 → 在全屏模式下使用应用时(优先级通知横幅也会隐藏)」即恢复。 - 标题下新增两枚徽章:npm 版本与总下载量(中文版用中文标签「下载量」)。 - 补上桌面端安装命令:Quick Start、安装小节与桌面端小节都写明 `dsh plugin --profile desktop add @hawkongz/dsh-task-reminder`,并说明桌面端装完重启 App 即可(不存在浏览器硬刷新那一步)。 ### 变更 - 只有文档变更:插件行为与 1.5.4 完全一致,除版本号外代码逐字节相同;已装 1.5.4 的无需升级 (除非想要包内最新文档)。 ## [1.5.4] — 2026-10-02 ### 修复 - 修「上一轮刚停、你立刻开始新任务,那一轮在 5 秒内跑完时弹窗和提示音都没有」:把「同一次 停止」的判据从 **5 秒时间窗**换成**回合号** —— 停止边沿分类时本来就要读会话持久日志最后 一条 `turn/end`,现在把它的 `data.turn` 一并带出,与每个会话记下的「最近一次结清的回合号」 相等就确定性丢掉(计入 `stats.stopDuplicates`),不同则照常提醒并记下。 - 5 秒窗口只保留给「错误优先」两个方向(error → 完成不报、完成 → error 撤回完成弹窗)与读 不到回合号时的兜底。 - 有意不报的停止(取消 / 询问已报 / 崩溃孤儿 / 询问豁免)也记回合号,它们的重复边沿同样不 会再弹第二条。 - 有意**不**把「`running=true` 就清账本」推广到另外两条通道:那会让会话列表的陈旧回放重新 造出一次停止边沿、弹出第二条;回合号判据本身就把这种回放挡住了。 ### 变更 - 其余行为一律不变:三种停止原因、错误优先、两种弹窗时机、子智能体闸门、询问豁免窗口、提示 音与自定义音效;无配置迁移,值不用改。 - 兜底一侧(有意保守):分类读不到原因(于是也读不到回合号)时按完成报,这种「无号」停止的 重复边沿仍只能靠 5 秒窗口兜着。 - 因 1.5.3 的发布卡在 npm staging(公开索引里一直没出现),本版直接换号为 1.5.4。 ## [1.5.3] — 2026-10-01 ### 变更 - 内容与 1.5.2 **完全相同**,只换了版本号:1.5.2 的 npm 发布在 registry 侧卡在 staging(重发 返回 `409 Cannot publish over previously staged version "1.5.2"`,公开索引里始终没有它)。 - 装 1.5.3 即可;不要装 1.5.2(装不到,当时 `latest` 仍是 1.5.1)。 - 与 1.5.2 相同的修复:完成豁免变成有界窗口(45 秒),且任一通道观测到 `running=true` 立刻 作废该豁免。 ## [1.5.2] — 2026-10-01 ### 修复 - 修「Agent 向你提过问(`ask_user_question` / 计划确认)之后,那一轮真正跑完时既不弹窗也不 响提示音」:完成豁免变成**有界窗口**(45 秒)—— 只豁免「回答完紧随」的那次完成,回答之后 Agent 又干了几分钟活的那次停止照常提醒;并且**任一通道**观测到 `running=true`(会话又跑 起来)就立刻作废该豁免,不再依赖某一条通道必然送达。 ### 变更 - 三种停止、去重、错误优先、弹窗时机、子智能体闸门等其余行为一律不变;无配置迁移,值也不用 改。 ## [1.5.1] — 2026-10-01 ### 新增 - 点系统通知后,会话打开即**自动落到最新的对话内容**(相当于替你点了界面自带的「回到底部」 按钮);三种通知(完成 / 等你回答 / 出错)点击行为一致。 ### 变更 - 实现方式(如实说明):DSH 没有对外暴露滚动接口(`openSession(target)` 不收参数, `ctx.uiConversation` 也没有导航能力),所以插件打开会话后在约 1.4 秒内轮询应用自带的 「回到底部」按钮(只在未跟随底部时渲染),出现就替用户点一下,走应用自己的 `returnToBottom()`,滚动状态机保持一致。 - 按钮一直不出现 = 本来就在底部,什么也不做;将来 DSH 改了 DOM,最多丢掉这一步,**绝不影响 「打开会话」与桌面端的窗口唤醒**;轮询定时器随插件卸载一并取消。 ## [1.5.0] — 2026-09-29 ### 新增 - 设置 → 任务提醒 →「提示音音效」新增第五档 **自定义**:在「自定义音效」行点「选择文件」选 本机音频(mp3 / wav / ogg / m4a 等浏览器能解码的格式,上限 5 MB),选完即按当前音量试听, 并自动切到该档。 - 音频字节存进浏览器 **`IndexedDB`**(本地存储那点配额装不下音频),装载 / 换文件时用 `decodeAudioData` 解码,播放走与合成音效同一个音量增益,首尾各 10ms 淡入淡出防爆音。 - **音频不出本机**:不上传、不进 npm 包,宿主半侧完全不参与;按浏览器 Origin 保存,重启后仍 在。 - **失败一律如实提示并回落第一种合成音效**,提醒不会变哑:超过 5 MB、编码解不开、写入失败 (隐私模式 / 配额满)、浏览器不支持 `IndexedDB`、文件已丢失。 ### 变更 - 「恢复默认」不再删除你的音频文件(只是把音效档写回第一种);要删就在「自定义音效」行点 「清除」。 - 「清除站点数据」或换浏览器会丢,行内会如实提示并要求重选。 ### 修复 - 设置页排版修复:五档控件改上下排,说明文字不再被挤成一列单字;窄窗口下控件自己折行。 ## [1.4.6] — 2026-09-28 ### 新增 - 子智能体会话默认不提醒,改用新增的「子智能体提醒」开关控制。 ## [1.4.5] — 2026-09-26 ### 修复 - 修「被闸门挡掉的停止被响两次提示音」;清掉死导出与恒真检查。 ### 变更 - CI:已发布版本的重复发布改为跳过,而不是弄红构建(registry 索引延迟兜底)。 ## [1.4.4] — 2026-09-26 ### 修复 - 桌面端:点弹窗时把应用窗口抬回前台。 - 诊断信息报告 1.4.4,并对版本漂移加守卫。 ### 变更 - CI:要求 tag 与 `package.json` 的版本一致,并跳过已发布的版本。 ### 文档 - 说明 activation 路由为什么不带前导斜杠。 ## [1.4.3] — 2026-09-22 ### 文档 - 安装说明改为以 registry 安装命令为主(`github:` 作为备选);版本号升到 1.4.3。 ## [1.4.2] — 2026-09-22 ### 修复 - 按 `turn/end` 的 reason 给停止分类;同一次停止的重复报告去重。 ## [1.4.1] — 2026-09-22 ### 新增 - 每种停止都发 Windows 系统弹窗:任务完成、等你回答(`ask_user_question` 挂起)、出错。 ### 修复 - 完成弹窗的合并窗口从 3000ms 收到 500ms。 - 浏览器模块按包名(`@hawkongz/dsh-task-reminder`)注册。 ### 变更 - 改到 `@hawkongz` scope 下发布(npm 认为非 scope 名与 dsh-taskreminder 过于相似而拦截); `publishConfig` 钉住官方 registry。 ### 文档 - npm 包里带上 `zh-CN` README、`CONTRIBUTING` 与 `SECURITY`。 ## [1.2.3] — 2026-09-22 ### 新增 - 首次加载时申请一次通知权限。 ## [1.2.2] — 2026-09-22 ### 新增 - 每次完成都响提示音;授予通知权限后由系统通知取代应用内卡片。 ### 文档 - 安装说明改用 `dsh plugin` CLI(不再用裸 npm);去掉面向用户文案里的内部音量调节细节。 ## [1.2.1] — 2026-09-22 ### 新增 - 首个版本:DSH Web UI 的对话任务完成提醒。