任务完成或出错时推送到你的 Webhook 并弹出系统通知
29.5/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/gitMFQ/dsh-webhook-notify.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 6 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
发起外部网络请求
查看扫描证据(共 9 处,展示前 9 条)
- 发起网络请求lib/index.js:575
const response = await fetch(`${origin}/favicon.svg`, { cache: 'no-cache' }); - 发起网络请求lib/client.js:411
const res = await fetch(path, { - 发起网络请求lib/client.js:422
const res = await fetch(path, { cache: 'no-store' }); - 发起网络请求lib/client.js:952
fetch(ROUTES.pushKey, { cache: 'no-store' }), - 发起网络请求lib/client.js:953
fetch(ROUTES.pushList, { cache: 'no-store' }), - 发起网络请求lib/client.js:1109
const response = await fetch(link.href, { cache: 'no-store' }); - 发起网络请求lib/client.js:1155
const response = await fetch(new URL(probe.src, link.href).href, { cache: 'no-store' }); - 发起网络请求lib/send.js:155
const response = await fetch(request.url, { - 发起网络请求lib/pwa.js:417
const response = await fetch(url, {
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DSH 通知插件:宿主进程推 Webhook + 浏览器系统通知 + PWA + Web Push
README
由 DeepSeek 最新模型翻译生成dsh-webhook-notify
DSH 通知插件:任务需要你操作 / 回复完成 / 本轮出错时,从 DSH 宿主进程把通知推送到你自己的 Webhook,同时(可选)在系统通知中心弹一条浏览器通知(参考 dsh-notify-me,点击通知回到对应会话),再进一步:把 DSH 变成可安装的 PWA(只补可安装性,不改宿主的窗口显示模式与状态栏),并支持 Web Push(页面全关也能收到提醒)。
为什么不是「填个地址就行」的前端插件
dsh-notify-me 这类浏览器端插件用 fetch 直接 POST,会撞上两道墙:
1. 跨域(CORS):目标端点不放行 Access-Control-Allow-Origin 时,浏览器连请求体都读不到,只能降级成「已送出不可确认」;
2. 自定义请求头:Authorization: Bearer … 会触发预检,端点不配合就发不出去——而这恰好是绝大多数 Bot / 推送网关的鉴权方式。
本插件把发送放在宿主(Node)进程里:任意请求头、任意目标、不受同源策略约束,页面关掉也照发。
展开完整文档(README 剩余 1 节)
dsh-webhook-notify
DSH 通知插件:任务需要你操作 / 回复完成 / 本轮出错时,从 DSH 宿主进程把通知推送到你自己的 Webhook,同时(可选)在系统通知中心弹一条浏览器通知(参考 dsh-notify-me,点击通知回到对应会话),再进一步:把 DSH 变成可安装的 PWA(只补可安装性,不改宿主的窗口显示模式与状态栏),并支持 Web Push(页面全关也能收到提醒)。
为什么不是「填个地址就行」的前端插件
dsh-notify-me 这类浏览器端插件用 fetch 直接 POST,会撞上两道墙:
1. 跨域(CORS):目标端点不放行 Access-Control-Allow-Origin 时,浏览器连请求体都读不到,只能降级成「已送出不可确认」;
2. 自定义请求头:Authorization: Bearer … 会触发预检,端点不配合就发不出去——而这恰好是绝大多数 Bot / 推送网关的鉴权方式。
本插件把发送放在宿主(Node)进程里:任意请求头、任意目标、不受同源策略约束,页面关掉也照发。
触发事件
| 事件 | 时机 | kind |
| 需要你操作 | approval/asked(工具审批等) | attention |
| 回复完成 | turn/end 且 reason.kind === 'completed' | done |
| 本轮出错 | turn/end 且 reason.kind === 'error' | error |
浏览器通知(参考 dsh-notify-me)
除了推 Webhook,本插件还能在系统通知中心弹一条浏览器通知,页面开着也能立刻看到、点一下回到对应会话。
- 持久通知走 Service Worker:页面被系统挂起后仍能弹出,点击通知带用户手势、能把窗口真正带到前台;没有 Service Worker(如 dsh-app:// 桌面端、非安全上下文)时自动退回页面内 new Notification()。
- 触发规则与 Webhook 同源:同一批事件,Webhook 推到端点、浏览器通知弹到桌面,两边独立开关。
- 点击回到会话:点击通知把 DSH 带到前台并切到该条提醒所属的会话(可在设置里关掉)。
- 安静规则:默认「当前对话的等待不弹」(卡片就在眼前)、「回复完成只在页面隐藏时弹」、「子代理会话不弹」——都可在设置页调整。
设置页「浏览器通知」卡片里有权限状态、Service Worker 状态和「发送测试通知」按钮。
浏览器通知权限需要在页面上点一次(浏览器要求用户手势才能询问)。首次点设置页的「请求通知权限」即可。
PWA:可安装为应用
插件只补齐可安装性所需的东西(manifest 链接、图标、启动字段),不改写宿主自己的窗口显示模式与状态栏。
manifest 怎么处理
DSH 自带 manifest.webmanifest(品牌名、图标、display 都在里面)。插件不另起一份,而是:
1. 宿主在下发 index.html 时做三件事(webServer.tapIndex 变换;老宿主没有这个 API 时由客户端兜底改写):
- 在 最前面注入 /webhook-notify/pwa-capture.js——beforeinstallprompt 每次页面加载只派发一次,而客户端插件是异步加载的,跑晚了就永久错过(设置页只能显示「浏览器没有给安装入口」);
- 把 指向插件路由 /webhook-notify/manifest.webmanifest;
- 插入一段 :html,body{overscroll-behavior-y:contain},关掉下滑刷新(见下);
2. 插件的路由回源抓取宿主原 manifest,在它基础上合并:
- 补 192×192 / 512×512 位图图标(宿主只有 SVG 时过不了可安装性检查,见下);
- 可选覆盖 name / short_name / background_color(都留空就沿用宿主);
- id 稳定化、launch_handler: navigate-existing(单窗口复用);
- 所有 URL(start_url / scope / icon.src …)按原 manifest 的地址解析,同源的写成 / 开头的根相对地址;
- display / display_override / theme_color 原样保留:显示模式与状态栏属于宿主,插件一个字都不改(所以 DSH 默认的 display: "fullscreen" 全屏就是它自己的选择);
3. 抓不到原 manifest 就 302 跳回原地址:宁可少几个字段,也不要让应用变得不可安装。
状态栏与底部导航栏:插件不碰
这两条栏的颜色归宿主 manifest(theme_color)与浏览器管:插件既不再往页面里插 ,也不再改 viewport-fit 或注入底部安全区样式。之前那套「把宿主 fullscreen 改成 standalone + 给状态栏染色 + 让底部导航栏透明」的做法会连带改变宿主的全屏观感,现在已经全部拿掉。需要换配色或显示模式时,直接改宿主自己的 manifest 即可。
下滑刷新:为什么要用 CSS 关掉
装成应用之后,从页面顶部往下拽会拉起 Chrome 那个「转圈 → 整页重载」的手势。对原生感的界面这是纯粹的灾难:聊到一半的输入框、展开的面板、滚动位置全被一次误触抹掉。
Chrome 从 63 起把这件事交给 CSS 的 overscroll-behavior:在 html, body 上写 contain,越过顶部的那段 overscroll 就不再冒泡到浏览器窗口,整页重载也就不会发生。插件注入的是:
html, body { overscroll-behavior-y: contain; }
几个取舍:
- 用 contain 而不是 none:none 连橡皮筋回弹一起去掉,手感反而更假;contain 只拦住向上的冒泡。
- 只加在根滚动容器上,不动嵌套滚动区(消息列表、抽屉):它们的滚动链保持原生,root 那层已经兜住了越界。
这是纯 CSS,没有 touchmove 监听,不抢滚动线程的合成器,也不影响惯性滚动。
为什么 manifest 里不能写死 http://host
这个坑很难自己看出来:宿主把 manifest 里的地址写成 http://<Host>/… 之后,经过 HTTPS 反向代理访问的用户拿到的就是混合内容——浏览器拦掉图标,start_url 又跨了协议,于是:
- 地址栏没有安装图标;
- 不派发 beforeinstallprompt,设置页只能说「浏览器没有给安装入口」;
- 控制台往往一句错都不报。
而宿主那头完全正常(在 127.0.0.1 上直接打开当然没问题),所以很容易怀疑到别处。根相对地址把 origin 交给浏览器按当前访问地址补,https / 端口 / 反向代理怎么变都对;跨域资源(CDN 图标)保持绝对地址。
为什么不 preventDefault()
拦掉 beforeinstallprompt 的默认行为,等于把浏览器自己的安装入口(地址栏的安装图标)一起关掉。插件现在只记录不拦截:浏览器原生入口归浏览器,设置页的按钮只是多一个入口。
用 Chrome 的 Page.getAppManifest 验证过:解析无 error,displayOverrides 里第一个就是 kWindowControlsOverlay。
图标:为什么插件要自己生成 PNG
Chrome/Edge 的可安装性检查要求 manifest 里有 192×192 与 512×512 的位图图标。DSH 原 manifest 只有一个 favicon.svg(sizes: "any" → 实际尺寸 0×0),过不了「至少 192px 宽的图标」这一关——页面明明满足其它条件,浏览器也不给装。
所以插件在宿主侧现栅格化宿主 logo(见 lib/icon.js):解析 SVG 的 <path d> → 扫描线填充(非零环绕规则 + 4×4 超采样抗锯齿)→ 用 Node 自带 zlib 编码 PNG。产物:
| 路由 | 尺寸 | 用途 | 外观 |
| /webhook-notify/icon-192.png | 192×192 | purpose: any | 圆角 + 品牌蓝底 + 白色 logo |
| /webhook-notify/icon-512.png | 512×512 | purpose: any | 同上 |
| /webhook-notify/icon-maskable-512.png | 512×512 | purpose: maskable | 满幅蓝底(系统自己裁形状),logo 收在安全区内 |
三张图长得一样:Windows 的任务栏、开始菜单、安装对话框、macOS 的 Dock 各自可能挑不同的那张,长得不一样就会显得很怪。
另外合并 manifest 时会把宿主里非位图的图标(favicon.svg,sizes: "any")从 icons 列表里换掉,不是留着当备选:浏览器挑图标会把 sizes: "any" 的标量图当万能解,装出来的应用就是一张透明底的黑色 logo——深色任务栏上几乎看不见。插件补的位图本来就是同一个 logo 栅格化出来的,换掉不丢品牌。
不随包发 PNG 资源:logo 形状来自宿主的品牌 SVG,宿主一改就不该留旧副本。栅格化要几百毫秒,所以只做一次并缓存在宿主内存里。
兜底图标不长期缓存:宿主刚启动时 webServer 可能还没开始监听,这时回源抓 favicon.svg 会 ECONNREFUSED;如果把这个失败结果钉死在缓存里,之后装出来的应用图标就一直是内置铃铛。所以兜底只管一分钟,之后自动重试真 logo。设置页的「应用图标」一行会直接写明当前用的是「宿主 logo」还是「内置铃铛」。
装完图标还是旧的? 那是操作系统的安装快照:Windows 把图标存进了应用快捷方式,宿主这边换图标它不会跟着变。到 edge://apps / chrome://apps 里卸载再装一次即可。
装不上?设置页会直接告诉你原因
「PWA 安装」分组里「安装为应用」旁边会显示当前状态:
| 提示 | 含义 |
| 浏览器已给出安装入口 | 可以装 |
| 当前不是安全上下文({origin}) | 最常见的原因:PWA 安装与 Web Push 都要求 https:// 或 http://localhost;用 http:// 访问一个域名一定装不了 |
| Service Worker 还没就绪 | 刷新页面让 worker 装上 |
| 浏览器没有给安装入口 | 多半是这台浏览器已经装过(装过之后地址栏就不会再有图标),也可能是企业策略;用下面的自检确认 |
| 页面上没有 manifest 链接 | 宿主没下发改写后的 index.html,刷新一次即可 |
| 已经以应用方式在运行了 | 装过了 |
光有文案还不够:卡片里还有 「安装自检」,在页面里逐项跑一遍可安装性条件——安全上下文、manifest 能不能取到且是合法 JSON、有 name/start_url/display、声明了 192×192 与 512×512 图标、manifest 里的地址与当前页面同源同协议(不是混合内容)、图标真能下载、Service Worker 已激活、浏览器有没有派发 beforeinstallprompt。哪一环断了一目了然,不用去猜。
离线兜底
Service Worker 监听导航请求(request.mode === 'navigate'),走「网络优先 + 缓存兜底」:网络正常时行为完全不变,断网时至少能打开上次缓存的应用外壳。其它请求(脚本、接口、WebSocket)一概不碰。可用 pwaOffline 关掉。
Web Push:页面全关也能收到
浏览器通知依赖页面活着;Web Push 则由推送服务直接投给 Service Worker,页面全关、浏览器在后台都照收。
链路
宿主事件 → VAPID 签名 + aes128gcm 加密 → POST 推送服务 → Service Worker 的 push 事件 → 系统通知
- VAPID:插件自动生成 P-256 密钥对,公钥给浏览器订阅用,私钥留在宿主签名用。密钥存在 profile 配置里,必须长期稳定,换密钥等于所有订阅失效。
- 出站代理(pushProxy):推送服务都在公网。宿主只能经代理出网时,直连只会得到一句 fetch failed——什么都不说。填 http://127.0.0.1:7890 这样的地址后,推送走 undici 的 ProxyAgent;留空=直连。只影响 Web Push,Webhook 投递仍然直连(这些地址通常在内网)。改完记得保存配置,代理 Agent 会跟着重建。
- 载荷加密:按 RFC 8188 的 aes128gcm 内容编码(密钥派生链与 http_ece 参考实现逐字节一致;测试里直接用 RFC 8188 §3.1 的官方测试向量对齐)。
- 点击行为:推送通知的 data 与页面内通知同形,点击照样切回对应会话。
用法
1. 设置页 → 「Web Push」→ 打开「启用 Web Push」;
2. 点「订阅推送」(需要先授予通知权限;浏览器要求用户手势);
3. 订阅信息会存到宿主(profile 配置),宿主在事件发生时向所有订阅推送;
4. 「发送测试推送」可验证整条链路。
推送端点默认要求 https://;本机回环地址(127.0.0.1 / localhost)允许 http://,方便接自建推送中继。
端点字段
| 字段 | 说明 |
| url | 必填,可含模板变量 |
| method | POST / PUT / PATCH / GET / HEAD / DELETE(其它值回落成 POST) |
| headers | 对象,或每行一条 Key: Value 的文本 |
| bodyMode | json(通用载荷)/ text(只发正文)/ none |
| body | 自定义请求体模板,留空用 bodyMode 生成 |
| kinds | 订阅哪些事件;留空 = 全部 |
| retries / timeoutMs | 重试次数 / 单端点超时。timeoutMs 为 0(默认)时跟随插件级 timeoutMs,只有显式填了值才覆盖它。4xx 不重试(408 / 425 / 429 除外);3xx 不自动跟随,按失败上报 |
模板变量
{{title}} {{body}} {{content}}(拼好的正文){{text}} {{session}} {{sessionId}}
{{kind}} {{event}} {{time}} {{tool}} {{reason}} {{json}}(完整事件 JSON)
body 以 { 或 [ 开头时按 JSON 拼装,变量自动转义——正文里的换行和引号不会把 JSON 拆坏。
例子
OpeniLink Hub / 微信
url: https://oih.osai.eu.org:8443/bot/v1/message/send
headers: Authorization: Bearer app_xxx
body: {"content":"{{content}}"}
Discord
url: https://discord.com/api/webhooks/xxx/yyy
body: {"username":"DSH","content":"{{content}}"}
Bark
url: https://api.day.app/<key>/{{title}}/{{content}}
bodyMode: none
自定义接收端
url: https://example.com/hook
body: {"event":"{{event}}","text":"{{content}}","session":"{{session}}","at":"{{time}}"}
设置页
DSH Web → 设置 → Webhook 通知。面板按 DSH 自身设置页的样式与结构重做:
- 排版对齐宿主:行内「标签左 / 控件右」+ .5px 分隔线、14px 正文 / 12px 次要文字、36px 控件;颜色全部走 --dsw- 设计令牌,浅色 / 深色主题自动跟随;
- 开关、按钮、事件胶囊直接复用宿主暴露的原子组件 @deepseek-ai/dsh-client-ui-primitives(Switch / Button / Pill),拿不到时退回等价的自绘样式;
- 分组:Webhook 投递(事件开关、默认超时、节流、正文模板、日志)→ 浏览器通知(开关、静音规则、权限与测试)→ PWA 安装(开关、应用名、manifest 与图标状态、自检)→ Web Push(开关、VAPID 联系地址、出站代理、订阅与测试)→ 推送端点 → 最近投递;
- 保存 / 预览 / 添加端点固定在面板底部的操作条上,改动后随手可保存;
- 端点卡片:备注名、启用开关、地址、方法、订阅事件、超时、重试、请求体模式与模板、请求头,以及「发送测试消息」。
配置字段
除端点字段外,插件级配置如下(都存在 profile 的 cordis.patch.yml):
| 字段 | 默认 | 说明 |
| notifyAttention / notifyDone / notifyError | true | 三类事件各自的投递总开关 |
| minIntervalMs | 0 | 同一会话的最小推送间隔(毫秒,0=不限) |
| timeoutMs | 10000 | 插件级默认请求超时;端点自身的 timeoutMs 为 0 时用它 |
| textTemplate | '' | 正文模板(留空用内置排版) |
| logDeliveries / debug | true / false | 投递日志 / 调试日志 |
| pwaEnabled | true | 接管 manifest 与可安装性(关闭后不再改写 index.html) |
| pwaOffline | true | Service Worker 缓存应用外壳(断网兜底) |
| pwaName / pwaShortName | '' | 覆盖应用名/短名(留空沿用宿主) |
| pwaBackgroundColor | '' | 覆盖启动背景色(留空沿用宿主) |
| pushEnabled | false | 宿主向浏览器推送 |
| pushSubject | mailto:dsh-webhook-notify@localhost | VAPID 联系地址(须 mailto: 或 https:) |
| pushProxy | '' | 推送出站代理(如 http://127.0.0.1:7890);留空=直连 |
| pushVapidPublicKey / pushVapidPrivateKey | 自动生成 | VAPID 密钥对,勿手改(换密钥=订阅全废) |
| pushSubscriptions | [] | 浏览器订阅列表,自动维护 |
修复与行为变化(0.4.0)
这一版按代码审查结论做了一轮修复,并拿掉了对宿主窗口外观的改写:
- 停用端点也能自测:此前对一个 enabled: false 的端点发「发送测试消息」,notify() 放行、投递层又按启用过滤,结果一律显示「找不到该端点」,一个请求都发不出去。现在自测路径绕过启用过滤;地址还没填的端点会得到真实的「地址无效」结果,真正不存在该 id 才报「找不到该端点」。广播路径仍然静默跳过空地址草稿行,不会往最近投递里塞红条。
- 反向代理下设置页不再全 403:trusted() 只比对 Origin 与 Host,代理按默认改写 Host 后保存/测试/预览/订阅一律 403(manifest 却正常,极难排查)。现在 X-Forwarded-Host 存在时也计入允许集合。
- 插件级 timeoutMs 真的生效:端点 timeoutMs 默认改成 0(跟随插件级超时),此前端点默认值总会覆盖插件级设置,导致 profile 里改 timeoutMs 毫无作用。
- 「窗口拖拽条」开关修好:开关此前写到了 React 状态副本上,实际读取的是模块级状态,勾选后永远不生效;该功能随窗口覆盖改写一起移除(见下)。
- 待处理交互不再重复提醒:去重键此前用 key.split(':') 反推会话 id,而宿主下发的 key 是 approval:<序号> 这类不含会话 id 的形式,导致同一次等待被反复弹。
- 「点击通知回到对应对话」在持久通知路径下生效:该开关此前只作用于页面降级通知;现在偏好随通知 data 交给 Service Worker,worker 不再无条件抢焦点,页面侧也再判一次。
- 结局分类不再用过期数据:「本轮出错」判定新增 60 秒有效期,并在页面回到前台时立即刷新,避免上一轮的 error 把后台完成的一轮误报成出错。
- i18n 补齐:中文补上「推送代理」文案,英文补上图标来源文案,并清掉中文词典里重复定义(英文值)的三个死条目。
- 死代码清理:未使用的 deliver / LIMITS 导入与无处调用的 resolveManifestSource() 删除。
- 不再改写状态栏 / 底部导航栏 / 窗口显示模式:删掉 theme-color 注入、viewport-fit=cover 与底部安全区注入、manifest 的 display / display_override 强制值与 theme_color 覆盖、窗口覆盖(WCO)相关的 CSS 变量发布与拖拽条。宿主原本的 display: "fullscreen" 与全屏观感原样保留。
安全与一致性(0.3.0)
这一版修掉了几个会造成数据泄露或「看起来成功其实没成功」的问题,行为变化如下:
- manifest 回源被收紧:/webhook-notify/manifest.webmanifest?src=… 只接受宿主自己的 /manifest.webmanifest,并拒绝 query / hash / 跨源地址。此前 ?src=/webhook-notify/state 会把宿主的内部状态接口当 manifest 抓取并原样返回,端点的 Authorization 头与私密 Webhook 地址会因此泄露。非法 src 现在直接 400,不会发起任何本机请求。
- 图标回源固定走本机:Host / X-Forwarded- 只用来决定 manifest 里对外的地址,不再参与「去哪里抓 favicon」。伪造这些头无法让宿主访问任意地址。
- 设置页保存有字段白名单:pushVapidPrivateKey 与 pushSubscriptions 永远不下发、也无法被保存请求覆盖。此前一次保存可能把订阅列表清空。
- 配置写回串行化:订阅上报、VAPID 密钥生成与设置页保存并发时不再互相覆盖,各自只写自己负责的字段。
- 测试通知不再「空成功」:没有可用端点时返回 ok: false 与具体原因。
- 3xx 不再自动跟随:端点返回重定向会明确报错(避免对端决定请求最终发往哪里)。429 / 408 会重试,其余 4xx 不重试。
- 响应体有上限:最多读取 64 KiB,对方回一个超大响应不会吃掉宿主内存。
浏览器侧同时修掉了:同一条点击消息触发两次导航、showNotification() 失败被当成成功(并产生未处理拒绝)、订阅上报失败仍显示「已订阅」、以及插件重载后监听器与通知残留。
注意
- HTTP 头只能是单字节字符:X-Tag: 中文 会被底层拒绝,插件会直接报「请求头含非 ASCII 字符」而不是静默失败。中文放请求体。
- 端点配置存在 profile 的 cordis.patch.yml,重启保留;headers 里的 token 也一并存在那里,注意该文件的读取权限。VAPID 私钥同样存在这个文件里。
- 同一会话的推送可用「最小间隔」节流,避免连续回合刷屏。
- Webhook 正文上限 21000 字符:助手最后一条回复先截到 21000 字(超出以 … 结尾),拼上标题/时间等附加行后再按同一上限截一次,所以端点收到的 {{content}} 不会超过 21000 字。Web Push 通知正文仍截到 400 字——推送服务对单条载荷有 4 KiB 硬上限。
- PWA 安装与 Web Push 都要求安全上下文:https:// 或 http://localhost / 127.0.0.1。用 http:// 访问一个域名(例如 http://dsh.example.com)时,浏览器不给注册 Service Worker,也就不给安装、不给推送——设置页会直接这么提示。反向代理要记得透传 X-Forwarded-Proto / X-Forwarded-Host,否则 manifest 里的绝对地址会指向内网。
- 改了宿主 manifest 的 display / theme_color 之后:WebAPK 不会立刻更新,卸载重装最快(也可以在 Chrome 打开 chrome://webapks 点 Update)。插件本身不再改写这两个字段。
- Web Push 依赖推送服务可达(Chrome 走 FCM / Edge 走 WNS)。网络不通时订阅会失败;本机自建中继可用 http://127.0.0.1 端点。
- 设置页保存时不会覆盖 pushVapidPrivateKey 与 pushSubscriptions(客户端根本拿不到这两个字段)。
测试
cd /root/dsh-webhook-notify && npm test
npm test 等价于 node --test test/;当前共 116 项,全绿。
覆盖:端点投递与模板、浏览器通知运行时、RFC 8188 官方测试向量(内容编码逐字节对齐)、HKDF(RFC 5869 + Node 内置实现交叉验证)、VAPID 签名、manifest 合并与 URL 根相对化(含反向代理下的混合内容回归)、SVG 栅格化与 PNG 编码、Service Worker 源码真跑一遍(push / notificationclick / 订阅失效)、以及一条端到端推送(宿主 → 本地 HTTP 推送服务 → 用浏览器侧私钥解密校验)。
开发说明
node_modules 是指向 profile 依赖的软链,只为本地跑测试时解析 @deepseek-ai/schemastery 用;删除它插件在宿主里仍能正常工作(宿主自己解析依赖),但 node --test 会因找不到 schemastery 而失败。
新增文件:
| 文件 | 职责 |
| lib/pwa.js | manifest 链接改写、早期安装提示捕获脚本、禁止下滑刷新、manifest 合并(补图标/icon、稳定 id、启动字段;不动 display / display_override / theme_color)、URL 根相对化 |
| lib/push.js | VAPID 签名、aes128gcm 加密、推送发送 |
| lib/icon.js | SVG path 解析、扫描线栅格化、PNG 编码(PWA 图标) |
| lib/sw.js | Service Worker 源码(通知点击中转 + push + 离线兜底;点击时按通知携带的 autoFocus 决定是否抢焦点)
| lib/browser-notify.js | 浏览器通知运行时(页面半边的纯 ESM 孪生实现,页面侧那套由 lib/client.js 内联) |
宿主半边的改动需要宿主重新加载插件才会生效(Profile 重组合即可;lib/index.js 的改动不会热替换到已运行的进程里)。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
gitMFQ/dsh-webhook-notify
任务完成或出错时推送到你的 Webhook 并弹出系统通知
相关插件 · 工具 / 效率
破甲管控台kingcharleslzy-ai/dsh-purge
dsh-purge Community · DeepSeek Harness 社区维护版:宿主兼容、状态诊断、提示词管理、更新与本机备份回滚。基于小杨 / YuJunZhiXue 的 dsh-purge。
★ 4,173已汉化DeepSeek 客户端
74.4
网文长卷lingfengQAQ/webnovel-writer
基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200…
★ 7,636已汉化DSH
72.2
多智能体协作HKUDS/AutoSwarm
AutoSwarm: Unify Your Agents. Unify Your Context (Codex · Claude Code · DeepSeek Harness · Muse · Grok · WorkBuddy· nanobot · and more)
★ 2,349已汉化DSH
71.6
Vox 拼贴视频生成Alisa0808/vox-director
🎬 Vox Director拼贴动效导演
★ 2,129已汉化DSH
71.4
Agent 演化引擎Q00/ouroboros
智能体 OS:智能体自己变聪明,我们只守住底线:面试准入、分阶段评估、带预算的进化循环。MCP 服务器,14 种运行时:Claude Code、Codex CLI、Gemini CLI、OpenCode、Copilot、Kiro 等。
★ 6,308已汉化DSH
71.3
智能体运行框架路由HarnessRouter/harnessrouter
智能体运行框架的统一接口。
★ 3,897已汉化DSH
71.2
这是你的仓库?认领条目