Turn event notifications: six event classes (completed, error, interrupted, approval requested, AI question, limit reached) delivered via sound, system notification, in-page banner, webhook, IM and host desktop-notification channels; when several browser windows are open, only one rings.
Install
# from npm (prebuilt)
dsh plugin --profile web add @mzzsfy/dsh-turn-notify
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:mzzsfy/dsh-plugin#path:/packages/dsh-turn-notify
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
This plugin publishes its README in Chinese only.
DeepSeek Harness 消息通知插件:AI 回合产生六类事件(任务完成/任务出错/异常中断/等待审批/AI 提问/回复被截断),按配置通过声音、系统通知、页内通知、webhook、IM 与后台桌面通知提醒。同源多窗口共享一次呈现,不同浏览器或不同地址独立接收。
快速上手
dsh plugin --profile web add @mzzsfy/dsh-turn-notify
安装后打开 设置 > 消息通知,默认进入「提醒方式」。全部事件默认开启;提示音需先与页面交互,浏览器系统通知需授权并满足系统通知设置。webhook 与聊天(IM)在「外部推送」配置;后台桌面通知在「提醒方式」开启。页内提示与推送总线由公共依赖 @mzzsfy/dsh-common-tools 提供,由 session-manager 插件代挂装载;总线为 client 硬依赖,订阅 WS 总线 @mzzsfy/dsh-turn-notify 插件通道。host/client 在 apply(ctx) 调用 setupCommonTools(ctx),通道身份取 ctx.fiber.entry.options.name 的完整 npm 包名;client 各实例退出时释放自己的订阅,同一 factory 的存活实例接管一次共享通知工作,最后实例退出才中止共享快照并清启动状态;跨 factory HMR 清理旧代。声音通道受浏览器自动播放策略约束,首次点击页面后才会出声。想推到微信等聊天工具,见 IM 推送;想推到自建服务,见 webhook 推送;想在运行 DSH 的电脑桌面接收通知,见 宿主桌面通知。
六类通知事件
插件监听 AI 会话,把回合结果归入六类,每类可独立开关、独立指定声音:
| 事件 | 含义 |
|---|---|
| 任务完成 | AI 回合正常结束 |
| 任务出错 | AI 回合以错误结束,或被你手动停止 |
| 异常中断 | 会话关闭时未正常收尾的回合被补发中断结束(少见),不表示手动停止 |
| 等待审批 | AI 请求工具授权,等你点击允许;回合以等待审批结束也归此类 |
| AI 提问 | AI 调用 ask_user_question 向你提问 |
| 回复被截断 | 回合因输出长度上限结束 |
「通知规则」控制所有通知方式的事件与高级过滤:
- 最短执行时长:所有回合结束类通知(任务完成、任务出错、异常中断、回复被截断,以及因审批阻塞结束的回合)在执行时长严格少于阈值时不发送,默认 5 秒;等于阈值时不因时长被过滤。即时 AI 提问与审批请求不受此过滤。过滤影响所有通知方式,并非仅静音。
- 仅通知主会话:子代理会话(前台或后台委托)自身的事件不通知,保留主会话通知;不表示过滤 Bash 等所有后台任务。
- 减少委托过程通知:仅影响「任务完成」类。回合结束时仍有后台子代理运行,或该回合由子代理收尾后唤醒主会话时,不发送完成通知;出错、审批与提问不受此项影响。这是对委托过程的过滤,不保证整个任务只在最终完成时提醒一次。
声音通知
声音通知是本插件的核心能力,全部在浏览器内完成,不依赖系统音效与音频文件:
- 8 种内置音色:上行琶音、铃铛、清脆双音、警报方波、低鸣、双音提示、嘀嗒、低音下滑。由 Web Audio 实时合成,零下载、零系统依赖。浏览器自动播放策略要求先与页面交互一次(任意点击),首次交互前声音静默,其余通道不受影响。
- 自定义音效上传:支持 wav / mp3 / ogg,可一次多选,单文件上限 2MB、总库上限 10MB。选择文件后进入「待上传」列表,可先逐个试听,点击「上传」后才保存到共享音效库。已上传文件支持重命名;同一文件重复上传自动识别,不产生重复文件。
- 按事件选择音效:在「音效 → 事件音效」为六类事件选择内置或上传音效,例如「任务完成」用上行琶音、「等待审批」用双音提示。删除音效会清除共享配置中的引用,播放时回落内置默认;当前浏览器的独立引用可能保留为失效项,试听时会提示原因。
- 声音开关与分类静音:在「提醒方式」控制通知提示音与页内提示音,两者开关和发声事件独立。通知提示音关闭或某类静音后,页内提示音仍可能发声;系统通知、标题闪烁与页内通知也有独立设置。关闭「通知规则」中的事件则会过滤该类事件的所有通知方式。等待动作的二次提醒另有行为,见等待动作二次提醒。
- 音量:在「提醒方式」按 5% 步进调节 0-100%,通知提示音与页内提示音共用,保存在当前浏览器。
- 音效作用域:事件音效默认共享,存 settings.yaml。开启当前浏览器独立音效后,改动保存在当前浏览器的当前站点(按协议、域名与端口隔离),独立选择优先,未独立选择的事件仍沿用共享音效。关闭后恢复共享配置,独立选择保留,重新开启即可恢复;同一电脑的其他浏览器不共享这些本地设置。
- 试听:事件音效、页内提示音效与音效库均可独立试听。试听验证所选音色及播放能力,不代表事件开关、静默规则与通道路由均已放行。
声音由抢到呈现权的窗口播放,多个窗口打开同一页面时只有一个窗口出声(见 多窗口只响一次)。同页多个插件实例共用当前激活代的音频资源,最后一个实例退出或 HMR 新代接管时移除解锁监听、关闭 AudioContext 并清理解码缓存;旧代迟到的交互和解码结果不会恢复播放。
系统弹窗与页内提示
- 浏览器系统通知:在「提醒方式」开启并授权后,按静默规则与通道路由发送系统通知,标题为事件文本,通知小结作正文。默认在窗口失焦时提醒;关闭专注静默后,前台也可尝试发送。HTTP 非回环地址通常不提供 Notification 能力;通知未授权或不可用时,可用备用标题闪烁提醒,与声音开关无关。Windows 下还受系统通知设置与专注助手约束。授权正常时不显示权限状态;未授权、被拒绝或环境不支持时显示红字,仅未授权时提供申请按钮。测试会延迟发送,需按提示切出窗口。
- 页内通知:页面角落浮出的通知(公共依赖 toast 组件栈式展示,6 秒),前台与后台均可显示,不受专注静默限制。带小结时以第二行呈现,点击可直达对应会话。「提醒方式 → 页内通知」可选「标准浮条」或「主题卡片」,均随亮暗主题切换;选择保存在当前浏览器,新通知、预览与二次提醒即时采用。「预览样式」仅展示视觉效果,不播放声音;声音由独立的试听按钮验证。
- 页内提示音:在「提醒方式」独立开启并选择发声事件;在「音效 → 单独设置页内提示音效」选择音色,未单独选择时沿用事件音效。页内通知显示且通知提示音未播放时补充发声,不受专注静默限制,也可能在失焦时发声;关闭页内通知后不补声。两种提示音共用音量,常规通知同一条至多播放一种声音。
- 备用标题闪烁:浏览器系统通知已开启但未授权或不可用时,在未触发专注静默且路由允许的情况下,标签页标题以 ⏳ 前缀闪烁代替系统通知。单条闪烁 6 秒自停,连环通知可延长至最近一条后的 6 秒,上限是本轮首次闪烁后的 30 秒,返回窗口立即停止;在「提醒方式 → 系统通知备用提醒」可关闭。
- 专注时减少打扰(专注静默):在「通知规则」设置,仅作用于当前浏览器。页面可见且有焦点时,暂停通知提示音、系统通知与标题闪烁,页内通知及其提示音保留;可见但无焦点时不静默。连续 5 分钟无操作后不再按前台静默,各通道仍须满足开关、授权与路由。桌面版(dsh-app 协议)可在「提醒方式」设置「专注时保留无声系统通知」:macOS 默认开启,其他平台默认关闭,当前浏览器的明确选择优先于平台默认。开启后前台静默时保留无声系统通知(
silent: true,须授权且系统通知开关与事件路由允许),不解除提示音静默;普通浏览器不应用此豁免。webhook 与聊天推送不受专注静默影响。
点击直达会话
等待你动作的审批与提问、以及回合结束类通知,呈现时都携带唯一 sessionId:点击页内提示卡片或系统弹窗,经官方 uiWorkspace.openSession(sessionId) 切换到对应会话并清除该会话未读高亮,不依赖侧边栏 DOM、标题或文件夹展开状态,支持重名、改名与跨工作区。缺少 ID 的旧通知/测试通知只聚焦,不按标题猜测目标;导航服务未就绪或同步调用失败会显示提示。同页多个插件实例按每次注入激活独立登记导航引用,点击时使用最后激活且仍存活的实例;任一实例卸载不影响其余实例,最后一个退出后不再持有导航引用。「知道了」类显式关闭不触发直达。
等待动作二次提醒
审批请求与 AI 提问送达后 10 分钟仍未处理时,自动补发一轮提醒(页内提示 + 声音 + 标题闪烁,不受常规声音开关、分类静音、页内通知开关、专注静默与通道路由限制),每条通知至多补发一次,不连环催。"已处理"的判定:你已切到该会话,或已点掉会话行高亮;通知缺少会话 ID 时无法感知处理,按未处理补发。后续快照确认通知被其他窗口处理或已移出投影队列时,补发登记自动撤销。投影仅保留最近 20 条且有效期 1 分钟,因此 10 分钟补发要求当前页面的登记一直保留、没有收到将该条淘汰的后续快照;持续活跃的通知流可能提前撤销登记,不保证每条等待动作都在 10 分钟后补发。
通知小结
回合结束类通知附一句话小结:耗时(回合时长)+ tokens(本回合各步用量四桶合计)+ 最终回答前缀(末条含文本回答的首行,按码点截断),拼装为「耗时 12 秒 · 1.5k tokens · 已修复登录」形态;缺哪项省哪项,全缺省无小结。系统弹窗作正文、页内卡片作第二行,webhook payload 增补 summary、tokens 与 sessionId 结构化字段。统计来自 host 侧会话事件流内的 assistant 消息,新回合开始重置、任意结束事件无条件清账,包括被过滤或未映射成通知的结束;中途提问与审批读取当时快照,保留本回合后续累计,无额外请求。
事件→通道路由
六类事件各自可指定放行通道名单(kindRoutes,存 settings.yaml),名单外的通道对该类事件一律不送达;未配置的分类全通道放行,名单为空数组即全禁。通道名:sound(提示音)/ system(系统弹窗)/ toast(页内提示,页内提示音随行)/ blink(降级标题闪烁)/ webhook / im / host(宿主桌面通知)。典型用法:任务完成只推 webhook,重要事件(审批/提问)走 IM:
turn-notify:
kindRoutes:
completed: [webhook] # 完成只推 webhook,浏览器不响
approval: [im, sound, system] # 审批走 IM 且本机弹窗出声
路由是全局配置,作用于所有浏览器;当前浏览器的声音与通知开关、专注静默在其上叠加,常规通知需两层都放行。面板四个入口均不提供路由编辑,仍经 yaml 配置。等待动作的二次提醒不受该路由限制。
webhook 推送
在「外部推送 → webhook」输入 URL,点击「保存地址」后启用;清空地址并保存后停用。输入草稿不会在失焦时保存,未保存或保存失败时不能测试,避免误测旧地址;测试使用已成功保存的地址。URL 原文随配置响应回显。
DSH 进程直接向接收端发送通用 JSON:text 字段为通知文本,summary 为通知小结,另附 event/category/status/session/workspace/durationMs/tokens/ts 结构化字段。接收端须支持此请求格式,插件不自动适配所有平台的机器人协议,不能保证任意钉钉、企业微信或 Slack 机器人 URL 都可直接使用。浏览器关闭后仍可发送,前提是 DSH 持续运行;超时 10 秒,失败不重试。测试成功仅表示接收端返回 HTTP 2xx,不表示平台消息已被最终用户收到。
宿主桌面通知
在「提醒方式」开启单个「后台桌面通知」开关,可在无浏览器接收时由运行 DSH 的电脑尝试发送系统桌面通知;通知显示在运行 DSH 的机器,可能与当前浏览器不在同一台电脑。macOS 使用 osascript,Linux 使用 notify-send,Windows 使用 PowerShell 调用 WinRT toast,依赖对应系统工具与可用桌面环境;超时 10 秒,失败不重试,不影响其余通道。
去重采用浏览器优先:本插件 WS 通道有连接,或最近活动仍在 2 秒认可窗口内时,后台让位;无浏览器在场且超出窗口时补位。任意设备的浏览器连接均计入在场,与是否同机无关;即使该浏览器关闭声音、系统通知与页内通知,后台也不会因此补发。边界判定与网络抖动仍可能导致重复。
面板以 hostNotify || hostNotifyFallback 读取已有配置,只展示一个开关;切换时写入 hostNotify 布尔值并将 hostNotifyFallback 清为 false,避免两个等效开关互相混淆。yaml 中任一字段为 true 仍会启用相同的补位行为。
开启后台桌面通知后,可点击「测试桌面通知」直接触发服务器上的通知命令,不模拟浏览器关闭;测试端点本身不经过自动投递的开关与浏览器在场判定。成功仅证明命令执行结束且未报告错误,不保证操作系统实际显示通知;无桌面环境、系统通知设置或勿扰模式仍可能影响显示。专注静默仅作用于浏览器,不会改变后台补位判定。
IM 推送
「外部推送」中的「聊天推送(IM)」使用 @xmanrui/dsh-im 支持的平台;未安装时显示启用该插件的提示。先在 dsh-im 设置页创建并测试接收对象;本插件仅选择已有对象,支持多个机器人。
组内优先展示已选接收对象。展开「添加接收对象」,粘贴从「IM机器人」设置复制的 Bot ID,获取目录后开启相应对象,选择即保存。机器人列表只表示已有对象引用该机器人,不代表机器人在线;移除机器人会清除此插件下该机器人的接收对象,不会删除 dsh-im 中的机器人或对象。
关闭聊天推送开关后停止自动投递,已选对象保留,再次开启即恢复。浏览器关闭后仍可发送,需 DSH 及机器人保持运行;失败或机器人离线时不重试、不补发。开启聊天推送且已选择对象后,可点击「测试聊天推送」向全部已选对象发送测试消息;测试端点本身不经过自动投递开关判定。成功仅代表平台受理,不保证最终用户已收到。
会话行高亮
通知实际送达时,侧边栏会话列表中对应会话行以背景脉冲闪烁强调,六类各一色(完成绿/出错红/提问蓝/中断橙/审批黄/上限紫),点击该会话行即停止。开关在「提醒方式 → 侧边栏状态」(当前浏览器独立保存),默认开启。并行多会话时用于快速定位状态刚更新的会话:运行中的会话不闪烁(与 dsh 原生状态点分工——状态点表达运行中,闪烁表达已更新待查看),会话重新进入运行状态时闪烁自动让位;聚焦时正在查看的会话不闪烁,失焦期间本会话的通知照常闪烁,返回窗口即自动消失(回来即已读,焦点与页面可见双通道)。行定位使用会话 ID 对应的侧边栏行标识,不依赖标题文本。会话行未渲染(列表折叠/懒加载未滚动到)时该次高亮静默跳过。重开页面的冷启动静默对齐同样挂高亮(见"多窗口只响一次"),重开即见哪些会话有动静。
工作区文件夹运行标记
侧边栏会话列表按工作区分组(官方 WorkspaceBrowser 分组模式)时,有运行中会话的工作区文件夹组头显示脉冲运行点并给文件夹图标着色,游离(未归属任何工作区)的可见运行中会话使末位「未分组」组头同样标记——折叠与展开同样生效。归属与运行态一律取服务快照投影,DOM 仅按下标对位官方组容器;组容器数漂移(单列表模式/搜索态/结构变更)即清除标记不误标。图标着色让位官方 folderActive(展开且含当前会话)态。开关在「提醒方式 → 侧边栏状态」(存宿主配置,各浏览器共用),默认开启,变更需刷新页面后生效。
运行状态包含主会话自己的 Agent 回合、origin=subagent 的本地子会话(含多级子会话)与它们拥有的后台任务(Bash 等)。子会话按 parentId 归到主会话所在工作区,不按子会话 cwd 另行分组;普通 fork 是独立会话,不回传源会话。后台任务仅 running / stopping 算活动,完成、失败、取消即撤标,无主任务不归到任何文件夹。通知的子代理静默配置不影响运行标记。
标记通过 uiSession.sessionStatus、sessions.list 与 jobs.state 的官方快照和订阅更新;为可见主会话及其子树持有 jobs.watchRows() 名册,不依赖当前打开哪条会话,不订阅任务输出。离开分组、归档根会话或卸载时释放对应名册。宿主缺少 jobs / uiSession 服务时仅此标记不激活,其他通知功能保留。任务名册首次加载或断流期间没有权威状态,不把无标记解释为已经完成;不具备本地会话运行状态的外部委托不在此聚合范围。「工作区树」视图下工作区路径嵌套使官方组渲染序(树先序)与快照平铺序不一致时,对位失去依据,该视图形态整体放弃标记(宁缺不误),无嵌套的平铺树视图照常标记。
多窗口只响一次
同一地址(同源)打开的多个窗口共享一次呈现:各窗口订阅公共 WS 总线 @mzzsfy/dsh-turn-notify 插件通道(首连、重连与变更触发通知队列全量快照拉取,空闲期无周期请求),经 IndexedDB 原子事务认领,本机偏好与提醒标记保留在 localStorage,仅一个窗口抢先呈现——发声并弹出页内提示、系统弹窗、高亮会话行,其余窗口全部跳过,不止声音。失效广播与快照刷新各自按一秒窗口合并,持续变更时最终快照会收敛;不同浏览器或不同地址打开的窗口各自发声互不感知。窗口关闭/刷新期间错过的通知不做重开回放:启动首轮静默对齐游标与完成标记,不逐条补发提示与声音(等待用户动作的审批与提问例外,照常呈现);未读会话行高亮不在静默范围,照常挂上。
认领记录自认领起按浏览器本地时间保留 90 秒(60 秒投影窗口 + 30 秒请求消费窗口),不按单窗旧快照删除。快照读取与后续事务认领共用超时信号;处理超时或实例卸载会取消尚未提交的认领,其他窗口可接手。通知时间戳保持宿主口径,不要求与浏览器时钟同步。IndexedDB 被阻止或不可用时会通告降级,此时仅保证本窗口去重。
设置面板指南
设置 > 消息通知,四个入口按以下顺序排列,默认打开「提醒方式」:
| 入口 | 配置内容与顺序 |
|---|---|
| 提醒方式(默认) | 通知提示音开关、音量与发声事件;页内通知开关、样式及纯视觉「预览样式」;独立页内提示音开关与发声事件;浏览器系统通知开关、权限异常、测试与备用标题闪烁;单个后台桌面通知开关与测试;「侧边栏状态」中的通知会话闪烁与工作区运行标记。试听与视觉预览分开 |
| 通知规则 | 全局六类通知事件;可展开的高级过滤(最短执行时长、仅通知主会话、减少委托过程通知);仅当前浏览器保存的专注静默。全局事件与过滤同时影响浏览器、webhook、IM 和后台桌面通知 |
| 音效 | 先选择六类事件音效与共享/当前浏览器作用域,再展开页内提示音效(未指定时沿用事件音效),最后管理音效库:选择文件、待上传文件试听/上传、已上传音效试听/重命名/删除 |
| 外部推送 | webhook 地址、「保存地址」与已保存地址测试;安装 dsh-im 后显示聊天(IM),先展示已选对象,展开「添加接收对象」获取并选择目录,同时提供推送开关与测试 |
开关与下拉选择改动即保存,webhook 地址必须点击「保存地址」,音效文件需逐个点击「上传」。工作区运行标记的开关变更需刷新页面后生效。后台桌面通知与工作区运行标记为共享配置;声音、页内通知、浏览器系统通知、会话闪烁及专注静默保存在当前浏览器、当前站点,其他浏览器不共享。
常见操作:
- 切走窗口后接收声音与系统通知:在默认「提醒方式」确认提示音和浏览器系统通知已开启,未授权时申请权限;声音可直接试听,系统通知测试需按提示切出窗口。
- 仅审批与提问出声,其他事件仍保留通知:在「提醒方式」的发声事件中仅保留这两类;已开启页内提示音时也需分别调整其发声事件。若所有通知方式都只需这两类,则在「通知规则」关闭其他事件。
- 浏览器关闭后接收外部消息:在「外部推送」保存 webhook 地址后测试,或展开聊天(IM)的添加对象、获取并选定接收对象后测试。临时暂停聊天推送只需关闭开关,无需移除对象。
测试与试听用于验证指定通道,不会验证整条自动通知规则:声音试听不受事件静音限制;聊天与后台桌面通知在面板开启后才可测试,测试请求本身不经过自动投递规则。webhook 测试仅确认 HTTP 受理,聊天测试仅确认平台受理,桌面测试仅确认通知命令触发。事件→通道路由(kindRoutes)仍通过 yaml 配置,面板不提供路由编辑。
settings.yaml 参考
面板的共享设置与 settings.yaml 读写同一命名空间,保存后生效;工作区运行标记需刷新页面。webhookUrl 随配置响应回显,面板地址需显式保存,yaml 直改后可在重新加载配置时读取。
turn-notify:
webhookUrl: '' # webhook 目标 URL,留空禁用
minTurnDurationMs: 5000 # 最短回合时长(毫秒),回合结束类通知短于此不送达
rootsOnly: true # 子代理会话不通知
suppressSubagentWake: true # 子代理相关回合不通知:后台委托未收尾或收尾唤醒(仅任务完成类)
hostNotify: false # 后台桌面通知;无浏览器在场且超出认可窗口时在运行DSH的电脑通知
hostNotifyFallback: false # 与hostNotify按OR生效;面板单开关写hostNotify并将本字段清为false
enabled: # 六类事件独立开关
completed: true
error: true
interrupted: true
approval: true
ask: true
max-tokens: true
soundMapping: # 每类事件音效映射,空为内置默认,值为内置音名或上传音效 id
completed: ''
kindRoutes: # 事件→通道路由:分类到放行通道名单,未配置的分类全通道放行
completed: [webhook]
imTargets: # dsh-im 投递目标,空数组禁用
- botId: wx_xxx
targetId: owner
imEnabled: true # IM 推送总开关:关闭后不投递,目标绑定保留
folderRunningEnabled: true # 工作区文件夹运行标记(侧边栏分组模式),关闭后不渲染
音量、聚焦静默、分类静音等本机偏好存浏览器 localStorage,不经 yaml。
工作原理
按数据流向分五步:
- 事件监听:host 观察
session/event(回合结束、ask_user_question 工具调用与 assistant 消息)、approval/asked审批事件(审批通知唯一信号:生产者先 append 后发 waterfall,会话事件流恒先达且不依赖应答方放行)。回合结束原因逐一映射:正常结束归任务完成,错误与手动停止归任务出错,审批拦截归等待审批,输出触顶归回复被截断,会话收尾补发的中断归异常中断;assistant 消息流经途累积回合小结(tokens 与回答前缀),回合结束随通知消费。 - 分类与过滤:事件归入六类,经子代理会话、子代理相关静默(仅任务完成类)、最短回合时长三道过滤,通过即产生一条通知,并按 kindRoutes 裁定放行通道。
- host 直发通道:webhook、IM 与宿主桌面通知由 host 进程直接投递(经路由名单过滤),不依赖浏览器;宿主通知按本插件空间 WS 连接的在场信号(来源不限本机)浏览器优先去重,离场补位;同时通知写入内存队列(环形 20 条,60 秒过期,不落盘),路由名单随单元下发。
- 浏览器通道:各窗口订阅公共 WS 总线的本插件空间,首连、重连和变更时拉取队列快照,IndexedDB 原子认领保证同一通知只有一个窗口呈现,再按本机偏好与路由名单分发到声音/系统弹窗/页内提示;等待用户动作的审批与提问超时未处理时补发一轮提醒。
- 降级链:浏览器系统通知开启但不可用或未授权时,在备用标题闪烁、静默与路由条件允许时闪烁标题,不依赖声音开关;页内提示依赖缺失 → 干净禁用该通道;IndexedDB 认领不可用时跨窗口去重降级,仅保证当前窗口去重,可能与其他窗口重复。
已知取舍
- 标签页全关时,仅 webhook、IM 与宿主桌面通知(如开启)送达(声音与弹窗的浏览器前提)。
- 后台桌面通知采用浏览器优先去重:本插件空间有 WS 连接或最近活动仍在 2 秒认可窗口内时让位,浏览器未授权或关闭呈现通道也不会改变该判定。断连后的在场清理由公共总线负责,边界情况可能重复;显示还依赖运行 DSH 的机器有可用桌面及系统通知权限。
- IM 依赖 dsh-im 的 bot 在线,离线时该次通知弃置不补发;成功回执仅代表平台受理。
- 不同浏览器或不同地址打开的窗口各自发声,互不去重。
- 系统弹窗在 HTTP 非回环下永久降级,HTTPS 化后自动恢复;Windows 下受系统通知设置与专注助手约束。
- 经中间反代时需允许公共总线 WebSocket upgrade 与长连接,断线恢复后通过 onReset 全量快照对账。
- 等待动作二次提醒的"已处理"判定以本窗口可见信号(会话切换/高亮清除)近似,缺少会话 ID 的通知无法感知处理,可能再次提醒。
- 点击直达按通知携带的
sessionId经 uiWorkspace 导航,不再依赖侧边栏标题匹配;旧投影/测试通知无 ID 时仅聚焦不跳转,导航服务缺席时提示不阻断;宿主 AppleScript 补位通知无点击回调,App 完全退出后的旧通知不在直达范围。
安全
- 配置写入类接口(config / mapping / upload / 音效改名与删除 / 测试)带同源守卫:Origin 与 Host 不符即 403,JSON 写入另校验 content-type,阻断跨站页面 drive-by 改写配置。
- webhookUrl 在 settings 层标记为 secret(导出与日志脱敏);面板配置接口原文回显,本机同源可读写。
- 音效上传校验扩展名与大小上限(单文件 2MB/总库 10MB);真实音频内容校验在浏览器端完成(选文件即解码,失败拒收),host 接口不做内容嗅探。音效读取接口拒绝音频扩展名以外的文件。
- 已知边界:同源守卫不防 DNS rebinding(Origin 与 Host 相等即放行)。该暴露面属 host webserver 全部 /api 路由的存量问题,应在 host 层统一解决而非逐插件补丁。
开发
cd packages/dsh-turn-notify && npm test
开发安装(仓库维护者)
node scripts/dev-link.mjs dsh-turn-notify # 仓库根执行:归一 profile 依赖行 + 挂 junction
工作副本以 junction 挂进 profile,host 半区改动保存约 1 秒热重载,client 半区改动刷新页面即生效,无需发版;规约与全仓归一见 node scripts/dev-link.mjs all。
dsh 版本兼容
按仓库动态窗口验证(scripts/compat/window.mjs),不预置任何固定版本槽:主测 = 渠道 dist-tag 最新 rc,完全适配口径;基线 = npm latest,不崩溃底线口径;主测与基线同版时收敛单槽。兼容面以窗口实测为准,不逐版本承诺。逐轮实测结论见 docs/兼容性测试/逐包测试进度.md(本地维护,不入库)与本包 兼容性测试.md。
Links
More in this category
xmanrui/dsh-im★ 2328
Connect IM bots to DeepSeek Harness via QR codes or bot credentials (9 channels: Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp).
shaobeichen/dsh-pocket★ 2244
Remote phone access to the DSH Web UI: scan a QR code for LAN or public (cloudflared tunnel) access with real-time sync, a mobile-adaptive layout, and a settings tab.
OpenPetsHQ/openpets#dsh★ 1320
Bridges DeepSeek Harness lifecycle status, errors, and approval requests to a locally running OpenPets desktop companion.
inclusionAI/Avernet#deepseek-harness-channel-bcn★ 590
Connects DeepSeek Harness to Avernet's Bot Collaboration Network over WebSocket V2, with automatic onboarding, isolated agent sessions, tool-call events, and multi-bot routing tools.
c1overzz/dsh-bili-scroll★ 423
Let your DSH agent browse Bilibili on its own, read subtitles, write a daily digest, and @ you when it finds something worth your attention.
omdsh-dev/dsh-notification★ 89
Desktop notifications for turn completions, with per-outcome controls and keyword rules.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.