npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@citisen/dsh-notification

v0.2.0

Published

DeepSeek Harness plugin: per-state desktop notifications — a card per session state with its own bell, volume, and system-notification template

Readme

dsh-notification

一个 dsh 插件:会话需要你的时候响一声提醒。 为桌面版而做,浏览器里也能用。

你正看着界面的时候,它其实已经把话说完了:侧边栏每个会话有状态,对话自己有流式指示。这个插件补的 是另一件事 —— 不管你在不在看,状态到了就响一声:切到别的应用、窗口留在后面、或者就坐在它面前, 只要那张卡是开着的,它就出声。

它加了什么

设置 → 通用 里多出一行 会话通知:一个总音量,然后是每个状态一张卡片。

| 状态 | 什么时候响 | 出厂声音 | | --- | --- | --- | | 等待回答 | agent 提了问题 | 贝多芬《第五交响曲》—— 命运动机 | | 等待审批 | agent 申请权限 | 巴赫《d 小调托卡塔与赋格》BWV 565 | | 等待审阅计划 | agent 提了计划 | 同一个音连敲三下,然后跳到高八度并保持 | | 执行出错 | 会话的 agent 报了错 | 《末日经》(Dies irae)圣咏 | | 执行完成 | 一轮结束 | 贝多芬《第九交响曲》——「欢乐颂」 | | 开始执行 | 一轮开始了 | 莫扎特《弦乐小夜曲》K. 525 —— 默认关闭 |

每一段都是公有领域的古典乐句,按状态的含义挑的。开始执行默认关闭,因为"一轮开始"不值得打扰 任何人;想要的话在它自己的卡片里打开。

每张卡片有自己的开关、音量、音色和旋律。只有一个开关,因为一张卡片只能做一件事:出一声。 当这段声音长到不止一声的时候,旋律就值得改 —— 见旋律。

没有任何"什么时候才准响"的规则 —— 没有窗口聚焦、没有"我正在看的会话不提醒"、没有最小间隔。 状态对得上、卡片是开的,就响;要安静就把总音量拖到 0,或者关掉那张卡片。理由见 为什么没有那些开关。

安装

dsh plugin --profile desktop add @citisen/dsh-notification

然后重启应用。浏览器 profile 用 --profile web。

卸载

dsh plugin --profile desktop remove @citisen/dsh-notification

先把应用完全退出 —— desktop 这个 profile 由应用自己管理,占用中时命令会拒绝操作。这条命令 会移除包本身、dsh.profile.bundles 里的那一项,以及安装出来的目录。

然后还要自己删掉配置,这部分命令碰不到。插件那一行带着一个 config: 块,里面是你改过默认值的所有 设置,它在你自己的 patch 文件里:

# $DSH_HOME/profiles/desktop/cordis.patch.yml
- id: notification
  name: "@citisen/dsh-notification"
  config:
    masterVolume: 1
    # ...以及各个状态的设置

把整段删掉。如果留着它,插件是没了,但配置还在,而且每次启动都会打印:

dsh: [.../cordis.patch.yml] patch: entry "notification" not found

它只是警告不是失败 —— 应用照常启动,那些设置被忽略 —— 但在你删掉这段之前,每次启动都会报。 删掉之前想留个备份的话,先把这段复制出来。

如果你是从本地检出装的

用 link: 装出来的目录联接(junction),pnpm remove 不会清理,它会留在 node_modules 里、 指向你的检出。它不会让插件继续生效 —— 包已经从依赖表、bundles 表和插件名册里消失了 —— 但它 待在那里会让人以为还装着东西。手动删掉这个链接:

# 删的是链接,不是检出
cmd /c rmdir "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\@citisen\dsh-notification"

对目录联接执行 rmdir 只会删掉链接,D:\path\to\dsh-notification 原封不动。不要在不确定的时候 用 Remove-Item -Recurse:某些 PowerShell 版本会跟着联接进去,把后面的检出一起删掉。

设置

只想暂时关掉,不想卸载

把总音量拖到 0:所有卡片立刻安静,设置都留着,拖回来就恢复。要彻底关掉插件本身,用 dsh 自己的 插件管理器(改的是 profile 的 bundles 表,需要重启应用)。

所有东西都在 设置 → 通用 的这一行里:

  • 总音量 —— 与每张卡片自己的音量相乘,所以两个数字都有意义;0 就是静音。
  • 状态选择器 —— 左边竖排的六个状态。每一项都显示当前有几个会话处于这个状态,关掉的状态是灰的。 选中一个就显示它的卡片。

全局设置只有这一个,因为它是唯一一个全局问题能诚实回答的:多响。每一张卡片自己的开关回答 要不要,而那些已经删掉的开关回答的是你在不在看 —— 插件不知道,猜错一次就少响一次。

卡片上的控件:

| 控件 | 含义 | | --- | --- | | 启用这个状态 | 这张卡片唯一的开关 | | 音量 | 这张卡片的音量,与总音量相乘 | | 音色 | 下面十一种之一 | | 旋律 | 要播的音,见下 | | 试听 | 真的播出来;没响才说话 —— 见下 | | 恢复默认 | 把这张卡片的每个字段恢复成出厂值 |

「试听」一次做两件事,所以只有一个按钮而不是两个。它用真实的声音路径把这段声音播出来 —— 真的音色、真的旋律、这张卡片的音量与总音量相乘之后的真实结果 —— 声音本身就是回答:播出来了 就不打印任何字。卡片只在什么都没响的时候说话("音量为 0,所以不会出声"),因为那是唯一一个 靠听诊断不出来的情况。在一个关掉的状态上按它照样有意义:它会把这个卡片当成开着的来测。

音频状态那一行同理,只在还没弄好的时候出现:音频还没解锁 —— 点一次「试听」即可,或者这台 机器根本没有 Web Audio。能正常出声之后这一行就消失了 —— 一切正常的事没什么可报的。

第一次按它也是解锁音频的那一次点击。

为什么没有那些开关

早先这里有五个全局规则,回答的都是同一个问题:你现在在不在看? —— 什么时候出声(窗口不在前台 时 / 总是 / 从不出声)、不要提醒我正在看的那个会话、窗口在前台时完全安静、两次提示音的最小间隔、 同一状态的最短重复间隔。

它们全都删了,理由是同一个:猜错的代价正好落在插件存在的那个场合。一个对话开在主视图里,长任务 在跑,人去了别的应用 —— 窗口还是可见的,于是窗口不在前台时拒绝了这一声。本来防打扰的规则,防掉 的是通知。那两条开关式的规则之间还自相矛盾:在窗口不在前台时之下,"我正在看的会话不提醒"只可能 在一个已经被静音的场合里生效。

删掉之后还剩什么一直没变:一轮里同一个瞬间只出一声(界面一次发布好几个状态变化时,取最紧急的 那个),而相隔一秒的两个状态变化是两个事件,各出各的声音。要安静是音量的事,不是模式的事。

已知限制

  • 「执行完成」的判据是"一轮结束了",不是"这轮跑成功了"。 它是从会话安静下来这个边沿读的, 不是读 dsh 的未读标志 —— dsh 对主视图里那个会话抑制了这个标志,靠它的话,你正在看的那个对话 永远响不了。代价也写在明处:出错的一轮同样会"结束",如果错误报得比这一轮结束还晚,你可能听到 的是「执行完成」那一声,而它其实是「执行出错」。
  • 同一状态连着响几次是可能的。 没有重复间隔限制了:会话在状态之间来回横跳,每一次都会响。 嫌吵就关掉那张卡片,或者把它的音量调小。
  • 执行出错 的含义是"这个会话的 agent 报了一个错"。 dsh 不会转发是哪一轮,而且这个事件在重连 之后不会重放。
  • 音频需要一次点击来解锁才能出第一声。这是浏览器的自动播放策略,绕不过去;随便哪张卡片的 试听就是那次点击。在那之前这一行会写着"音频尚未初始化"。
  • 界面只有中英双语。

第一次按它也是解锁音频的那一次点击。

旋律

旋律写成音名加可选的时值:

A5:200ms E6:200ms          两个音,各响各自的时长
G4 G4 G4 Eb4:680ms         四个音;没写时值的用出厂步调
A5:120ms -:80ms E6:240ms   休止是不发声但占时间的一步
880 1318.5                 赫兹,给没有音名的音高
off                        这个状态不出声
  • 音名是 A5、C#4、Bb3 —— 任意八度,升号降号都认。
  • 写了时值的项目就占那么长:它响这么久,下一个在它结束时起音。s、ms、m 都行, 只写数字表示秒。
  • 没写时值的项目沿用出厂步调 —— 响 130ms、下一个晚 90ms 起音 —— 这才让 A5 E6 读起来是 一个音程,而不是两声分开的敲击。
  • 休止(-)占时间但不发声。
  • 赫兹数在音名的位置同样可用。

读不出来的内容会在输入框下面报出来,而且只损失它自己那一项 —— 一个笔误不会让整段旋律哑掉。

音色

出厂十一种。四条是单音波形,另外七种由分音构成,这才让它们听起来像乐器而不只是一个音:

| 音色 | 听起来像 | | --- | --- | | sine | 纯音 —— 最朴素的一声 | | triangle | 柔和长笛 —— 温和、泛音少 | | square | 芯片音 —— 空洞、一听就是电子声 | | sawtooth | 蜂鸣 —— 明亮刺耳,能从噪音里穿出来 | | bell | 敲击金属,尾巴很长 | | glass | 高、亮、短 | | marimba | 木条,衰减快而均匀 | | pluck | 短促的拨弦 | | wood | 几乎没有音高的敲击 —— 这组里最不打扰人的 | | blip | 极短的一声 | | digital | 两个分音的电子提示音 |

生成旋律

旋律是纯文本,所以可以由模型生成、并且不用听就能检查。分析器会打印一段旋律到底会做什么:

node scripts/analyze-sound.mjs "G4:170ms G4:170ms G4:170ms Eb4:680ms" --voice bell
node scripts/analyze-sound.mjs "A5:220ms -:80ms E6:400ms" --voice marimba --json
node scripts/analyze-sound.mjs --voices

它报告每个音的唱名、频率、起始时间、响多久,以及所选音色给它的包络。--json 输出同样的数据; 读不出来的 token 会让它以非零码退出 —— 于是生成器可以拿它当闸门。

开发

构建和设计说明见 DEVELOPMENT.md(英文)。

许可

MIT