dsh-plugin-notify-sounds 1.6.9 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # dsh-plugin-notify-sounds
2
2
 
3
+ [![awesome · DSH plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
4
+ [![Listed on dsh-plugin.org](https://dsh-plugin.org/badges/listed.svg)](https://dsh-plugin.org/plugins/billcx330/dsh-plugin-notify-sounds)
5
+ [![DeepSeek Harness plugin](https://img.shields.io/badge/dsh-plugin-8b5cf6.svg)](https://github.com/deepseek-ai/deepseek-harness)
3
6
  [![npm version](https://img.shields.io/npm/v/dsh-plugin-notify-sounds.svg)](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
4
7
  [![npm downloads](https://img.shields.io/npm/dm/dsh-plugin-notify-sounds.svg)](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
5
8
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
- [![DeepSeek Harness plugin](https://img.shields.io/badge/dsh-plugin-8b5cf6.svg)](https://github.com/deepseek-ai/deepseek-harness)
7
9
 
8
10
  English | [中文](README.zh.md)
9
11
 
@@ -34,7 +36,7 @@ Every visual detail of the settings section comes from DSH's own design system:
34
36
  | **Only what you care about** | Sub-agents (background tasks) are completely silent by default — only your own conversation is announced |
35
37
  | **Quiet when it should be** | Quiet hours (e.g. 22:00–08:00, wrapping past midnight), notify-only-when-hidden, and a master switch |
36
38
  | **Your sound, your way** | Nine built-in sounds, custom ringtone upload, volume — each feature with its own toggle |
37
- | **Update checks** | Check npm for a new version and install it in one click: verified against the published digest before anything is replaced, restored on failure; restart DSH to load it |
39
+ | **Update checks** | Check npm for a new version and install it in one click: verified against the published digest before anything is replaced, restored on failure with advice you can act on; restart DSH to load it |
38
40
 
39
41
  ## 💡 Why
40
42
 
@@ -74,7 +76,13 @@ The "install source" dropdown above the box picks the download mirror (mainland
74
76
 
75
77
  ### ⬆️ Upgrading
76
78
 
77
- DSH does not update plugins on its own, but this plugin **updates itself**: Settings → Sounds → Updates can check for a new version and install it in one click. Uninstalling and installing again also works.
79
+ **Upgrades are installed by the package manager**, so the profile's lockfile moves with the files — a DSH plugin cannot install its own update durably (the manager refuses a package that is already declared, and its remove-then-install step unloads the very code that would finish the install). The plugin therefore only *checks*, and tells you where to install:
80
+
81
+ - **Inside DSH (recommended)**: Settings → Plugins → remove this plugin → **Add plugin** → paste `dsh-plugin-notify-sounds` → Install → restart DSH.
82
+ - **With the marketplace plugin** ([dshmarket](https://www.npmjs.com/package/dshmarket)): update it in one click there.
83
+ - **On a `web` profile**: `dsh plugin --profile <your profile> add dsh-plugin-notify-sounds@<version>`.
84
+
85
+ The update row also warns when the running version is not what the profile's lockfile records — the state left behind by the pre-1.8.0 self-updater. One reinstall through the package manager fixes it for good.
78
86
 
79
87
  ### 🛠️ Other ways
80
88
 
@@ -84,7 +92,13 @@ DSH does not update plugins on its own, but this plugin **updates itself**: Sett
84
92
  dsh plugin --profile <your profile> add github:BillCx330/dsh-plugin-notify-sounds
85
93
  ```
86
94
 
87
- **Release archive** — download the `.tgz` from [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) and hand it to `dsh plugin add`.
95
+ **Release archive** — download the `.tgz` from [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) and install it by its **path on disk**:
96
+
97
+ ```sh
98
+ dsh plugin --profile <your profile> add ./dsh-plugin-notify-sounds-1.8.0.tgz
99
+ ```
100
+
101
+ (`dsh plugin add` hands its argument straight to the package manager, so it takes a local file path — a download URL will not work.)
88
102
 
89
103
  **Local directory** — for development or trying unreleased changes:
90
104
 
@@ -99,7 +113,8 @@ The command line writes `dsh.profile.bundles` and installs the dependency for yo
99
113
  ## ⚠️ Known limitations
100
114
 
101
115
  - **Hand-edited config**: preferences live in the profile's `cordis.patch.yml`; values must match the schema (volume 0–100, a preset id, `HH:MM` times) or the plugin declines to load — just fix the value. The settings UI only ever writes valid values.
102
- - **One-click update only swaps files**: it replaces the seven files this package ships and **never touches the profile's configuration**. Downloaded code is never executed — the new code loads on a **DSH restart**. Let the row report a result before closing the window (an interrupted update restores itself, but there is no reason to gamble); if a future release adds a dependency, that needs installing separately (this one has none).
116
+ - **Upgrades are installed by the package manager, not by the plugin**: 1.8.0 removed the self-installer (writing files in place never updated the profile's lockfile, so the next plugin install silently restored the old version). The update row still checks npm and reports a newer version, then points at the route that installs — Settings → Plugins (remove, then add again), the marketplace, or `dsh plugin add` on a web profile.
117
+ - **Versions up to 1.7.0** reach 1.8.0 through their own updater (1.8.0 keeps the same seven filenames), but that arrival is not registered with pnpm: reinstall once through the package manager as above and every later upgrade stays in place. Versions up to 1.6.9 cannot install a release that adds a file — their fixed whitelist refuses it safely; the same one-time reinstall fixes that too.
103
118
  - **Multiple windows** fire independently: the same event may chime once per window; turn on notify-only-when-hidden to avoid it.
104
119
  - **Click-to-return** is fully implemented and tested on Windows; macOS / Linux fall back to the system deep link and are unverified.
105
120
  - **The window is found by its title** — deliberately without inspecting other processes (that trips security software). If DSH ever changes its title format, click-to-return silently stops working; sounds and notifications are unaffected.
@@ -124,6 +139,8 @@ For anyone hacking on the code (exact details live in the source comments):
124
139
 
125
140
  ## 📜 Changelog
126
141
 
142
+ - **v1.8.0** (2026-10-20) **The plugin stops installing itself; the package manager owns upgrades.** Writing files in place never updated the profile's lockfile, so the next plugin install — or a market upgrade — silently restored the version pnpm had recorded: a 1.7.0 install could roll back to 1.6.9 with no warning. DSH 0.2.1 makes a durable self-install impossible from inside a plugin (the manager refuses a package that is already declared, and its remove-then-install step unloads the very code that would finish the install), so the self-installer is gone: the update row checks npm, reports the newer version, and points at the route that installs — Settings → Plugins (remove, then add again), the marketplace, or `dsh plugin add` on a web profile. It also compares the running version with the version the profile's lockfile would restore and **says so when they differ**, turning the silent rollback into a self-service fix. **New: goal-mode alerts wait for the goal to end** (issue #2) — a goal runs several automatic rounds and every round used to chime; the new switch **Only alert on the final goal round** stays silent on intermediate rounds and chimes once when the goal completes, pauses or blocks (ordinary sessions are unaffected; off by default). The release keeps the same seven filenames, so 1.6.9 / 1.7.0 installations still reach it through their own updater — after one reinstall through the package manager the upgrade is permanent.
143
+ - **v1.7.0** (2026-10-16) **The update mechanism turns a corner**: one-click update is no longer limited by a fixed list of seven filenames. It now accepts any regular file inside the package directory, governed by rules instead of an inventory — path traversal, absolute paths, symlinks, non-file entries, reserved names (its own backup/temp names and its record file, `.git`, `node_modules`, `.npmrc`), paths containing `:`, names colliding only by case, and a file that differs from the entry point `package.json` declares only by case are all still refused, with the file count and the decompressed size capped (enforced while inflating). **1.7.0 and later update cleanly into a release that adds or drops any number of files**: a file a later release drops is now actually deleted, based on the `.update-manifest.json` record this updater leaves behind — **only files an update installed are ever deleted**, anything you put in that directory yourself is left alone, and installations older than the first record are never guessed at. **1.6.9 and earlier will fail** (safely — nothing is written, the installed version keeps working) if a newer release adds a file, and the README says to reinstall once. Fixed: turning auto-check off ended the daily check chain for good, even after turning it back on; clicking a notification did nothing when the window title changed between the two Win32 reads; prerelease versions compared as strings (`rc.10` looked older than `rc.9`); **two tabs — or two windows — of the same GUI each rang the sound, raised their own system notification and ran their own repeat reminder** (one page is now elected to speak, via BroadcastChannel plus a shared claim, and the others stay silent until it disappears; per-window title marks are unaffected); and custom-sound normalization now visits **every sample** (taking every 8th frame aliased against content near fs/8 and systematically underestimated the peak). A failed update now gives **stage-appropriate advice** — retry for network failures, and the repository plus the uninstall/reinstall steps when the payload itself could not be applied, naming both versions — `package.json` is written **last** (a crash mid-swap leaves the old version number over the new code, so the next check still offers the update instead of declaring success), and the archive's manifest is verified to be this package at the version the registry named. The custom-sound row moved to sit **directly under the three trigger sounds** it is used by, and the smaller fixes on top: the cooldown table is a real LRU rather than FIFO (the session that fired most often was evicted first), one session-list snapshot per pass instead of per session, the macOS Desktop's window-title switch is now disabled rather than merely re-described, the full-width punctuation that leaked into the English update message is gone, and the README's release-archive instructions now give a command that actually works.
127
144
  - **v1.6.9** (2026-10-12) Fixes a README filename compatibility issue in v1.6.8: reverted to `README.md` (English) + `README.zh.md` (Chinese) so the update whitelist in every prior version can recognise them. A new filename would be refused by old users' updates — the whitelist is one-directional because the update runs old code.
128
145
  - **v1.6.8** (2026-10-12) Review fixes and optimizations: the auto-check first-frame timing gap is closed (`undefined` is no longer treated as permission to reach out); an orphaned JSDoc is removed; the teardown assertion now actually verifies listener removal; `normalizedGain` samples every 8th frame (2.6M → 330K iterations for a 30-second upload); the master gain disconnects after playback ends (no more audio-node leak); `swapNavIcon` is wrapped in try/catch and preserves the original node for restore on dispose (React re-renders can no longer crash it); the cooldown table evicts the oldest entry instead of clearing all; and `sessionRows` caches one snapshot per synchronous block.
129
146
  - **v1.6.7** (2026-10-12) Three fixes from the review: a macOS browser tab is no longer mislabeled "not supported" for the title alert (`isDesktopShell` is the right criterion, not `isMac` alone); the first-frame timing gap in the auto-check guard is closed (`undefined` is no longer treated as permission); and three comments that no longer matched the code are corrected. Plus BUG-1 regression tests covering the suspended AudioContext path.
package/README.zh.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # dsh-plugin-notify-sounds
2
2
 
3
+ [![awesome · DSH plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
4
+ [![Listed on dsh-plugin.org](https://dsh-plugin.org/badges/listed.svg)](https://dsh-plugin.org/plugins/billcx330/dsh-plugin-notify-sounds)
5
+ [![DeepSeek Harness plugin](https://img.shields.io/badge/dsh-plugin-8b5cf6.svg)](https://github.com/deepseek-ai/deepseek-harness)
3
6
  [![npm version](https://img.shields.io/npm/v/dsh-plugin-notify-sounds.svg)](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
4
7
  [![npm downloads](https://img.shields.io/npm/dm/dsh-plugin-notify-sounds.svg)](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
5
8
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
- [![DeepSeek Harness plugin](https://img.shields.io/badge/dsh-plugin-8b5cf6.svg)](https://github.com/deepseek-ai/deepseek-harness)
7
9
 
8
10
  [English](README.md) | 中文
9
11
 
@@ -34,7 +36,7 @@ dsh-plugin-notify-sounds
34
36
  | **只提醒你关心的** | 子智能体(后台任务)默认完全静默,只提醒主对话,可开关 |
35
37
  | **该安静时安静** | 静音时段(如 22:00–08:00,可跨午夜)、仅页面不可见时提示、总开关一键全静音 |
36
38
  | **声音随你** | 九种内置音效、自定义铃声上传、音量调节,每项独立开关 |
37
- | **检测更新** | 设置里检查 npm 新版本并一键更新:下载后校验完整性才替换,失败自动还原;更新后重启 DSH 生效 |
39
+ | **检测更新** | 设置里检查 npm 新版本并一键更新:下载后校验完整性才替换,失败自动还原并给出可照做的处理建议;更新后重启 DSH 生效 |
38
40
 
39
41
  ## 💡 为什么需要它
40
42
 
@@ -74,7 +76,13 @@ DSH 的状态提示只有视觉——状态点、侧栏标记。你一切到别
74
76
 
75
77
  ### ⬆️ 升级
76
78
 
77
- DSH 不会自动更新插件,但本插件**自带更新功能**:设置 → 提示音 →「更新」里可以检查新版并一键安装。想走手动路径也可以:在同一处先**卸载**旧版,再按上面的步骤装新版。
79
+ **升级由包管理器安装**,这样 profile 的 lockfile 会跟着一起更新——DSH 插件无法自己持久地更新自己(管理器拒绝已声明的包,而它的「先移除再安装」会先卸载掉正要完成安装的代码)。所以插件只负责**检查**,并告诉你从哪里装:
80
+
81
+ - **在 DSH 里(推荐)**:设置 → 插件 → 卸载本插件 → **添加插件** → 粘贴 `dsh-plugin-notify-sounds` → 安装 → 重启 DSH。
82
+ - **装了市场插件**([dshmarket](https://www.npmjs.com/package/dshmarket)):在市场里一键更新。
83
+ - **`web` profile**:`dsh plugin --profile <你的 profile> add dsh-plugin-notify-sounds@<版本>`。
84
+
85
+ 更新行还会提示「当前版本与 lockfile 记录不一致」——那是 1.8.0 之前的自更新留下的状态,按上面方式重装一次即可永久修好。
78
86
 
79
87
  ### 🛠️ 其他安装方式
80
88
 
@@ -84,7 +92,13 @@ DSH 不会自动更新插件,但本插件**自带更新功能**:设置 →
84
92
  dsh plugin --profile <你的 profile> add github:BillCx330/dsh-plugin-notify-sounds
85
93
  ```
86
94
 
87
- **Release 压缩包** —— 从 [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) 下载 `.tgz`,交给 `dsh plugin add`。
95
+ **Release 压缩包** —— 从 [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) 下载 `.tgz`,用它**在磁盘上的路径**安装:
96
+
97
+ ```sh
98
+ dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds-1.8.0.tgz
99
+ ```
100
+
101
+ (`dsh plugin add` 把参数原样交给包管理器,所以要给本地文件路径,不能填下载地址。)
88
102
 
89
103
  **本地目录** —— 开发或试用未发布的改动:
90
104
 
@@ -99,7 +113,8 @@ dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds
99
113
  ## ⚠️ 已知边界
100
114
 
101
115
  - **手改配置**:偏好写在 profile 的 `cordis.patch.yml`,值必须符合 schema(音量 0–100、音效为预设之一、时间 `HH:MM`);写错会让插件不加载,改回即可。设置界面只会写入合法值。
102
- - **一键更新只换文件**:只替换本包内的七个文件,**不碰 profile 配置**;下载内容从不执行,新代码要等**重启 DSH** 才生效。更新过程请等状态行给出结果再关窗口(中断会自动还原);若未来的新版引入了新依赖,需另行安装(当前零依赖)。
116
+ - **升级由包管理器安装,不再由插件自己完成**:1.8.0 移除了自安装器(原地写文件从不会更新 profile 的 lockfile,于是下一次插件安装会静默把旧版本装回来)。更新行仍会检查 npm、报告新版,然后指向真正负责安装的入口——设置 → 插件(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`。
117
+ - **1.7.0 及更早版本**可以通过它们自带的自更新到达 1.8.0(1.8.0 保持同样的七个文件名),但这次到达不会被 pnpm 登记:按上面的方式用包管理器重装一次,此后所有升级都会留下。1.6.9 及更早无法安装「新增了文件」的版本——固定白名单会安全拒绝;同样的一次性重装即可解决。
103
118
  - **多窗口**:各窗口独立触发,同一事件可能各响一次;打开「仅在页面不可见时提示」即可避免。
104
119
  - **点击通知回到窗口**:Windows 完整实现并实测;macOS / Linux 走系统深链,未验证。
105
120
  - **唤窗按窗口标题定位主窗口**:刻意不读取其他进程信息(那会触发杀软主动防御)。若将来 DSH 改变标题格式,唤窗会静默失效——提示音与通知本身不受影响。
@@ -123,6 +138,8 @@ dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds
123
138
 
124
139
  ## 📜 更新记录
125
140
 
141
+ - **v1.8.0**(2026-10-20)**插件不再自己安装更新,改由包管理器负责。** 原地写文件从不会更新 profile 的 lockfile,于是下一次插件安装(或市场升级)会静默把 pnpm 记录的版本装回来:1.7.0 的安装可能一声不响退回 1.6.9。DSH 0.2.1 让插件无法从内部持久地自安装(管理器拒绝已声明的包,而它的「先移除再安装」会先卸载掉正要完成安装的代码),所以自安装器被移除:更新行只检查 npm、报告新版,并指向真正负责安装的入口——设置 → 插件(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`。它还会把「运行版本」与「lockfile 会恢复的版本」做比较,**不一致时明确提示**,把静默回退变成用户可自助修复的状态。**新增:目标模式下等目标结束再提醒**(issue #2)——目标模式会自动进行多轮,原先每轮结束都会响;新开关「目标模式下只在最终轮提醒」让中间轮保持安静,只在目标完成、暂停或受阻时响一次(普通对话不受影响;默认关闭)。本版保持同样的七个文件名,1.6.9 / 1.7.0 的安装仍可通过它们自带的自更新到达 1.8.0——之后用包管理器重装一次,升级即永久生效。
142
+ - **v1.7.0**(2026-10-16)**更新机制的转折点**:一键更新不再受「固定七个文件名」的白名单约束,改为按规则接受包目录下的任何普通文件——路径穿越、绝对路径、符号链接、非普通文件、保留名字(更新器自己的备份/临时名与记录文件、`.git`、`node_modules`、`.npmrc`)、含 `:` 的路径段,以及只有大小写不同的重名或**与 `package.json` 声明的入口只差大小写**的文件,依然一律拒绝,文件数与解压体积也都有上限(解压时即受 `gunzip` 上限约束)。**1.7.0 及以后可以正常更新到任意增减文件的新版**:某个版本去掉的文件现在会真的被删掉(依据更新器自己留下的 `.update-manifest.json` 记录,**只删它自己装过的文件**,用户放进目录里的东西一律不动;第一条记录之前的安装不做任何猜测)。**1.6.9 及更早**遇到「新增了文件」的新版会更新失败(安全失败:一个字节都不写,已装版本继续正常工作),README 里说明了重装一次的办法。修复:关掉「自动检查更新」会让每日轮询永久停摆(重新打开也不恢复);窗口标题在两次 Win32 读取之间变短时,点通知唤窗会静默失效;预发布版本号按字符串比较(`rc.10` 被误判为比 `rc.9` 旧);**同一个 GUI 开多个标签页或多个窗口时提示音、系统通知、重复提醒全部翻倍**(现在由 BroadcastChannel + 本地记录选出一个「发声页」,其余页保持安静,只在发声页消失后接管;窗口标题标记各窗口独立,不受影响);自定义音效的峰值归一化改为**逐样本**扫描(原先每 8 帧抽样会与接近 fs/8 的高频混叠、系统性低估峰值)。更新失败时给出**按阶段区分的建议**(网络类提示重试;解包/替换类给出手动重装步骤与仓库地址,并列出失败的两个版本号),写入顺序改为**最后写 `package.json`**(中途崩溃时检查仍会提示更新,用户再点一次即可自愈),并会校验归档里的清单确实是本包、确实是 registry 报的那个版本。设置里「自定义音效」移到**三种提示音之后**(它们才是会用到它的三处);`settings` 相关的小修:冷却表改为真正的 LRU(原先是 FIFO,最常触发的会话反而最先被淘汰)、会话列表每轮只取一次快照、macOS 桌面版的「窗口标题提醒」开关改为**禁用**(原先能打开但标记无处显示)、英文界面更新提示里残留的全角标点修掉、README 的 Release 安装说明改为可照做的本地路径写法。
126
143
  - **v1.6.9**(2026-10-12)修正 v1.6.8 的 README 文件名兼容性:改回 `README.md`(英文默认)+ `README.zh.md`(中文),确保旧版本更新白名单能识别。新文件名会让旧用户的更新被拒——白名单是单向兼容的,更新时跑的是旧代码。
127
144
  - **v1.6.8**(2026-10-12)修复复核细节 + 优化:`autoCheck` 首帧时序补上(`undefined` 不再被当成允许联网);删孤立 JSDoc;teardown 断言改为真正验证监听器移除;`normalizedGain` 抽样(每 8 帧,260 万→33 万次);`master` gain 播完自动断连(不再泄漏音频节点);`swapNavIcon` try/catch + 保留原节点、dispose 时还原(React 重排不再炸);冷却表 LRU 淘汰(不再全清);`sessionRows` 同步块级快照缓存。
128
145
  - **v1.6.7**(2026-10-12)修复复核发现的 3 处细节:macOS 浏览器标签页不再被误标「暂不支持标题提醒」(`isDesktopShell` 才是判据);「自动检查=关」的首帧时序缺口补上(`undefined` 不再被当成允许);三处注释与实现不符已更正。补 BUG-1 回归测试(挂起 AudioContext 三断言)。