@nolit/dsh-notify 0.0.0-stage → 0.0.1-rc.4
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 +445 -0
- package/LICENSE +21 -0
- package/PROVENANCE.md +96 -0
- package/README.md +331 -2
- package/cordis.patch.yml +19 -0
- package/docs/2026-10-20-dsh-notify-design.md +335 -0
- package/docs/2026-10-20-final-status.md +125 -0
- package/docs/2026-10-23-asset-policy.md +170 -0
- package/docs/2026-10-23-deployment-strategy-review.md +530 -0
- package/docs/2026-10-23-headless-nonintrusive-ui-architecture.md +579 -0
- package/docs/2026-10-23-hybrid-dual-mode-design.md +955 -0
- package/docs/2026-10-23-timezone-global-report.md +204 -0
- package/docs/2026-10-23-web-notify-plugin-spec.md +454 -0
- package/docs/2026-10-23-web-plugin-mount.md +111 -0
- package/docs/2026-10-23-windows-widget-poc-report.md +312 -0
- package/docs/2026-10-24-linux-desktop-verification.md +134 -0
- package/docs/BOOT-CARD.md +176 -0
- package/docs/RECOVERY-NOTES.md +111 -0
- package/docs/WORK-PROTOCOL.md +155 -0
- package/docs/deepseek-peak-spec.md +370 -0
- package/docs/dsh-harness-notify-spec.md +149 -0
- package/icon.svg +6 -0
- package/lib/client.js +2175 -0
- package/lib/client.src.js +1966 -0
- package/lib/index.js +13 -0
- package/lib/locale-table.js +215 -0
- package/locale/en.json +104 -0
- package/locale/ko.json +104 -0
- package/market/icons/dsh-notify.svg +6 -0
- package/market/index.json +77 -0
- package/package.json +80 -4
- package/scripts/build-client.mjs +41 -0
- package/scripts/gen-locale.mjs +36 -0
- package/test/client.test.mjs +601 -0
- package/test/locale.test.mjs +114 -0
- package/test/manifest.test.mjs +115 -0
- package/test/peak.test.mjs +370 -0
- package/test/typography.test.mjs +85 -0
package/README.md
CHANGED
|
@@ -1,3 +1,332 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Notify for Chrome
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- skeleton:
|
|
4
|
+
version: 2.0
|
|
5
|
+
kind: readme
|
|
6
|
+
status: active
|
|
7
|
+
updated: 2026-11-05
|
|
8
|
+
summary: Operator manual and behavior contract for Notify for Chrome (Korean: 알림 for 크롬) — Chrome/Web Notification only, silent in-app toast fallback, native DSH settings rows and typography, Windows/install-mode notification branches.
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
> Status: active · Updated: 2026-11-07 · Package: `@nolit/dsh-notify` v`0.0.1-rc.4` · Korean display name: **알림 for 크롬** · Parent: `README.md` in the `dsh-plugins` workspace
|
|
12
|
+
|
|
13
|
+
**Notify for Chrome** turns DeepSeek Harness events into **Chrome notifications** (the Web
|
|
14
|
+
Notification API, `new Notification(...)`). It has no native app, no ports, no IPC, no file queue
|
|
15
|
+
and no system notifier. When Chrome cannot show a notification, the plugin falls back to a
|
|
16
|
+
**silent in-app toast**.
|
|
17
|
+
|
|
18
|
+
## 0. Version numbering — why `0.0.1-rc.4` is not lower than `0.2.1`
|
|
19
|
+
|
|
20
|
+
The version number went **down** against this project's own history, on purpose. Two separate
|
|
21
|
+
facts explain it, and until 2026-11-06 neither was written down anywhere.
|
|
22
|
+
|
|
23
|
+
**`0.2.x` was never this plugin's version.** The `v0.2.0` and `v0.2.1` releases belonged to the
|
|
24
|
+
**Windows PowerShell/WPF prototype** (a tray widget polling the DeepSeek billing window). The
|
|
25
|
+
browser plugin lived inside that repository under `plugin/` and happened to carry the same
|
|
26
|
+
number — by accident, not by design.
|
|
27
|
+
|
|
28
|
+
**The `@nolit` ladder was reset by owner decision on 2026-11-05.** Every `@nolit` package moved
|
|
29
|
+
to one scheme, `0.0.1-rc.N`, in which only the `rc#` moves. `0.1.8` and `0.2.1` are not
|
|
30
|
+
milestones under that scheme; the scheme replaced them.
|
|
31
|
+
|
|
32
|
+
| Surface | Before | After |
|
|
33
|
+
| :--- | :--- | :--- |
|
|
34
|
+
| Version scheme | per-track, drifting (`0.1.6 → 0.1.7 → 0.1.8 → 0.2.1`) | **`0.0.1-rc.N`** |
|
|
35
|
+
| Package | `@nolit/dsh-notify-web` @ `0.2.1`, nested in `plugin/` | **`@nolit/dsh-notify`** @ `0.0.1-rc.4`, repository root |
|
|
36
|
+
| Repository | Windows prototype at root | plugin at root, prototype preserved in `prototype-windows/` |
|
|
37
|
+
|
|
38
|
+
The `-web` suffix came from the 2026-10-24 recovery and was never the owner's choice;
|
|
39
|
+
`PROVENANCE.md` documented the package as `@nolit/dsh-notify` the entire time while the files
|
|
40
|
+
said `-web`. The rename landed in `0.0.1-rc.3`; `0.0.1-rc.4` is the corrected build.
|
|
41
|
+
|
|
42
|
+
Version numbers are the owner's decision. An agent must not choose, bump or "stabilise" one.
|
|
43
|
+
|
|
44
|
+
## 1. Behavior
|
|
45
|
+
|
|
46
|
+
| DSH event | Channel |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `api-session/status` (`running=false`) | Chrome notification "Turn complete", root sessions only, 5 s cooldown |
|
|
49
|
+
| `api-session/error` | Chrome notification "Turn failed", message truncated to 160 chars |
|
|
50
|
+
| `approval/request` | Chrome notification "Approval needed"; `next()` passes through immediately |
|
|
51
|
+
| `user-questions/request` | Chrome notification "Question waiting"; `next()` passes through immediately |
|
|
52
|
+
|
|
53
|
+
- **Chrome first.** The plugin calls the Notification API. A granted permission and a secure
|
|
54
|
+
context are the only prerequisites.
|
|
55
|
+
- **Silent toast fallback.** If the permission is denied/pending, the origin is not a secure
|
|
56
|
+
context, the Notification API is unavailable, or the constructor/`onerror` fails, the event is
|
|
57
|
+
shown as the **native DSH toast** and nothing else. There is no sound, no second notification
|
|
58
|
+
channel, and no title-bar marker.
|
|
59
|
+
- **One tab delivers.** Multiple tabs elect a leader (Web Locks, localStorage lease fallback) so an
|
|
60
|
+
event is not announced once per tab. A focused tab always delivers.
|
|
61
|
+
- **No sound engine.** The plugin never synthesizes audio, never ships or stores audio, and never
|
|
62
|
+
uses `<audio>`/Web Audio/IndexedDB. When the OS notification has a sound, it is the **operating
|
|
63
|
+
system's own** notification sound.
|
|
64
|
+
|
|
65
|
+
## 2. Windows and install-environment behavior
|
|
66
|
+
|
|
67
|
+
**Which OS does the environment card report?** The **browser's** OS — the machine running the tab
|
|
68
|
+
that shows the notification — not the OS running the `dsh` host process. The two are independent:
|
|
69
|
+
a Windows Chrome can be pointed at a DSH server on Linux (the default remote setup), and the
|
|
70
|
+
notification rules that matter (Action Center persistence, `requireInteraction` support, the
|
|
71
|
+
installed-app branch) are properties of the browser's OS.
|
|
72
|
+
|
|
73
|
+
The sensitivity is per-platform, measured:
|
|
74
|
+
|
|
75
|
+
| Browser OS | Installed app | Behaviour |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| Windows | yes | `requireInteraction: true` for every kind; the app window and Action Center keep them |
|
|
78
|
+
| Windows | no | `requireInteraction` follows the setting, approval/question only |
|
|
79
|
+
| Linux | either | same as the Windows browser tab |
|
|
80
|
+
| macOS | either | `requireInteraction` is not honoured by Chrome, so it stays `false` |
|
|
81
|
+
| Android / other | either | `silent: false`, unique `tag`; no persistence |
|
|
82
|
+
|
|
83
|
+
Because a value like "Windows" next to a Linux host looks wrong, the row is labelled
|
|
84
|
+
**Browser OS** (브라우저 OS) and carries that explanation inline.
|
|
85
|
+
|
|
86
|
+
The Chrome notification parameters branch on the **runtime platform** and the **install mode**.
|
|
87
|
+
Platform detection order: DSH's `document.documentElement.dataset.platform` (the native shell sets
|
|
88
|
+
it; native code also tests it for `darwin`), then `navigator.userAgentData.platform`, then
|
|
89
|
+
`navigator.platform`, then `navigator.userAgent`. Install mode is `installed` when the page runs in
|
|
90
|
+
a standalone/minimal-ui/fullscreen display mode (or `navigator.standalone`), otherwise `browser`.
|
|
91
|
+
|
|
92
|
+
| Environment | `requireInteraction` | `silent` | `tag` |
|
|
93
|
+
|---|---|---|---|
|
|
94
|
+
| **Windows, installed app** | `true` for every kind — the Action Center keeps the alert while the app window is minimized, so a completion cannot be auto-dismissed | `false` (the OS plays the sound) | unique per event |
|
|
95
|
+
| **Windows, browser tab** | follows the "Keep approval alerts open" setting; approval/question only | `false` | unique per event |
|
|
96
|
+
| **macOS** | `false` — Chrome does not honour `requireInteraction`, so claiming it would misrepresent the behavior | `false` | unique per event |
|
|
97
|
+
| **Linux / other** | follows the setting; approval/question only | `false` | unique per event |
|
|
98
|
+
|
|
99
|
+
- **Why a unique tag on Windows:** Windows replaces an existing notification that reuses a `tag`,
|
|
100
|
+
which silently drops repeated events. Every event gets a fresh tag so completions accumulate in
|
|
101
|
+
the Action Center instead of being replaced.
|
|
102
|
+
- **Permission guidance is platform-specific:** a Windows profile points at Chrome's site settings
|
|
103
|
+
and **Windows Settings → System → Notifications**; other platforms point at the browser's site
|
|
104
|
+
settings. The guidance is shown next to the status row and is the only place a blocked
|
|
105
|
+
permission is explained.
|
|
106
|
+
- Nothing else is Windows-specific: event filtering, cooldowns, tab leadership, locale and the
|
|
107
|
+
toast fallback are generic.
|
|
108
|
+
|
|
109
|
+
## 3. Install
|
|
110
|
+
|
|
111
|
+
The package name stays `@nolit/dsh-notify`; only the **display identity** changed to
|
|
112
|
+
"Notify for Chrome" / "알림 for 크롬". Renaming the npm package would break the live profile's
|
|
113
|
+
`link:` dependency.
|
|
114
|
+
|
|
115
|
+
Local checkout (the live profile already links it):
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
dsh plugin --profile web add "link:/path/to/dsh-plugins/dsh-notify"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
From npm after publishing:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
dsh plugin --profile web add @nolit/dsh-notify
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The package must be listed in the profile's `dsh.profile.bundles`. Reload the DSH page after
|
|
128
|
+
installing. If `lib/client.js` has a syntax error only this plugin is disabled; the DSH core keeps
|
|
129
|
+
working.
|
|
130
|
+
|
|
131
|
+
## 4. Settings
|
|
132
|
+
|
|
133
|
+
**Settings → Notify for Chrome** (English; the label is **알림 for 크롬** when the host locale is
|
|
134
|
+
Korean) renders native DSH settings surfaces only:
|
|
135
|
+
|
|
136
|
+
- a native `Tag` for the Chrome-notification status, native `Button` actions, native `Switch`
|
|
137
|
+
toggles and a native `Input` for the cooldown;
|
|
138
|
+
- the section navigation icon is a **DSH icon** (`IconAlarmClockOutlineRegular`), registered through
|
|
139
|
+
`settings.section.icon`; the plugin ships no icon set of its own;
|
|
140
|
+
- typography comes from the live DSH tokens `--dsh-content-font-size` /
|
|
141
|
+
`--dsh-content-font-size-secondary` and their `--dsh-content-font-delta*` line-height deltas;
|
|
142
|
+
colours and surfaces come from `--dsw-*` tokens. The plugin **injects no stylesheet**, sets **no
|
|
143
|
+
font-family** and hardcodes **no pixel font size**.
|
|
144
|
+
|
|
145
|
+
The page is grouped into four cards. The two owner-requested categories (2026-11-06) are the
|
|
146
|
+
**DeepSeek peak timer** and **notifications**, in that order.
|
|
147
|
+
|
|
148
|
+
**알림 조건 (notification rows)**
|
|
149
|
+
|
|
150
|
+
| Row | Default | Meaning |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| Turn complete / Approval needed / Question waiting / Turn error | on | which events notify |
|
|
153
|
+
| Include subagents | off | also notify for subagent complete/error |
|
|
154
|
+
| Hide completion alerts while focused | off | suppress completion while the DSH tab is focused |
|
|
155
|
+
| Keep approval alerts open | on | `requireInteraction` for approval/question where supported (Windows/Linux) |
|
|
156
|
+
| Completion cooldown | 5 s | per-session grouping window |
|
|
157
|
+
|
|
158
|
+
**딥시크 피크 타이머 (peak timer rows)**
|
|
159
|
+
|
|
160
|
+
| Row | Default | Meaning |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| Show peak countdown chip | on | 7-segment `HH:MM:SS` chip in the Session header: green off-peak, red at peak |
|
|
163
|
+
| Announce peak changes | on | Chrome notification + `setAppBadge` when the billing window flips |
|
|
164
|
+
| Show timer on other providers | **off** | also render the chip when the active route is *not* an official DeepSeek route |
|
|
165
|
+
|
|
166
|
+
### The peak timer only trusts official DeepSeek routes by default
|
|
167
|
+
|
|
168
|
+
The peak/off-peak clock is a property of **DeepSeek's own API billing**
|
|
169
|
+
([pricing footnote](https://api-docs.deepseek.com/quick_start/pricing)). DeepSeek publishes the
|
|
170
|
+
off-peak discount for its own API; **a different service serving the same model may bill
|
|
171
|
+
differently**, so the timer is a *reference*, not a fact, on any other route.
|
|
172
|
+
|
|
173
|
+
The plugin therefore gates on the **provider id**, never on a model name:
|
|
174
|
+
|
|
175
|
+
| Route | Chip by default |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `deepseek-official` (official API-key route) | shown |
|
|
178
|
+
| `deepseek-account` (official account route) | shown |
|
|
179
|
+
| everything else (OpenCode, DeepInfra, Antigravity, any proxy/gateway) | **hidden** |
|
|
180
|
+
|
|
181
|
+
Those two ids are the ones the official DSH packages register. **Provider ids differ between
|
|
182
|
+
installations** — if your setup exposes the official DeepSeek route under a different id, turn on
|
|
183
|
+
**Show timer on other providers** and the chip appears on every route. The default stays
|
|
184
|
+
conservative because a wrong "50% off" claim is worse than a hidden widget.
|
|
185
|
+
|
|
186
|
+
The live selection is read from `[data-provider-id][data-model-id]` on the model selector trigger,
|
|
187
|
+
which is the same path DeepInfra's cost chip uses. Nothing is guessed from the model name.
|
|
188
|
+
|
|
189
|
+
The settings card carries the caveat inline, in the owner's wording (2026-11-06):
|
|
190
|
+
|
|
191
|
+
> 딥시크는 공식 모델 API에 대해서만 할인을 명시합니다. 같은 모델이라도 다른 제공자는 서비스 요금이
|
|
192
|
+
> 다를 수 있으며 보장하지 않습니다. 그 경우 이 타이머는 참고 사항일 뿐입니다.
|
|
193
|
+
>
|
|
194
|
+
> *DeepSeek states this discount only for its official model API. A different provider may charge
|
|
195
|
+
> differently for the same model, and that is not guaranteed. In that case this timer is a reference
|
|
196
|
+
> only.*
|
|
197
|
+
|
|
198
|
+
Preferences persist in the browser's `localStorage` under `dsh-notify-web:settings` (version 2).
|
|
199
|
+
They are browser preferences, not Host configuration: the plugin's Host half is intentionally a
|
|
200
|
+
no-op and exposes no settings namespace. No audio file is read, stored or referenced.
|
|
201
|
+
|
|
202
|
+
Guidance rules:
|
|
203
|
+
|
|
204
|
+
- **Permission pending** → the Enable button is shown.
|
|
205
|
+
- **Denied / insecure / unsupported** → the Enable button is **hidden** (a capability that is gone
|
|
206
|
+
is not shown as a broken control); the row explains what to change, and the test action still
|
|
207
|
+
exercises the toast fallback.
|
|
208
|
+
|
|
209
|
+
## 5. Localization
|
|
210
|
+
|
|
211
|
+
English is the default. Korean is used **only** while the host locale (`ctx.locale.active`) is
|
|
212
|
+
Korean; a locale change switches the next notification and the settings strings live.
|
|
213
|
+
|
|
214
|
+
- Source of truth: [`locale/en.json`](locale/en.json) and [`locale/ko.json`](locale/ko.json).
|
|
215
|
+
- `scripts/gen-locale.mjs` bakes them into `lib/locale-table.js`; `scripts/build-client.mjs` inlines
|
|
216
|
+
that table into `lib/client.js` (the browser loader cannot import JSON).
|
|
217
|
+
- No hardcoded Korean exists outside the baked dictionary (a test enforces this).
|
|
218
|
+
- Display identity: English **Notify for Chrome**, Korean **알림 for 크롬**.
|
|
219
|
+
|
|
220
|
+
## 6. Limitations
|
|
221
|
+
|
|
222
|
+
### Browser support — Chrome / Chromium required
|
|
223
|
+
|
|
224
|
+
The plugin is built for **Chrome and Chromium-based browsers** (Edge, Brave, Opera, Vivaldi, Arc).
|
|
225
|
+
Those are the engines where the whole surface below exists at once. **On any other browser, correct
|
|
226
|
+
operation is not guaranteed and is not tested.**
|
|
227
|
+
|
|
228
|
+
| Capability | Chrome / Chromium | Firefox | Safari |
|
|
229
|
+
|---|---|---|---|
|
|
230
|
+
| `new Notification()` | yes | yes | 16+ only |
|
|
231
|
+
| `badge` / `setAppBadge` | 81+ | no (falls back silently) | no |
|
|
232
|
+
| `navigator.locks` (tab leader) | 69+ | yes | no (localStorage lease fallback) |
|
|
233
|
+
| `requireInteraction` | Windows/Linux | **ignored** | **ignored** |
|
|
234
|
+
| Installed-app notification branch | yes | n/a | n/a |
|
|
235
|
+
|
|
236
|
+
**The plugin does not detect the browser.** It feature-detects (`Notification`, `isSecureContext`,
|
|
237
|
+
`navigator.locks`, `setAppBadge`) and degrades, but it never claims a browser is supported just
|
|
238
|
+
because it is not Chrome. A non-Chromium browser may look functional while behaving differently —
|
|
239
|
+
for example Firefox accepts `requireInteraction` and ignores it, so an approval alert auto-dismisses
|
|
240
|
+
even though the setting is on.
|
|
241
|
+
|
|
242
|
+
Recommended minimum: **Chrome 81+** (when `setAppBadge` landed; everything else the plugin uses is
|
|
243
|
+
older). Older Chrome still works, minus the badge channel.
|
|
244
|
+
|
|
245
|
+
### Security constraints that can stop a notification appearing
|
|
246
|
+
|
|
247
|
+
These are browser/OS security rules, not plugin bugs. Each one degrades to the **silent in-app
|
|
248
|
+
toast** rather than failing loudly, which is why the toast fallback exists.
|
|
249
|
+
|
|
250
|
+
| Constraint | What the user sees | Measured behaviour |
|
|
251
|
+
|---|---|---|
|
|
252
|
+
| **Permission not granted** (`default`) | nothing from the OS | `new Notification(...)` **does not throw** — it looks successful and shows nothing. The plugin checks `Notification.permission === 'granted'` *before* constructing, so it routes to the toast instead. |
|
|
253
|
+
| **Permission blocked** (`denied`) | nothing, and no prompt returns | `requestPermission()` resolves `'denied'` immediately; Chrome will not prompt again for the origin. Only the user can undo it in site settings. The plugin hides the Enable button, because a control that cannot work is not shown as a broken one. |
|
|
254
|
+
| **Insecure origin** | nothing | `http://<LAN-IP>:3080` is not a secure context; Chrome refuses OS notifications. Use `https://` or `localhost`. Reported as `insecure`. A self-signed certificate needs to be trusted once in the browser; do **not** browse with certificate errors bypassed — notifications and the peak timer need a genuinely secure context. |
|
|
255
|
+
| **No user gesture** | prompt never appears | `requestPermission()` needs a click. A call on page load is auto-denied; the plugin drives it from the Enable button only. |
|
|
256
|
+
| **OS Do Not Disturb** / Focus Assist | nothing, or a silent banner | The OS owns this; the page cannot override it and cannot detect it. |
|
|
257
|
+
| **Browser-level site mute** | nothing | Silent skip at the Chrome layer; indistinguishable from a delivered notification. |
|
|
258
|
+
| **Tab closed** | nothing | No service-worker backend, so no delivery once the DSH tab is gone. |
|
|
259
|
+
|
|
260
|
+
- Notifications work **only while the DSH tab is open**. There is no service-worker push backend.
|
|
261
|
+
- Background-tab throttling, browser notification policy and OS Focus Assist / Do Not Disturb can
|
|
262
|
+
change what is shown.
|
|
263
|
+
- Approval/question notifications do not replace the DSH approval UI; the event handler passes
|
|
264
|
+
`next()` through immediately.
|
|
265
|
+
|
|
266
|
+
## 7. Privacy
|
|
267
|
+
|
|
268
|
+
- No `XMLHttpRequest`, `WebSocket`, `EventSource` or local port; no filesystem access.
|
|
269
|
+
- **One network request**: the peak timer fetches the Chinese public-holiday list from
|
|
270
|
+
`raw.githubusercontent.com/NateScarlet/holiday-cn`. Nothing is sent but the request itself — no
|
|
271
|
+
prompt, code, session title, token or identifier. The response is cached in `localStorage` for 10
|
|
272
|
+
days. Disable **Show peak countdown chip** and the request never happens.
|
|
273
|
+
- The only storage is the settings object, the tab-leader lease key and that holiday cache, all in
|
|
274
|
+
`localStorage`.
|
|
275
|
+
- Notification bodies are fixed copy plus the session title (80 chars max); prompts, code and tool
|
|
276
|
+
arguments are never included.
|
|
277
|
+
- Notification clicks only focus the DSH tab; no external link is opened.
|
|
278
|
+
|
|
279
|
+
## 8. Development
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
cd dsh-notify
|
|
283
|
+
npm test # pretest runs gen-locale + build-client, then node --test
|
|
284
|
+
npm run build # regenerate lib/locale-table.js and lib/client.js
|
|
285
|
+
node --check lib/client.js
|
|
286
|
+
node --check lib/index.js
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Tests use mocked browser APIs (Notification, localStorage, Web Locks) and assert event filtering,
|
|
290
|
+
cooldowns, approval/question pass-through, the Chrome-vs-toast channel decision, Windows/macOS/Linux
|
|
291
|
+
parameter branches, locale switching, settings persistence, native-primitive rendering, the
|
|
292
|
+
typography token contract, and the absence of every removed legacy path.
|
|
293
|
+
|
|
294
|
+
## 9. Structure
|
|
295
|
+
|
|
296
|
+
- `lib/client.src.js` — editable browser-half source (baked by `scripts/build-client.mjs`).
|
|
297
|
+
- `lib/client.js` — shipped browser entry (generated; do not edit by hand).
|
|
298
|
+
- `lib/locale-table.js` — generated locale dictionary (from `locale/*.json`).
|
|
299
|
+
- `lib/index.js` — no-op Host half; registers the package only. No services, no I/O.
|
|
300
|
+
- `cordis.patch.yml` — bundle row and default settings.
|
|
301
|
+
- `market/index.json` — market/index entry (renamed titles, version, no audio keyword).
|
|
302
|
+
|
|
303
|
+
## 10. License and assets
|
|
304
|
+
|
|
305
|
+
- Code: MIT. See [LICENSE](LICENSE).
|
|
306
|
+
- The package bundles **no fonts, logos or audio**. The manifest icon is the neutral clock SVG at
|
|
307
|
+
[`icon.svg`](icon.svg)/[`market/icons/dsh-notify.svg`](market/icons/dsh-notify.svg).
|
|
308
|
+
- The historical `docs/` and `prototype-windows/` trees are kept as history; neither is shipped in
|
|
309
|
+
the package (`package.json` `files`) nor referenced by the notification code path.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
## 한국어 요약
|
|
315
|
+
|
|
316
|
+
**버전이 내려간 이유부터**: `0.0.1-rc.4`는 `0.2.1`보다 낮은 것이 아닙니다. `0.2.x`는 이
|
|
317
|
+
플러그인의 버전이 아니라 같은 저장소에 있던 **Windows 프로토타입**의 버전이었고, 2026-11-05
|
|
318
|
+
소유자 결정으로 모든 `@nolit` 패키지가 **`0.0.1-rc.N`** 단일 사다리로 재설정됐습니다.
|
|
319
|
+
`rc#`만 올라갑니다. 패키지명도 `@nolit/dsh-notify-web` → **`@nolit/dsh-notify`** 로
|
|
320
|
+
바뀌었습니다. `-web`은 2026-10-24 복구 당시 붙은 것으로 소유자가 고른 이름이 아니었습니다.
|
|
321
|
+
|
|
322
|
+
**알림 for 크롬**은 DeepSeek Harness의 턴 완료·도구 승인·질문·오류를 **크롬 알림**(Web
|
|
323
|
+
Notification API)으로 알립니다. 크롬이 알림을 막거나 표시할 수 없으면 **소리 없이 DSH 인앱
|
|
324
|
+
토스트**로 대신 알립니다. 자체 오디오 엔진·BYO 오디오·자체 CSS·네이티브 앱/포트/파일 경로는
|
|
325
|
+
모두 제거되었습니다.
|
|
326
|
+
|
|
327
|
+
- 설정은 **설정 → 알림 for 크롬**에서 하며, DSH 네이티브 컴포넌트(Switch/Button/Tag/Input/
|
|
328
|
+
Toast)와 DSH 디자인·타이포그래피 토큰만 사용합니다.
|
|
329
|
+
- 영어가 기본이고, 호스트 로케일이 한국어일 때만 한국어로 표시됩니다.
|
|
330
|
+
- Windows에서는 플랫폼과 설치 환경(설치된 앱/브라우저 탭)에 따라 알림 파라미터가 달라집니다:
|
|
331
|
+
설치된 앱은 모든 알림을 닫을 때까지 유지하고, 브라우저 탭은 승인·질문만 유지합니다.
|
|
332
|
+
macOS에서는 `requireInteraction`을 사용하지 않습니다.
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Notify for Chrome bundle layer.
|
|
2
|
+
# The package is the bundle; this row activates its no-op Host half. Every
|
|
3
|
+
# notification runs through the browser's Chrome / Web Notification API. No
|
|
4
|
+
# local IPC, HTTP, ports, filesystem access, native notifier or audio engine.
|
|
5
|
+
- insert:
|
|
6
|
+
- id: notify
|
|
7
|
+
name: '@nolit/dsh-notify'
|
|
8
|
+
config:
|
|
9
|
+
notifyOnComplete: true
|
|
10
|
+
notifyOnApproval: true
|
|
11
|
+
notifyOnQuestion: true
|
|
12
|
+
notifyOnError: true
|
|
13
|
+
completeCooldownMs: 5000
|
|
14
|
+
suppressWhenFocused: false
|
|
15
|
+
requireInteractionForApproval: true
|
|
16
|
+
notifyOnSubagents: false
|
|
17
|
+
showPeakChip: true
|
|
18
|
+
notifyOnPeakChange: true
|
|
19
|
+
peakOnAnyProvider: false
|