dsh-notify 0.1.6 → 0.1.7
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/CHANGELOG.md +6 -0
- package/README.en.md +9 -1
- package/README.md +8 -1
- package/docs/banner.svg +25 -0
- package/lib/index.js +33 -8
- package/package.json +1 -2
- package//350/256/276/350/256/241/346/226/207/347/250/277.md +0 -119
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.7] - 2026-09-10
|
|
4
|
+
|
|
5
|
+
- 安全:spawn 子进程环境变量清洗——剔除变量名含 KEY / SECRET / TOKEN / PASSWORD 的环境变量,防止宿主凭据经子进程泄漏;
|
|
6
|
+
- 修复:卸载时托盘进程 kill 后等待其退出再结束,无残留进程;
|
|
7
|
+
- 文档:功能节补充安全加固说明;相关插件表格修复断行。
|
|
8
|
+
|
|
3
9
|
## [0.1.6] - 2026-08-29
|
|
4
10
|
|
|
5
11
|
- 文档:删除与 FAQ 重复的「排障/触发时机」节;新增兼容性行(Windows 10/11 · Node ≥ 22.5 · DSH 0.1.1-rc.2 实测);
|
package/README.en.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.svg" alt="dsh-notify banner" width="100%">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
5
|
# dsh-notify
|
|
4
6
|
|
|
5
7
|

|
|
8
|
+

|
|
6
9
|

|
|
10
|
+

|
|
7
11
|

|
|
8
12
|
|
|
13
|
+
[中文](./README.md) | **English**
|
|
14
|
+
|
|
9
15
|
**The only dsh plugin with a system tray icon**: when the agent stops running (finished / aborted / error / waiting for your choice / session closed), a native Windows Toast pops up automatically with the body labeled "workspace · session", and a whale icon stays resident in the taskbar tray — switch away from the window during long tasks and one glance at the tray tells you whether it's done.
|
|
10
16
|
|
|
11
17
|
Zero runtime dependencies, zero build; one `dsh plugin add` command and it's ready to use.
|
|
@@ -22,6 +28,7 @@ Zero runtime dependencies, zero build; one `dsh plugin add` command and it's rea
|
|
|
22
28
|
- **Native Windows Toast notifications**: when the agent stops running (finished / aborted / error / output limit reached / waiting for your choice / session closed), a system notification pops up automatically with the body labeled "workspace · session" — tell at a glance which session finished;
|
|
23
29
|
- **Permanent system tray icon**: a whale icon stays resident in the taskbar tray; the right-click menu opens the dsh web page / quits the background process (competitors explicitly ship no tray — this plugin is the only one in the dsh ecosystem);
|
|
24
30
|
- **Anti-spam**: `rootsOnly` defaults to notifying only root sessions, so subagents won't flood you; `cooldownMs` sets the minimum interval between two notifications of the same type in the same session;
|
|
31
|
+
- **Security hardening**: the notification child process runs with a sanitized environment (variables whose names contain KEY / SECRET / TOKEN / PASSWORD are stripped, preventing credential leaks); on uninstall the tray process is killed and awaited before exit — no leftover processes;
|
|
25
32
|
- **Zero runtime dependencies, zero build**: one `dsh plugin add` command and it's ready to use.
|
|
26
33
|
|
|
27
34
|
## Use cases
|
|
@@ -88,6 +95,7 @@ This plugin is part of the **Pasumao dsh plugin ecosystem**; the published plugi
|
|
|
88
95
|
| [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-table-zoom) | Floating window for long chat tables + one-click Markdown copy |
|
|
89
96
|
| [dsh-plugin-windows-guard](https://www.npmjs.com/package/dsh-plugin-windows-guard) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-windows-guard) | Windows environment guard: rule skills + mojibake detection / dangerous-write interception / encoding diagnosis & repair |
|
|
90
97
|
| [dsh-plugin-workbench](https://www.npmjs.com/package/dsh-plugin-workbench) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-workbench) | VS Code-style file explorer + editable preview |
|
|
98
|
+
| [dsh-plugin-context-trim](https://www.npmjs.com/package/dsh-plugin-context-trim) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-context-trim) | Per-session injection gate: trim skills / tools / prompt sections per session |
|
|
91
99
|
|
|
92
100
|
> For the other plugins in the series, see [Pasumao · dsh plugins](https://github.com/Pasumao); if you find them useful, a ⭐ on GitHub is appreciated.
|
|
93
101
|
|
package/README.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.svg" alt="dsh-notify banner" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# dsh-notify
|
|
2
6
|
|
|
3
7
|

|
|
8
|
+

|
|
4
9
|

|
|
10
|
+

|
|
5
11
|

|
|
6
12
|
|
|
7
13
|
[**中文**](./README.md) | [English](./README.en.md)
|
|
@@ -21,6 +27,7 @@
|
|
|
21
27
|
- **Windows 原生 Toast 通知**:agent 不再运行时(完成 / 停止 / 出错 / 达到输出上限 / 等你选择 / 会话关闭)自动弹系统通知,正文标注「工作区 · 会话」,一眼知道哪个会话跑完了;
|
|
22
28
|
- **系统托盘常驻图标**:任务栏托盘鲸鱼图标常驻,右键菜单可唤起 dsh web 页面 / 退出后台(竞品均明确不做托盘,本插件是 dsh 生态唯一);
|
|
23
29
|
- **防刷屏**:`rootsOnly` 默认仅根会话通知,子代理不刷屏;`cooldownMs` 同会话同类型两次通知最小间隔;
|
|
30
|
+
- **安全加固**:弹通知的子进程环境变量经清洗(剔除含 KEY / SECRET / TOKEN / PASSWORD 的变量),托盘进程退出前不残留凭据;卸载时托盘进程 kill 后等待退出再结束,无残留进程;
|
|
24
31
|
- **零运行时依赖、零构建**,`dsh plugin add` 一条命令装完即用。
|
|
25
32
|
|
|
26
33
|
## 使用场景
|
|
@@ -88,7 +95,7 @@ node scripts/test-harness.mjs # 弹三条真实 Toast 自测
|
|
|
88
95
|
| [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-table-zoom) | 聊天长表格浮窗查看 + 一键复制 Markdown |
|
|
89
96
|
| [dsh-plugin-windows-guard](https://www.npmjs.com/package/dsh-plugin-windows-guard) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-windows-guard) | Windows 环境防坑:守则技能 + 乱码检测 / 危险写拦截 / 编码诊断修复 |
|
|
90
97
|
| [dsh-plugin-workbench](https://www.npmjs.com/package/dsh-plugin-workbench) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-workbench) | VS Code 风格文件浏览器 + 可编辑预览 |
|
|
91
|
-
|
|
98
|
+
| [dsh-plugin-context-trim](https://www.npmjs.com/package/dsh-plugin-context-trim) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-context-trim) | 会话注入门控:skill / tool / 提示词段落按会话裁剪 |
|
|
92
99
|
> 本系列其余插件见 [Pasumao · dsh 插件](https://github.com/Pasumao);觉得好用欢迎到 GitHub 点 ⭐。
|
|
93
100
|
|
|
94
101
|
## AI 生成声明
|
package/docs/banner.svg
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="260" viewBox="0 0 1200 260" role="img" aria-label="dsh-notify banner">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0a1830"/>
|
|
5
|
+
<stop offset="1" stop-color="#102a4c"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<radialGradient id="glow" cx="0.85" cy="0.1" r="0.9">
|
|
8
|
+
<stop offset="0" stop-color="#4ADE80" stop-opacity="0.22"/>
|
|
9
|
+
<stop offset="1" stop-color="#4ADE80" stop-opacity="0"/>
|
|
10
|
+
</radialGradient>
|
|
11
|
+
<linearGradient id="whale" x1="0" y1="0" x2="0" y2="1">
|
|
12
|
+
<stop offset="0" stop-color="#ffffff"/>
|
|
13
|
+
<stop offset="1" stop-color="#cfe3ff"/>
|
|
14
|
+
</linearGradient>
|
|
15
|
+
</defs>
|
|
16
|
+
<rect width="1200" height="260" rx="18" fill="url(#bg)"/>
|
|
17
|
+
<rect width="1200" height="260" rx="18" fill="url(#glow)"/>
|
|
18
|
+
<rect x="0" y="0" width="1200" height="6" rx="3" fill="#4ADE80" opacity="0.85"/>
|
|
19
|
+
<g transform="translate(64,80) scale(2.0)">
|
|
20
|
+
<path d="M48.8354 10.0479C48.3232 9.79199 48.1025 10.2798 47.8032 10.5278C47.7007 10.6079 47.6143 10.7119 47.5273 10.8076C46.7793 11.624 45.9048 12.1597 44.7622 12.0957C43.0923 12 41.666 12.5356 40.4058 13.8398C40.1377 12.2319 39.2476 11.272 37.8926 10.6558C37.1836 10.3359 36.4668 10.0156 35.9702 9.31982C35.6235 8.82373 35.5293 8.27197 35.356 7.72754C35.2456 7.3999 35.1353 7.06396 34.7651 7.00781C34.3633 6.94385 34.2056 7.2876 34.0479 7.57568C33.418 8.75195 33.1733 10.0479 33.1973 11.3599C33.2524 14.312 34.4736 16.6641 36.8999 18.3359C37.1758 18.5278 37.2466 18.7197 37.1597 19C36.9946 19.5757 36.7974 20.1357 36.624 20.7119C36.5137 21.0801 36.3486 21.1597 35.9624 21C34.6309 20.4321 33.481 19.5918 32.4644 18.5757C30.7393 16.8721 29.1792 14.9917 27.2334 13.52C26.7764 13.1758 26.3193 12.856 25.8467 12.5518C23.8618 10.584 26.1069 8.96777 26.627 8.77588C27.1704 8.57568 26.8159 7.8877 25.0591 7.896C23.3022 7.90381 21.6953 8.50391 19.647 9.30371C19.3477 9.42383 19.0322 9.51172 18.7095 9.58398C16.8501 9.22363 14.9199 9.14355 12.9033 9.37598C9.10596 9.80762 6.07275 11.6396 3.84326 14.7681C1.16455 18.5278 0.53418 22.7998 1.30664 27.2559C2.11768 31.9521 4.46582 35.8398 8.07373 38.8799C11.8159 42.0322 16.1255 43.5762 21.041 43.2803C24.0269 43.104 27.3516 42.6963 31.1016 39.4561C32.0469 39.936 33.0396 40.1279 34.686 40.272C35.9546 40.3921 37.1758 40.208 38.1211 40.0078C39.6021 39.688 39.4995 38.2881 38.9639 38.0322C34.623 35.9678 35.5762 36.8081 34.71 36.1279C36.9155 33.4639 40.2402 30.6958 41.54 21.728C41.6426 21.0161 41.5557 20.5679 41.54 19.9917C41.5322 19.6396 41.6108 19.5039 42.0049 19.4639C43.0923 19.3359 44.1479 19.0317 45.1167 18.4878C47.9292 16.9199 49.064 14.3438 49.3315 11.2559C49.3711 10.7837 49.3237 10.2959 48.8354 10.0479ZM24.3262 37.8398C20.1196 34.4639 18.0791 33.3521 17.2358 33.3999C16.4482 33.4482 16.5898 34.3682 16.7632 34.9678C16.9443 35.5601 17.1812 35.9683 17.5117 36.4878C17.7402 36.832 17.8979 37.3442 17.2832 37.728C15.9282 38.584 13.5728 37.4399 13.4624 37.3838C10.7207 35.7358 8.42822 33.5601 6.81348 30.584C5.25342 27.7197 4.34766 24.6479 4.19775 21.3677C4.1582 20.5757 4.38672 20.2959 5.15869 20.1519C6.17529 19.96 7.22314 19.9199 8.23926 20.0718C12.5327 20.7119 16.1885 22.6719 19.2529 25.7759C21.002 27.5439 22.3252 29.6558 23.6885 31.7202C25.1377 33.9121 26.6978 36 28.6831 37.7119C29.3843 38.312 29.9434 38.7681 30.479 39.104C28.8643 39.2881 26.1699 39.3281 24.3262 37.8398ZM26.3433 24.6001C26.3433 24.248 26.6191 23.9678 26.9658 23.9678C27.0444 23.9678 27.1152 23.9839 27.1782 24.0078C27.2651 24.04 27.3438 24.0879 27.4067 24.1602C27.5171 24.272 27.5801 24.4321 27.5801 24.6001C27.5801 24.9521 27.3042 25.2319 26.9575 25.2319C26.6108 25.2319 26.3433 24.9521 26.3433 24.6001ZM32.6064 27.8799C32.2046 28.0479 31.8027 28.1919 31.4165 28.208C30.8179 28.2397 30.1641 27.9922 29.8096 27.688C29.2583 27.2158 28.8643 26.9521 28.6987 26.1279C28.6279 25.7759 28.6675 25.2319 28.7305 24.9199C28.8721 24.248 28.7144 23.8159 28.2495 23.4238C27.8716 23.104 27.3911 23.0161 26.8633 23.0161C26.666 23.0161 26.4849 22.9277 26.3511 22.856C26.1304 22.7441 25.9492 22.4639 26.1226 22.1201C26.1777 22.0078 26.4458 21.7358 26.5088 21.688C27.2256 21.272 28.0527 21.4077 28.8169 21.7197C29.5259 22.0161 30.0615 22.5601 30.834 23.3281C31.6216 24.2559 31.7632 24.5117 32.2124 25.208C32.5669 25.752 32.8901 26.312 33.1104 26.9521C33.2446 27.3521 33.0713 27.6802 32.6064 27.8799Z" fill="url(#whale)"/>
|
|
21
|
+
</g>
|
|
22
|
+
<text x="212" y="86" font-family="'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif" font-size="17" font-weight="600" letter-spacing="5" fill="#4ADE80">DEEPSEEK HARNESS · DSH PLUGIN</text>
|
|
23
|
+
<text x="212" y="152" font-family="ui-monospace,'Cascadia Code',Consolas,monospace" font-size="46" font-weight="700" fill="#f4f8ff">dsh-notify</text>
|
|
24
|
+
<text x="212" y="204" font-family="'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif" font-size="22" fill="#9fb3c8">Windows 原生 Toast 通知 · 系统托盘常驻 · agent 停止即知</text>
|
|
25
|
+
</svg>
|
package/lib/index.js
CHANGED
|
@@ -88,6 +88,20 @@ function defaultTrayIconPath() {
|
|
|
88
88
|
/** 当前托盘图标的子进程(模块级:进程内同一时刻至多一个托盘图标)。 */
|
|
89
89
|
let trayChild = null
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* 清洗后的子进程环境:拷贝 process.env 并剔除疑似密钥项
|
|
93
|
+
* (key 名匹配 /KEY|SECRET|TOKEN|PASSWORD/i,大小写不敏感)——
|
|
94
|
+
* toast/tray 脚本只需要系统与通知变量,不该继承 dsh 进程里的凭据。
|
|
95
|
+
*/
|
|
96
|
+
function sanitizedEnv(extra = {}) {
|
|
97
|
+
const env = {}
|
|
98
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
99
|
+
if (/KEY|SECRET|TOKEN|PASSWORD/i.test(key)) continue
|
|
100
|
+
env[key] = value
|
|
101
|
+
}
|
|
102
|
+
return { ...env, ...extra }
|
|
103
|
+
}
|
|
104
|
+
|
|
91
105
|
/**
|
|
92
106
|
* 弹 Toast 的 PowerShell 脚本。全部参数从环境变量读取:
|
|
93
107
|
* DSH_NOTICE_TITLE / DSH_NOTICE_BODY / DSH_NOTICE_LOCATION(「工作区 · 会话」行) /
|
|
@@ -131,14 +145,13 @@ function fireToast(ctx, cfg, { title, body, location = '' }) {
|
|
|
131
145
|
ps,
|
|
132
146
|
['-NoProfile', '-STA', '-WindowStyle', 'Hidden', '-EncodedCommand', encoded],
|
|
133
147
|
{
|
|
134
|
-
env: {
|
|
135
|
-
...process.env,
|
|
148
|
+
env: sanitizedEnv({
|
|
136
149
|
DSH_NOTICE_TITLE: title,
|
|
137
150
|
DSH_NOTICE_BODY: body,
|
|
138
151
|
DSH_NOTICE_LOCATION: location,
|
|
139
152
|
DSH_NOTICE_ICON_PATH: existsSync(iconPath) ? iconPath : '',
|
|
140
153
|
DSH_NOTICE_AUMID: cfg.aumid,
|
|
141
|
-
},
|
|
154
|
+
}),
|
|
142
155
|
windowsHide: true,
|
|
143
156
|
stdio: 'ignore',
|
|
144
157
|
},
|
|
@@ -297,12 +310,11 @@ export function apply(ctx, config = {}) {
|
|
|
297
310
|
defaultPowershellPath(),
|
|
298
311
|
['-NoProfile', '-STA', '-WindowStyle', 'Hidden', '-ExecutionPolicy', 'Bypass', '-File', trayPath, '-ParentPid', String(process.pid), '-IconPath', defaultTrayIconPath(), '-WebUrl', cfg.webUrl],
|
|
299
312
|
{
|
|
300
|
-
env: {
|
|
301
|
-
...process.env,
|
|
313
|
+
env: sanitizedEnv({
|
|
302
314
|
DSH_TRAY_TOOLTIP: 'dsh 后台运行中',
|
|
303
315
|
DSH_TRAY_OPEN: '打开 dsh',
|
|
304
316
|
DSH_TRAY_EXIT: '关闭进程',
|
|
305
|
-
},
|
|
317
|
+
}),
|
|
306
318
|
windowsHide: true,
|
|
307
319
|
stdio: 'ignore',
|
|
308
320
|
},
|
|
@@ -471,14 +483,27 @@ export function apply(ctx, config = {}) {
|
|
|
471
483
|
const offSession = ctx.on('session/event', onSessionEvent)
|
|
472
484
|
const offDisposed = ctx.on('agent/disposed', onDisposed)
|
|
473
485
|
|
|
474
|
-
ctx.effect(() => () => {
|
|
486
|
+
ctx.effect(() => async () => {
|
|
475
487
|
offStatus()
|
|
476
488
|
offSession()
|
|
477
489
|
offDisposed()
|
|
478
490
|
states.clear()
|
|
479
491
|
if (trayChild) {
|
|
480
|
-
|
|
492
|
+
const child = trayChild
|
|
481
493
|
trayChild = null
|
|
494
|
+
// kill 后等待托盘进程真正退出(上限 2s 兜底),再结束 dispose。
|
|
495
|
+
await new Promise((resolve) => {
|
|
496
|
+
let done = false
|
|
497
|
+
const finish = () => {
|
|
498
|
+
if (!done) {
|
|
499
|
+
done = true
|
|
500
|
+
resolve()
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
try { child.once('exit', finish) } catch { finish() }
|
|
504
|
+
try { child.kill() } catch { finish() }
|
|
505
|
+
setTimeout(finish, 2000)
|
|
506
|
+
})
|
|
482
507
|
}
|
|
483
508
|
})
|
|
484
509
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-notify",
|
|
3
3
|
"description": "Native Windows toast + system tray for DeepSeek Harness (dsh): the only dsh plugin with a tray icon. Pops the moment the agent stops running — finished / aborted / error / output limit / waiting for your choice / session closed — body labeled with workspace · session, so you can switch windows during long tasks and glance at the tray instead of watching a spinner. Pure host-side, zero dependencies, zero build.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"README.md",
|
|
18
18
|
"README.en.md",
|
|
19
19
|
"CHANGELOG.md",
|
|
20
|
-
"设计文稿.md",
|
|
21
20
|
"LICENSE"
|
|
22
21
|
],
|
|
23
22
|
"scripts": {
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# dsh-plugin-notify 设计文稿
|
|
2
|
-
|
|
3
|
-
> 需求:设计一个 dsh 插件——只要 agent「没在运行了」(完成了绘画/生成等任务、被停止、出错、或停下来让我选择),就在 Windows 上弹系统提示提醒我。
|
|
4
|
-
|
|
5
|
-
## 1. 目标与范围
|
|
6
|
-
|
|
7
|
-
| 项 | 内容 |
|
|
8
|
-
|---|---|
|
|
9
|
-
| 目标 | 用户用 DSH Web GUI 发起长任务后离开电脑;当 agent 不再运行时弹 Windows 通知,叫用户回来看结果。通知正文标注「工作区 · 会话」位置行,用户能直接知道是哪个工作区的哪个会话完成了。 |
|
|
10
|
-
| 形态 | 纯 **host 端** Cordis 插件(`lib/index.js`,普通 ESM),零运行时依赖、零构建步骤。 |
|
|
11
|
-
| 通知形式 | Windows 原生 Toast(`ToastNotificationManager`),`scenario="reminder"` 常驻直到手动关闭,带 dsh 鲸鱼 logo,点击打开 dsh 页面。 |
|
|
12
|
-
| 后台指示 | 系统托盘(任务栏右下角)常驻 dsh 鲸鱼图标(`NotifyIcon`),双击/右键打开 dsh、右键关闭 dsh 后台,dsh 退出后自动消失。 |
|
|
13
|
-
| 非目标 | 点击通知精确跳转到某个会话(web 端无 URL 深链,且借用 AUMID 的 toast 点击激活在本机不可靠,已放弃)。 |
|
|
14
|
-
|
|
15
|
-
## 2. 关键结论(对 dsh 源码的调研)
|
|
16
|
-
|
|
17
|
-
1. **插件注册(标准 bundle)**:依赖的 `package.json` 声明 `dsh.bundle.patch`(指向包内 `cordis.patch.yml`),`dsh plugin --profile <name> add <pkg>` 安装后自动把该包加入 `dsh.profile.bundles` 层(校准逻辑见 `dsh` 的 `plugin` 子命令:按已装依赖里声明了 `dsh.bundle` 的包追加)。包内补丁用 `- insert: [{ id, name, config? }]` 注册自身,用户层 `cordis.patch.yml` 后应用、按 id 覆盖 config。本插件发布名 `dsh-notify`,补丁 `name` 与 `package.json.name` 一致。
|
|
18
|
-
2. **"不再运行"信号**:`@deepseek-ai/dsh-agent` 的 `agent/status`(`idle ⇄ running`),`running → idle` 即"不再运行";scope 过滤下未打标签的根 ctx 监听者能收到所有 agent 事件。
|
|
19
|
-
3. **结束原因**:`session/event` 的 `turn/end` 带 `TurnEndReason`:`completed / aborted / blocked / error / max-tokens / interrupted`。
|
|
20
|
-
4. **"等你选择"信号**:`ask_user_question` 执行时阻塞、agent 保持 `running`,用日志里未配对的 `tool/call`(`name:'ask_user_question'`)检测,`tool/result.message.callId` 配对即结束。
|
|
21
|
-
5. **配置传递**:cordis loader 调 `apply(ctx, config)`;patch 条目可带 `config:`。
|
|
22
|
-
6. **Windows 通知**:`powershell.exe`(5.1) 恒在 `%WINDIR%\System32\WindowsPowerShell\v1.0\`;用 `ToastNotificationManager` 发原生 Toast,AUMID 借用 PowerShell 已注册的 `{1AC14E77-...}\WindowsPowerShell\v1.0\powershell.exe`;脚本经 `-EncodedCommand`(UTF-16LE base64)传入、数据经 `env`(UTF-16)传入,规避引号/代码页问题。
|
|
23
|
-
7. **位置标注数据源**:`ctx.workspaceRegistry`(`dsh-web-app` 提供)`list()` 返回带 `title`/`path`/`sessionIds` 的工作区,按 `sessionIds.includes(id)` 同步匹配归属;`ctx.sessionTitle`(`dsh-base` 提供)`get(session)` 返回 sidebar 显示的会话标题。两者都是进程内同步读,通知时现取即可,异常/缺失时优雅降级。
|
|
24
|
-
|
|
25
|
-
## 3. 架构
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
D:\dsh\plugins\dsh-plugin-notify\
|
|
29
|
-
├── package.json # dsh-notify;main: lib/index.js;dsh.bundle.patch: ./cordis.patch.yml
|
|
30
|
-
├── cordis.patch.yml # bundle 补丁:- insert 注册 dsh-plugin-notify 行
|
|
31
|
-
├── lib/index.js # host 半区:事件订阅 + 状态机 + Toast 派发 + 托盘图标
|
|
32
|
-
├── assets/
|
|
33
|
-
│ ├── dsh.png # Toast 图标(黑色鲸鱼 logo,256×256)
|
|
34
|
-
│ └── dsh.ico # 托盘图标(黑色鲸鱼 logo,32×32)
|
|
35
|
-
├── 设计文稿.md # 本文档
|
|
36
|
-
├── README.md # 安装/配置/排障
|
|
37
|
-
└── scripts/
|
|
38
|
-
├── tray.ps1 # 系统托盘图标(常驻,父进程退出后自动消失)
|
|
39
|
-
├── smoke-notice.ps1 # 独立冒烟:直接弹一条 Toast
|
|
40
|
-
└── test-harness.mjs # 端到端自测:驱动处理器弹三条真实 Toast
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
数据流:
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
agent 循环 ──agent/status──▶ 状态机(每会话) ──running→idle──▶ 组装文案 ──▶ spawn powershell ──▶ Toast(点击打开 dsh 页面)
|
|
47
|
-
──session/event─▶ 状态机(记录 turn/reason/摘要/等待) ──等待/完成──▶ 同上
|
|
48
|
-
──agent/disposed▶ 状态机(兜底"已关闭")
|
|
49
|
-
宿主启动 ──▶ spawn tray.ps1 ──▶ 系统托盘常驻图标(父进程退出 → 图标消失)
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## 4. 事件订阅与状态机
|
|
53
|
-
|
|
54
|
-
每个被跟踪的会话维护一条状态记录(`Map<agentId, State>`):`running`、`turnStarted`(区分空转与真实工作)、`lastReason`、`lastPrompt`、`waiting/waitingCallId/waitingText`、`session`(最近可见会话对象引用)、`workspaceLabel/sessionLabel`(「工作区 · 会话」标签缓存)、`lastToastAt[kind]`(按类型冷却)。
|
|
55
|
-
|
|
56
|
-
| 事件 | 动作 |
|
|
57
|
-
|---|---|
|
|
58
|
-
| `agent/status` running | `running=true` |
|
|
59
|
-
| `agent/status` idle | 若 `running=true` 且 `turnStarted||waiting` → 按 `lastReason` 选文案通知;空转不通知 |
|
|
60
|
-
| `session/event` `turn/start` | `turnStarted=true` |
|
|
61
|
-
| `session/event` `turn/end` | 记录 `lastReason` |
|
|
62
|
-
| `session/event` `user/message` | 记录 `lastPrompt`(首个文本块摘要) |
|
|
63
|
-
| `session/event` `tool/call`(`ask_user_question`) | 置 `waiting`,立即通知"等你选择" |
|
|
64
|
-
| `session/event` `tool/result`(配对) | 清除 `waiting` |
|
|
65
|
-
| `agent/disposed` | 若曾 running → 通知"会话已关闭";删状态 |
|
|
66
|
-
|
|
67
|
-
结束原因 → 标题:`completed`→任务完成、`aborted`→任务已停止、`error/interrupted`→任务出错、`max-tokens`→达到输出上限、`blocked`→回合被阻断。
|
|
68
|
-
|
|
69
|
-
## 5. 关键实现细节
|
|
70
|
-
|
|
71
|
-
### 5.1 Toast 派发(fire-and-forget)
|
|
72
|
-
|
|
73
|
-
`TOAST_SCRIPT` 用 `ToastNotificationManager` 发 `<toast scenario="reminder" activationType="protocol" launch="<webUrl>">`(整条常驻且点击打开 dsh 页面),`<image placement="appLogoOverride" src="file:///…dsh.png">` 显示鲸鱼 logo。脚本经 `-EncodedCommand` 传入、数据经 `env` 传入;进程失败只 `ctx.logger.warn`,不影响 dsh。
|
|
74
|
-
|
|
75
|
-
正文由三个 `<text>` 组成:标题、任务摘要/等待文案、位置行(`工作区「…」 · 会话「…」`,经 `DSH_NOTICE_LOCATION` 环境变量传入,为空则省略该元素)。位置行在 `notify()` 时现取:`resolveWorkspaceLabel` 先按 `workspaceRegistry.list()` 的 `sessionIds` 匹配归属标题、兜底 cwd 目录名;`resolveSessionLabel` 优先 `sessionTitle.get(session).title`,再直接折会话日志 `session/title` 事件(与 `foldSessionTitle` 同款,插件 ctx 上服务不可见时仍能取到标题)、兜底会话 id 短号;两者均含长度截断,服务缺失时自动降级(无服务 → 无位置行)。
|
|
76
|
-
|
|
77
|
-
### 5.2 系统托盘图标
|
|
78
|
-
|
|
79
|
-
host 半区 `apply` 时 `spawn(powershell.exe -STA -File scripts/tray.ps1 -ParentPid <pid> …)`,`tray.ps1` 用 `NotifyIcon` + `Application.Run()` 常驻;内置 `Timer` 每 3s 检查父进程 PID,父进程消失即退出;模块级 `trayChild` 保证进程内至多一个。双击/右键「打开 dsh」`Start-Process <webUrl>`,右键「关闭进程」`Stop-Process <父 PID>`。
|
|
80
|
-
|
|
81
|
-
### 5.3 防抖与空转过滤
|
|
82
|
-
|
|
83
|
-
激活时把已 `running` 的 agent 记为"有活动"(完成时照常通知),空闲 agent 不建状态(避免历史会话刷屏);`idle→running→idle` 且无 `turn/start` 不通知;冷却按类型记录,`cooldownMs` 内同类型不重复。
|
|
84
|
-
|
|
85
|
-
## 6. 配置文件
|
|
86
|
-
|
|
87
|
-
patch 条目 `config`(全部有默认值,见 `README.md` 表格)。核心字段:`enabled`、`tray`、`rootsOnly`、`notifyFinished/Aborted/Error/Waiting/Disposed`、`cooldownMs`、`titlePrefix`(默认 `'dsh'`)、`iconPath`(默认 `assets/dsh.png`)、`webUrl`、`aumid`、`summaryMaxChars`、`powershellPath`。
|
|
88
|
-
|
|
89
|
-
## 7. 安装步骤
|
|
90
|
-
|
|
91
|
-
本项目是标准 DSH bundle:`package.json` 声明 `dsh.bundle.patch: ./cordis.patch.yml`,包内自带 `cordis.patch.yml`(`- insert: [{ id: dsh-plugin-notify, name: dsh-notify }]`)。`dsh plugin` 命令是 pnpm 转发器,安装成功后按「已装依赖中声明了 `dsh.bundle` 的包」自动校准 `dsh.profile.bundles`,无需手动写补丁。
|
|
92
|
-
|
|
93
|
-
安装方式(任选其一):
|
|
94
|
-
|
|
95
|
-
1. **npm**(推荐):`dsh plugin --profile web add dsh-notify`。
|
|
96
|
-
2. **GitHub**:`dsh plugin --profile web add github:Pasumao/dsh-plugin-notify`(零构建,一般无需 allowBuilds)。
|
|
97
|
-
3. **本地路径**:`dsh plugin --profile web add D:/dsh/plugins/dsh-plugin-notify`。
|
|
98
|
-
4. **手动 link**(旧版流程):dependencies 加 `"dsh-notify": "link:D:/dsh/plugins/dsh-plugin-notify"` 后 `pnpm install`。
|
|
99
|
-
|
|
100
|
-
装完重启 `dsh web`(托盘图标出现即加载成功)。调整行为时在用户层 `cordis.patch.yml` 按 id 覆盖 config。
|
|
101
|
-
|
|
102
|
-
## 8. 边界与备选
|
|
103
|
-
|
|
104
|
-
| 情况 | 处理 |
|
|
105
|
-
|---|---|
|
|
106
|
-
| 重载时已空闲的历史会话 | 不建状态、不通知 |
|
|
107
|
-
| 唤醒后被清空的空转 | 无 `turn/start`,不通知 |
|
|
108
|
-
| 子代理大量完成 | `rootsOnly` 默认过滤(`delegationDepth`) |
|
|
109
|
-
| 中文乱码 | `env`(UTF-16) + `-EncodedCommand`(UTF-16LE base64) |
|
|
110
|
-
| PowerShell 缺失/失败 | 仅 warn,不崩溃 |
|
|
111
|
-
| HMR 重复加载 | `ctx.effect` 清理监听/状态/托盘 |
|
|
112
|
-
|
|
113
|
-
备选(记录):点击精确跳会话需注册 dsh 自有 AUMID(`SHGetPropertyStoreFromParsingName` 在本机返回 `0x80070057` 未成功),或用 BurntToast 模块(`Install-Module BurntToast`)实现可点击 toast。
|
|
114
|
-
|
|
115
|
-
## 9. 测试与验收
|
|
116
|
-
|
|
117
|
-
1. `scripts/smoke-notice.ps1` 独立弹 Toast;`node scripts/test-harness.mjs` 驱动处理器弹三条真实 Toast(等待/完成/停止)。
|
|
118
|
-
2. 端到端(重启后):正常任务完成弹 Toast、点停止弹"任务已停止"、`ask_user_question` 等待期弹"在等你选择"、重载旧会话不弹、子代理不刷屏、关闭 running 会话弹"已关闭";托盘图标常驻、父进程退出自动消失、点击打开 dsh。
|
|
119
|
-
3. 日志:`ctx.logger` 记录每次通知的 kind/session/「工作区 · 会话」位置行与 spawn 错误。
|