dsh-macos-notify 0.2.1 → 0.3.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 +8 -9
- package/client.js +9 -1
- package/index.js +19 -7
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# dsh-macos-notify
|
|
2
2
|
|
|
3
|
-
Native macOS notifications for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), with event-specific sounds, notification filtering, multi-task coalescing, and a settings
|
|
3
|
+
Native macOS notifications for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), with event-specific sounds, notification filtering, multi-task coalescing, and a first-level settings page in the DSH Web UI.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- Notification Center alerts when a turn completes, fails, is blocked, or waits for approval.
|
|
8
8
|
- Separate sounds for completed, error, aborted, and approval events; any event can be muted.
|
|
9
|
-
- System sound picker plus managed custom sound import and deletion from the Web settings
|
|
9
|
+
- System sound picker plus managed custom sound import and deletion from the Web settings page.
|
|
10
10
|
- Custom imports are converted to AIFF, limited to 5 MB and 10 seconds, capped at 20 managed files / 50 MB total, and stored in `~/Library/Sounds`.
|
|
11
11
|
- A 1.5-second coalescing window and optional digest mode prevent parallel tasks from flooding Notification Center.
|
|
12
12
|
- Recent notification diagnostics explain whether an event was sent, queued, suppressed, or failed.
|
|
@@ -41,7 +41,7 @@ Alternatively, install the latest source directly from GitHub:
|
|
|
41
41
|
npx -y @deepseek-ai/dsh plugin --profile web add github:CrombastiC/dsh-macos-notify
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Then open **Settings →
|
|
44
|
+
Then open **Settings → macOS notifications** from the first-level settings navigation.
|
|
45
45
|
|
|
46
46
|
To remove the plugin:
|
|
47
47
|
|
|
@@ -88,7 +88,6 @@ The settings namespace is `macos-notify`. Values changed from the Web card apply
|
|
|
88
88
|
| `pauseUntil` | `0` | Temporary pause deadline as Unix milliseconds; managed by quick actions in the Web card. |
|
|
89
89
|
| `duplicateWindowSec` | `300` | Suppress identical errors from the same session within this window; `0` disables it. |
|
|
90
90
|
| `projectRulesJson` | `[]` | Project rules managed by the Web card. More-specific descendant paths win. |
|
|
91
|
-
| `notifyOnLoad` | `true` | Send a test notification when the plugin loads. |
|
|
92
91
|
|
|
93
92
|
### Project rule modes
|
|
94
93
|
|
|
@@ -96,7 +95,7 @@ The settings namespace is `macos-notify`. Values changed from the Web card apply
|
|
|
96
95
|
- `errors` — allow only errors, blocked events, and approval requests.
|
|
97
96
|
- `important` — bypass minimum-duration, focus, idle, quiet-hour, and temporary-pause filters.
|
|
98
97
|
|
|
99
|
-
The settings
|
|
98
|
+
The settings page keeps the last 50 decisions in process memory. Each row records whether an event was sent, queued, suppressed, or failed and includes the reason. This history resets when DSH restarts and does not contain message content.
|
|
100
99
|
|
|
101
100
|
## Notification channels
|
|
102
101
|
|
|
@@ -108,17 +107,17 @@ Sound selection applies to the `osascript` channel. With OSC 9, the terminal con
|
|
|
108
107
|
|
|
109
108
|
## Custom sounds
|
|
110
109
|
|
|
111
|
-
In the settings
|
|
110
|
+
In the settings page, select **Edit → Import sound**. Supported inputs include AAC, AIFF, CAF, FLAC, M4A, MP3, OGG, Opus, and WAV.
|
|
112
111
|
|
|
113
112
|
The host validates the extension, decoded size, converted duration, managed-file count, and total managed size before writing anything to the user sound directory. Imports are converted to 44.1 kHz mono AIFF using macOS `afconvert`, with `ffmpeg` as a fallback for formats that `afconvert` cannot decode. Existing files are never overwritten; a numeric suffix is added instead.
|
|
114
113
|
|
|
115
|
-
New imports are recorded in `~/Library/Application Support/dsh-macos-notify/sounds.json` and can be deleted from the settings
|
|
114
|
+
New imports are recorded in `~/Library/Application Support/dsh-macos-notify/sounds.json` and can be deleted from the settings page. If a sound is currently selected, deletion asks for confirmation and changes affected events to silent. Files remain in `~/Library/Sounds` if the plugin is removed without deleting them first.
|
|
116
115
|
|
|
117
116
|
## Known limitations
|
|
118
117
|
|
|
119
118
|
- The plugin is macOS-only. Native notifications use `osascript`, and custom import uses macOS audio tooling.
|
|
120
119
|
- OSC 9 sound behavior belongs to the terminal and ignores the per-event sound selection.
|
|
121
|
-
- The Web settings
|
|
120
|
+
- The Web settings page uses the trusted `/macos-notify` RPC channel because the current DSH Web settings proxy has a namespace allowlist for built-in settings.
|
|
122
121
|
- Only sounds imported by v0.2.0 or later are tracked as managed sounds. Earlier manually copied/imported files can still be selected, but must be removed from `~/Library/Sounds` manually.
|
|
123
122
|
|
|
124
123
|
## Development
|
|
@@ -126,7 +125,7 @@ New imports are recorded in `~/Library/Application Support/dsh-macos-notify/soun
|
|
|
126
125
|
The package is intentionally build-free:
|
|
127
126
|
|
|
128
127
|
- `index.js` — host plugin, event handling, notification delivery, settings RPC, and sound import.
|
|
129
|
-
- `client.js` — hand-written DSH client module for focus reporting and the Web settings
|
|
128
|
+
- `client.js` — hand-written DSH client module for focus reporting and the first-level Web settings page.
|
|
130
129
|
- `cordis.patch.yml` — profile bundle patch.
|
|
131
130
|
|
|
132
131
|
Run the release checks:
|
package/client.js
CHANGED
|
@@ -196,7 +196,15 @@ window.__ModuleLoader__.load({
|
|
|
196
196
|
var timer = setInterval(report, 30000)
|
|
197
197
|
var call = function (endpoint, payload) { return ctx.connection.rpc.call('/macos-notify', endpoint, payload).then(function (result) { if (!result || result.ok !== true) throw new Error(result && result.error && result.error.message || 'RPC 调用失败'); return result.value }) }
|
|
198
198
|
var getCurrentCwd = function () { try { var state = ctx.sessions.list.getSnapshot(); return state.current && state.byId[state.current] && state.byId[state.current].cwd || '' } catch { return '' } }
|
|
199
|
-
ctx.slots.inject('settings.
|
|
199
|
+
ctx.slots.inject('settings.section', function () {
|
|
200
|
+
return ctx.slots.register({
|
|
201
|
+
name: 'settings.section',
|
|
202
|
+
id: 'macos-notify',
|
|
203
|
+
order: 100,
|
|
204
|
+
label: 'macOS 通知',
|
|
205
|
+
inject: function () { return { call: call, getCurrentCwd: getCurrentCwd } },
|
|
206
|
+
}, Card)
|
|
207
|
+
})
|
|
200
208
|
ctx.effect(function () { return function () { clearInterval(timer); document.removeEventListener('visibilitychange', report); window.removeEventListener('focus', report); window.removeEventListener('blur', report) } })
|
|
201
209
|
}
|
|
202
210
|
return module.exports
|
package/index.js
CHANGED
|
@@ -53,8 +53,8 @@ export const Config = Schema.object({
|
|
|
53
53
|
duplicateWindowSec: Schema.number().default(300),
|
|
54
54
|
/** 项目规则 JSON:[{ path, mode }],mode 为 mute / errors / important */
|
|
55
55
|
projectRulesJson: Schema.string().default('[]'),
|
|
56
|
-
/**
|
|
57
|
-
notifyOnLoad: Schema.boolean().default(
|
|
56
|
+
/** 兼容旧配置;成功加载现在始终静默,仅初始化失败时提醒 */
|
|
57
|
+
notifyOnLoad: Schema.boolean().default(false),
|
|
58
58
|
})
|
|
59
59
|
|
|
60
60
|
/** 设置页可编辑的提示音字段 */
|
|
@@ -295,6 +295,11 @@ function notify(title, body, sound, channel, onResult = () => {}) {
|
|
|
295
295
|
})
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
function notifyStartupFailure(err, sound = 'Basso') {
|
|
299
|
+
const detail = String(err?.message ?? err ?? '未知错误').replace(/\s+/g, ' ').trim().slice(0, 180)
|
|
300
|
+
notify('DSH', `macOS 通知插件加载失败:${detail || '未知错误'}`, sound, 'osascript')
|
|
301
|
+
}
|
|
302
|
+
|
|
298
303
|
// —— OSC 9 通道(思路参考 kimi-code 的 terminal-notification.ts)——
|
|
299
304
|
|
|
300
305
|
/** 认识 OSC 9 桌面通知的终端白名单;不认识 OSC 9 的终端收到转义序列会打印乱码,所以必须保守 */
|
|
@@ -378,7 +383,7 @@ function isCriticalKind(kind) {
|
|
|
378
383
|
return kind === '出错' || kind === '被阻止' || kind === '审批'
|
|
379
384
|
}
|
|
380
385
|
|
|
381
|
-
|
|
386
|
+
function applyImpl(ctx, config) {
|
|
382
387
|
// 配置三层叠加:schema 默认值 < cordis 组合层(base = 插件 config)< 用户层(设置页)。
|
|
383
388
|
// 设置页写入后经 watch 实时生效,不需要重启。
|
|
384
389
|
const scope = ctx.settings.register('macos-notify', Config, { base: config, applies: 'live' })
|
|
@@ -597,6 +602,7 @@ export function apply(ctx, config) {
|
|
|
597
602
|
console.log('[dsh-macos-notify] RPC intercept mounted')
|
|
598
603
|
} catch (err) {
|
|
599
604
|
console.error('[dsh-macos-notify] RPC intercept failed:', err)
|
|
605
|
+
notifyStartupFailure(err, current.sounds.error)
|
|
600
606
|
}
|
|
601
607
|
})
|
|
602
608
|
|
|
@@ -780,10 +786,6 @@ export function apply(ctx, config) {
|
|
|
780
786
|
if (!flushTimer) flushTimer = setTimeout(flush, current.coalesceMs)
|
|
781
787
|
}
|
|
782
788
|
|
|
783
|
-
if (current.notifyOnLoad) {
|
|
784
|
-
send('DSH', 'macOS 通知插件已加载', current.sounds.completed, [], { detail: '插件加载测试通知' })
|
|
785
|
-
}
|
|
786
|
-
|
|
787
789
|
ctx.on('session/event', (session, event) => {
|
|
788
790
|
if (event.type === 'session/title') {
|
|
789
791
|
titles.set(session.id, event.data.title)
|
|
@@ -856,3 +858,13 @@ export function apply(ctx, config) {
|
|
|
856
858
|
if (digestTimer) clearInterval(digestTimer)
|
|
857
859
|
})
|
|
858
860
|
}
|
|
861
|
+
|
|
862
|
+
export function apply(ctx, config) {
|
|
863
|
+
try {
|
|
864
|
+
return applyImpl(ctx, config)
|
|
865
|
+
} catch (err) {
|
|
866
|
+
console.error('[dsh-macos-notify] plugin initialization failed:', err)
|
|
867
|
+
notifyStartupFailure(err, config?.sounds?.error)
|
|
868
|
+
throw err
|
|
869
|
+
}
|
|
870
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-macos-notify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Native macOS notifications and configurable sounds for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"inject": [
|
|
41
41
|
"@deepseek-ai/dsh-client-connection",
|
|
42
42
|
"@deepseek-ai/dsh-client-runtime",
|
|
43
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
43
44
|
"@deepseek-ai/dsh-client-ui-slots"
|
|
44
45
|
]
|
|
45
46
|
}
|