dsh-workspace-status 0.0.0-stage → 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/CHANGELOG.md ADDED
@@ -0,0 +1,72 @@
1
+ # Changelog
2
+
3
+ All notable changes to this package are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.0] - 2026-10-26
10
+
11
+ ### Added
12
+
13
+ - Pinned-only notifications. The pinned section watches the live status of
14
+ pinned conversations and notifies on transitions: a pinned conversation
15
+ starts waiting for you (approval, plan review or question) or finishes
16
+ unread. Running → idle with an unread completion fires once; repeated
17
+ renders, kind changes and late unread states are deduplicated, and the
18
+ first observation after a reload stays silent.
19
+ - Desktop/OS notifications when the window is in the background, plus in-app
20
+ notices inside the pinned section so a focused window still surfaces the
21
+ event. Clicking a row-shaped notice opens that pinned conversation; notices
22
+ auto-dismiss after eight seconds or via the close button.
23
+ - A bell toggle in the pinned section header turns pinned notifications on or
24
+ off and requests notification permission on first use; a speaker toggle
25
+ enables an optional two-note chime. Both preferences persist in browser
26
+ storage. The bell falls back to in-app notices when the OS blocks
27
+ notifications, and enabling notifications shows a one-off test notice.
28
+ - Notifications are only emitted for transitions while the app is running;
29
+ they are not external push and do not notify sessions outside the pin set.
30
+
31
+ ## [0.2.0] - 2026-10-26
32
+
33
+ ### Added
34
+
35
+ - Pinned conversations section above the Workspaces list. Pinned conversations
36
+ are lifted out of the regular workspace groups and rendered per workspace
37
+ with the shipped folder-header treatment, their live status dot, relative
38
+ time, current-session highlight, group counts and a filled pin icon on every
39
+ row. Clicking the pin unpins immediately.
40
+ - Section and group collapse state persisted in browser storage; the section
41
+ caps its height and scrolls independently.
42
+ - The section is driven by the registry-global `pinnedSessionIds` Workspace
43
+ feed, so pins survive restarts and stay in sync with the official browser;
44
+ unpin uses `ctx.workspaces.unpinSession`, opening a row uses
45
+ `ctx.uiWorkspace.openSession`.
46
+ - Pinned rows are hidden from the official grouped/flat tree with generated
47
+ `display:none` rules; search-result rows are untouched.
48
+
49
+ ### Changed
50
+
51
+ - Component now renders a React portal into a container inserted before the
52
+ sidebar browsing region, in addition to the emitted row stylesheet. The
53
+ official Workspace browser is still not replaced.
54
+ - The workspace-mark mount now always publishes the stylesheet and portal
55
+ anchor, so pins added while mounted appear without a reload.
56
+
57
+ ## [0.1.0] - 2026-10-25
58
+
59
+ ### Added
60
+
61
+ - Workspace rows in the sidebar show a status mark aggregated from their
62
+ sessions: amber dot while a session waits for the user (approval, plan
63
+ review, answer), blue spinning ring while a session or subagent runs, green
64
+ dot for a recently finished unread session (one-hour notice window).
65
+ - One mark per workspace with the shipped session-row precedence: waiting
66
+ outranks running, which outranks the finished reminder.
67
+ - Hidden screen-reader description with per-state counts and workspace names.
68
+ - Archived sessions ignored; ungrouped sessions mark the Ungrouped bucket.
69
+ - Zero-fork implementation: an additive `sidebar.footer.action` entry that
70
+ publishes row CSS keyed on `data-row-key="workspace:<id>"`, with no DOM
71
+ writes, observers or host services.
72
+ - Declares `dsh.catalog` so plugin markets place it under UI with a real summary.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-workspace-status contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,305 @@
1
- # Temporary Holding Version
1
+ # dsh-workspace-status
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm](https://img.shields.io/npm/v/dsh-workspace-status?label=npm&color=blue)](https://www.npmjs.com/package/dsh-workspace-status)
4
+ [![npm provenance](https://img.shields.io/badge/npm%20provenance-SLSA%20v1-brightgreen)](https://www.npmjs.com/package/dsh-workspace-status)
5
+ [![test](https://github.com/Stijnus/dsh-workspace-status/actions/workflows/test.yml/badge.svg)](https://github.com/Stijnus/dsh-workspace-status/actions/workflows/test.yml)
6
+ [![license](https://img.shields.io/npm/l/dsh-workspace-status)](LICENSE)
7
+
8
+ [English](./README.md) · [中文](./README.zh-CN.md)
9
+
10
+ Sidebar upgrades for DeepSeek Harness:
11
+
12
+ 1. **Workspace status marks** — colored status on the workspace (folder) row:
13
+ waiting for you, running, and just finished, aggregated from the sessions
14
+ inside it.
15
+ 2. **Pinned conversations section** — conversations pinned through the shipped
16
+ pin action leave the regular workspace groups and appear in a dedicated
17
+ section above the browsing region, grouped per workspace with the same
18
+ header treatment and a pin icon on every row.
19
+ 3. **Pinned notifications** — when a pinned conversation starts waiting for
20
+ you or finishes unread, the plugin can raise a desktop notification (when the
21
+ window is in the background) and always shows an in-app notice in the pinned
22
+ section. Bell and chime toggles sit in the section header.
23
+
24
+ Harness draws a status dot on every conversation row, but nothing on the
25
+ workspace row above it. Collapse a group, or scroll it out of view, and the
26
+ folder cannot tell you that an agent inside is stuck waiting for an approval or
27
+ still working. This plugin gives the folder row the same kind of mark.
28
+
29
+ | Mark | Meaning | Color |
30
+ |---|---|---|
31
+ | solid dot | at least one session is waiting for you — approval, plan review, or an answer | amber (`--dsw-alias-state-warn-primary`) |
32
+ | stroked ring, spinning | at least one session is running, including a running subagent | blue (`--dsw-static-deepseek-450`) |
33
+ | solid dot | at least one session finished recently and has not been opened since | green (`--dsw-alias-state-success-primary`) |
34
+
35
+ The mark sits in the empty right-hand end of the workspace row — the same place
36
+ a session row puts its timestamp — and does not displace the title. It appears
37
+ for expanded and collapsed groups alike, and its state is described to
38
+ screen-reader users in a hidden sentence ("Workspace activity: 2 running, 1
39
+ waiting for you — api, web").
40
+
41
+ ## Pinned conversations
42
+
43
+ Pinning is the shipped Harness action (row hover button or the row **…** menu).
44
+ Once a conversation is pinned:
45
+
46
+ - its row is lifted out of the regular workspace groups and listed in a
47
+ **Pinned** section between the global panel rows and the **Workspaces**
48
+ header;
49
+ - the section is grouped per workspace, each group using the same 34px folder
50
+ row, blue active-folder color, disclosure triangle and radius as the shipped
51
+ browser, with a small count at the end;
52
+ - every pinned row shows its live status dot, relative time, current-session
53
+ highlight, and a filled **pin icon** at its trailing edge; clicking the pin
54
+ unpins the conversation immediately — no restart, and it reappears in its
55
+ workspace group;
56
+ - the Pinned header and each workspace group are collapsible, and that state is
57
+ remembered in browser storage;
58
+ - the section caps its height and scrolls on its own, so a large pin set cannot
59
+ push the browsing region away;
60
+ - the pin set is the registry-global `pinnedSessionIds` feed, persisted by the
61
+ Host in the profile workspace registry — after relaunch the same pins come
62
+ back and the section renders again;
63
+ - search is untouched: pinned conversations still appear in search results,
64
+ while the regular grouped/flat tree hides the lifted rows.
65
+
66
+ The pinned rows are hidden from the regular tree with generated
67
+ `display:none` rules. The workspace header itself stays (so its *New session*
68
+ action remains reachable), which means a workspace whose sessions are all
69
+ pinned may read as an empty group under **Workspaces** while its sessions sit in
70
+ the Pinned section.
71
+
72
+ ## Pinned notifications
73
+
74
+ The bell in the Pinned header (next to the count) controls notifications; the
75
+ speaker enables an optional two-note chime. Both preferences persist in browser
76
+ storage and default to **notifications on, sound off**.
77
+
78
+ What fires an event:
79
+
80
+ - a pinned conversation **starts waiting for you** — approval, plan review or a
81
+ question (the notification names the reason and workspace);
82
+ - a pinned conversation **finishes unread** — a running session stops and its
83
+ completion mark is still unread.
84
+
85
+ Only transitions fire, only for pinned conversations. The first observation of
86
+ a session after mount is silent, so reloading the app does not replay old
87
+ events; repeated renders of the same waiting state are quiet, while a change of
88
+ reason (approval → question) is a new event. Finished fires once per run.
89
+
90
+ Delivery:
91
+
92
+ - when the window is in the background and the platform has granted
93
+ notification permission, a **desktop/OS notification** is raised — clicking it
94
+ focuses the app and opens that conversation;
95
+ - an **in-app notice** is always added inside the pinned section (also when the
96
+ OS blocks notifications), with a status icon, title and reason; click it to
97
+ open the conversation or dismiss it with **×**. Notices auto-dismiss after
98
+ eight seconds.
99
+
100
+ The first click on the bell requests notification permission and shows a
101
+ one-off test notice. If the OS denies or blocks notifications, the plugin falls
102
+ back to the in-app notices and the bell tooltip says so. Notifications are
103
+ client-side only: they fire while the app is running and are not external push
104
+ (no email, IM or web push), and sessions outside the pin set never trigger
105
+ them.
106
+
107
+ ## Quick start
108
+
109
+ ```sh
110
+ dsh plugin --profile web add dsh-workspace-status
111
+ ```
112
+
113
+ Restart the Harness (or refresh the Web UI). Workspace rows gain a colored status
114
+ mark; pin a conversation to see the Pinned section and its bell/speaker
115
+ controls.
116
+
117
+ <sub>More from this suite: [Moodboard](https://github.com/Stijnus/dsh-moodboard) · [Composer Predictions](https://github.com/Stijnus/dsh-composer-predictions) · [Move to Workspace](https://github.com/Stijnus/dsh-move-to-workspace) · [Workspace Status](https://github.com/Stijnus/dsh-workspace-status) · [Prompt Rewrite](https://github.com/Stijnus/dsh-prompt-optimizer)</sub>
118
+
119
+ <sub>⭐ If this saves you a step, a star helps the next DSH user find it.</sub>
120
+
121
+ ## Preview
122
+
123
+ ![Four sidebar rows: api waiting (amber dot), web running (blue ring), docs recently finished (green dot), sandbox idle (no mark)](docs/preview-mock.png)
124
+
125
+ This is the plugin's own stylesheet rendered over a local reproduction of the
126
+ sidebar row DOM and theme tokens — a design preview, not a live screenshot. The
127
+ shipped app draws the same marks on the real rows.
128
+
129
+ ## Rules for workspace marks
130
+
131
+ - **Precedence matches the shipped session row:** waiting for the user beats
132
+ running, which beats the finished reminder. A workspace therefore shows one
133
+ mark at a time; the hidden description still reports every count.
134
+ - **Subagents count as their parent's activity.** A running subagent keeps the
135
+ parent session's workspace marked even when the parent turn has settled.
136
+ Subagent rows never produce a mark of their own — they are not workspace
137
+ members.
138
+ - **Archived sessions are ignored**, the same way the default browser view
139
+ hides them.
140
+ - **The finished mark is a notice, not a flag.** It lapses one hour after the
141
+ session's last update, or one hour after the plugin watched it stop if that
142
+ is later. The shipped per-row green dot persists until opened; a folder row
143
+ has no timestamp to contradict it, so a permanent green dot would outlive the
144
+ news. A finished session that was never seen running is judged by its own
145
+ updated time only.
146
+ - **Ungrouped sessions** mark the "Ungrouped" bucket row, which behaves like a
147
+ workspace row in the sidebar.
148
+ - **No mark when everything is idle.** The plugin renders nothing visible in
149
+ that case — no mark and no hidden activity sentence.
150
+
151
+ The active workspace (the one containing the open conversation) is already
152
+ marked natively: Harness paints the folder icon of the active chain blue. The
153
+ Pinned section mirrors that color on the group header that contains the current
154
+ conversation.
155
+
156
+ ## Install
157
+
158
+ From npm:
159
+
160
+ ```sh
161
+ dsh plugin --profile <profile> add dsh-workspace-status
162
+ ```
163
+
164
+ From a local checkout (development):
165
+
166
+ ```sh
167
+ dsh plugin --profile desktop add /absolute/path/to/dsh-workspace-status
168
+ ```
169
+
170
+ `dsh plugin add` links the checkout and appends this package to
171
+ `dsh.profile.bundles` because it declares `dsh.bundle`. Use the profile that
172
+ runs your client — `desktop` for the macOS/Windows app, `web` for `dsh web`.
173
+ Or use sidebar → **Plugins** → **Add plugin** and pass the absolute path to this
174
+ directory. The host half contributes nothing, but the profile composition still
175
+ changes, so **restart the profile's Host** (quit and reopen the desktop app, or
176
+ restart `dsh web`) after installing. Then reload the page if the client half
177
+ does not appear.
178
+
179
+ Manual mount without the CLI: copy the package into the profile's
180
+ `node_modules`, add `"dsh-workspace-status"` to `dsh.profile.bundles` in the
181
+ profile's `package.json`, and insert the row from `cordis.patch.yml` into the
182
+ profile's patch layer.
183
+
184
+ ## Verify
185
+
186
+ Workspace marks:
187
+
188
+ 1. Start a session in a workspace and collapse that group while it runs — a
189
+ blue ring appears at the end of the folder row.
190
+ 2. Trigger an approval (or a plan review / question) in a session of another
191
+ workspace — that folder row shows an amber dot even while expanded.
192
+ 3. Let a session finish without opening it — a green dot appears, and lapses an
193
+ hour later.
194
+ 4. Expand the group: the mark stays on the folder row; the session rows keep
195
+ their own dots unchanged.
196
+
197
+ Pinned section:
198
+
199
+ 1. Pin any conversation from its row hover button or **…** menu — the Pinned
200
+ section appears above **Workspaces** without a restart, grouped under that
201
+ conversation's workspace, with a filled pin icon on the row.
202
+ 2. Pin a conversation from a second workspace — a second group header appears;
203
+ both groups keep the workspace header treatment and their own count.
204
+ 3. Click a pinned row — the conversation opens. Click the pin icon — the row
205
+ disappears from the Pinned section and returns to its workspace group
206
+ immediately.
207
+ 4. Collapse the Pinned header or a group — the state persists across reloads.
208
+ 5. Restart the Harness — the same pins are listed again, because the Host
209
+ persists the registry pin set in the profile workspace registry.
210
+
211
+ Pinned notifications:
212
+
213
+ 1. Click the bell in the Pinned header. On first use it requests notification
214
+ permission and shows a test notice; the bell is highlighted while enabled.
215
+ 2. Pin a conversation that is running, then let it finish without opening it —
216
+ an in-app notice appears in the Pinned section; if the app window is in the
217
+ background, a desktop notification is raised as well. Clicking either opens
218
+ the conversation.
219
+ 3. Trigger an approval, plan review or question in a pinned conversation — the
220
+ notice names the reason and workspace and remains until dismissed.
221
+ 4. Click the bell again to turn notifications off, or the **×** on a notice to
222
+ dismiss it early. Reload: the bell, speaker and notification preferences
223
+ persist.
224
+
225
+ If the plugin is missing, check the browser console for a failed client bundle
226
+ load first; nothing else in the sidebar is affected.
227
+
228
+ ## How it works
229
+
230
+ - The mount is an entry in the additive `sidebar.footer.action` seat. It
231
+ publishes a stylesheet, a visually hidden activity description, and a portal
232
+ anchor; it adds no control of its own at the foot.
233
+ - Workspace marks read the same public data the browser uses: `useWorkspaces`
234
+ (`items`, `archivedSessionIds`, `pinnedSessionIds`), `useSessions` (`byId`) and
235
+ `useSessionStatus` (`running`, `pendingInteraction`, `completionUnread`).
236
+ - The workspace mark is the folder row's trailing pseudo-element, emitted as a
237
+ rule targeting `[data-row-key="workspace:<id>"]::after`.
238
+ - The Pinned section is rendered through a React portal into a container
239
+ inserted immediately before the sidebar's `regionArea` element. The official
240
+ browser is not replaced: search, menus, drag ordering, dialogs and directory
241
+ picking stay native.
242
+ - Pinned rows are lifted by hiding their `[data-row-key="session:<id>"]` rows
243
+ with generated CSS (`display:none!important`); search-result rows carry no
244
+ `data-row-key`, so they remain visible.
245
+ - Unpin calls `ctx.workspaces.unpinSession(id)`; opening a pinned row calls
246
+ `ctx.uiWorkspace.openSession(id)`. The pin set itself comes from the
247
+ Workspace snapshot, so both the official tree and this section stay in sync.
248
+ - Collapse memories and notification preferences live in browser
249
+ `localStorage`; no plugin settings are written. Notification delivery uses the
250
+ renderer's standard `Notification` API (and Web Audio for the optional chime);
251
+ the plugin does not add a host service.
252
+ - Removing the plugin removes the mount, the stylesheet and the inserted
253
+ section container; no profile or session data is changed by the plugin.
254
+
255
+ ### Internal dependencies
256
+
257
+ Two details belong to `@deepseek-ai/dsh-client-ui-workspace` / `ui-sidebar`
258
+ rather than a public slot contract:
259
+
260
+ - `data-row-key="workspace:<id>"` / `session:<id>` for row targeting;
261
+ - the `…_regionArea` class token for the portal insertion point.
262
+
263
+ A future Harness release could rename either; the failure modes are
264
+ deliberately **"no mark / no section"**, not "broken sidebar": the plugin never
265
+ replaces the browser and its DOM writes are limited to one inserted container.
266
+ `react-dom` is a shared client platform module (the same baseline the shell
267
+ seeds for every bundle), used only for the portal.
268
+
269
+ ## Compatibility
270
+
271
+ - DeepSeek Harness `>=0.2.1-rc.2 <0.3.0-0` (developed and verified against
272
+ `0.2.1-rc.3`); Web and Desktop clients.
273
+ - Node `>=22.18.0` for the build-free package and its tests.
274
+ - No host-side services, no settings, no model-visible tools or prompt changes.
275
+ Pins are the shipped Workspace registry pin set.
276
+
277
+ ## Development
278
+
279
+ ```sh
280
+ npm test
281
+ ```
282
+
283
+ The suite loads the classic-script client envelope in a sandbox, drives the slot
284
+ component with fake standard hooks, and asserts the emitted stylesheet and
285
+ hidden description across waiting/running/finished, subagent, archived,
286
+ ungrouped, expiry, pinned grouping (workspace order, ungrouped bucket, archived
287
+ / blank / subagent exclusion), hide rules, pin precedence and selector
288
+ escaping cases. A manifest test checks the bundle patch, export map, locale
289
+ parity and the loader envelope.
290
+
291
+ There is no build step: `index.js` and `client.js` are the published artifacts.
292
+
293
+ ## Remove
294
+
295
+ ```sh
296
+ dsh plugin --profile <profile> remove dsh-workspace-status
297
+ ```
298
+
299
+ Restart the Host. The sidebar returns to stock; the inserted section container
300
+ is removed with the plugin, and pins remain the shipped workspace registry
301
+ state (unpin them through the normal pin action).
302
+
303
+ ## License
304
+
305
+ MIT
@@ -0,0 +1,83 @@
1
+ # dsh-workspace-status · 工作区状态与置顶会话
2
+
3
+ [English](./README.md) · [中文](./README.zh-CN.md)
4
+
5
+ 为 DeepSeek Harness 侧边栏增加三层能力:
6
+
7
+ 1. **工作区状态标记**:在侧边栏的**工作区(文件夹)行**上显示彩色状态——等待你处理、正在运行、刚刚完成,由该工作区内的会话聚合而来。
8
+ 2. **已置顶会话区**:通过 Harness 原生置顶操作置顶的会话,会从常规工作区分组中提取出来,显示在工作区列表上方的独立区域;按工作区分组,沿用原生工作区行的样式,并在行尾显示置顶图标。
9
+ 3. **已置顶会话通知**:置顶会话开始等待你处理或运行结束未读时,窗口在后台会发系统通知,同时置顶区内始终显示应用内提醒;通知开关与提示音按钮位于置顶区标题栏。
10
+
11
+ 侧边栏本来就会在每个会话行上显示状态点,但上方的文件夹行什么都没有。收起分组或滚动之后,就看不出里面是否还有等待审批、仍在运行的会话。本插件补上这一层,并把置顶会话集中到列表上方。
12
+
13
+ ## 功能
14
+
15
+ ### 工作区状态标记
16
+
17
+ | 标记 | 含义 | 颜色 |
18
+ |---|---|---|
19
+ | 实心点 | 有会话在等你:审批 / 计划评审 / 回答 | 琥珀 `--dsw-alias-state-warn-primary` |
20
+ | 旋转圆环 | 有会话或子代理正在运行 | 蓝 `--dsw-static-deepseek-450` |
21
+ | 实心点 | 有会话刚刚结束且尚未打开(1 小时提示窗口) | 绿 `--dsw-alias-state-success-primary` |
22
+
23
+ - 状态优先级与原生会话行一致:等待 > 运行 > 刚刚完成;一个工作区同时只显示一个主标记。
24
+ - 子代理的运行状态计入其父会话所在工作区;子代理行本身不产生标记。
25
+ - 已归档会话忽略;未分组会话落在「未分组」行。
26
+ - 标记固定在行尾时间戳的位置,不挤动标题;展开或收起都可见。
27
+ - 提供隐藏的无障碍描述(如「工作区状态:2 个运行中、1 个等待你处理 — api、web」)。
28
+
29
+ ### 已置顶会话区
30
+
31
+ - 使用 Harness 原生置顶操作(会话行悬停按钮或 **…** 菜单);置顶后无需重启即可出现在 **Pinned / 已置顶** 区域。
32
+ - 按工作区分组,每组沿用原生 34px 工作区行:文件夹图标、当前工作区蓝色高亮、折叠三角、圆角与计数。
33
+ - 每行显示实时状态点、相对时间、当前会话高亮,以及行尾的实心**置顶图标**;点击图标立即取消置顶,行会回到原工作区分组。
34
+ - Pinned 标题和各工作区分组都可折叠,折叠状态保存在浏览器本地。
35
+ - 区块限高并可独立滚动,不会把工作区列表挤走。
36
+ - 置顶集合来自 Harness 的 `pinnedSessionIds`(保存在 profile 的工作区注册表),重启后仍会显示同样的置顶会话与图标。
37
+ - 搜索不受影响:已置顶会话仍然出现在搜索结果中;常规分组列表则隐藏被提取的行。
38
+ - 常规列表中的工作区标题会保留(其「新会话」按钮仍可用),因此当某个工作区的会话全部被置顶时,常规列表里可能出现一个空分组,而会话显示在上方。
39
+
40
+ ### 已置顶会话通知
41
+
42
+ - 触发条件(仅限已置顶会话):开始等待你(审批 / 计划评审 / 提问),或运行结束且完成标记未读。
43
+ - 只对状态**变化**发通知:刷新后的第一次观察保持安静,同一等待原因不会重复提醒,原因变化(审批 → 提问)会再次提醒,完成只在每次运行结束时提醒一次。
44
+ - 窗口在后台且系统已授权时发**桌面通知**;点击通知会聚焦应用并打开对应会话。
45
+ - 置顶区**始终**显示应用内提醒(系统阻止通知时同样可用),带状态图标、标题与原因;点击打开会话,点 **×** 或等待 8 秒自动消失。
46
+ - 标题栏的铃铛开关通知并在首次点击时申请权限、显示一条测试提醒;喇叭开关可选的两声提示音。两项偏好保存在浏览器本地,默认通知开、提示音关。
47
+ - 通知是客户端行为:应用运行期间才会触发,不提供邮件 / IM / Web Push 等外部推送,也不会提醒置顶以外的会话。
48
+
49
+ ## 快速开始
50
+
51
+ ```sh
52
+ dsh plugin --profile web add dsh-workspace-status
53
+ ```
54
+
55
+ 重启 Harness(或刷新 Web 界面)。工作区行会出现状态标记;置顶任意会话即可看到上方的置顶区域与铃铛/喇叭开关。
56
+
57
+ ## 要求
58
+
59
+ - DeepSeek Harness `>=0.2.1-rc.2 <0.3.0-0`,Web 或桌面版。
60
+ - Node `>=22.18.0`(仅测试需要;无构建步骤)。
61
+ - 不修改 Host 行为、不提供 Host 设置项、不向模型注册工具或提示词;置顶状态使用 Harness 原生工作区置顶集合,通知偏好与折叠状态保存在浏览器本地。
62
+
63
+ ## 验证
64
+
65
+ 1. 在某工作区运行会话并收起分组:工作区行尾出现蓝色圆环。
66
+ 2. 在另一个工作区触发审批:即使展开,该行也显示琥珀点。
67
+ 3. 让会话跑完但不打开:出现绿点,约一小时后消失。
68
+ 4. 置顶任意会话:列表上方立即出现 Pinned 区,按工作区分组,行尾有置顶图标。
69
+ 5. 再置顶另一个工作区的会话:出现第二个分组标题。
70
+ 6. 点击行尾置顶图标取消置顶:该行立即从 Pinned 区消失并回到原工作区分组。
71
+ 7. 重启 Harness:同样的置顶会话仍在,图标也仍显示。
72
+ 8. 点击置顶区标题栏的铃铛:首次会申请通知权限并显示测试提醒;再次点击关闭。
73
+ 9. 让置顶会话结束或开始等待:置顶区出现应用内提醒;窗口在后台时还会收到系统通知。
74
+
75
+ ## 相关链接
76
+
77
+ - 英文说明(完整细节):[README.md](./README.md)
78
+ - npm:<https://www.npmjs.com/package/dsh-workspace-status>
79
+ - 更新记录:[CHANGELOG.md](./CHANGELOG.md)
80
+
81
+ <sub>同系列插件:[情绪板](https://github.com/Stijnus/dsh-moodboard) · [输入补全](https://github.com/Stijnus/dsh-composer-predictions) · [移动到工作区](https://github.com/Stijnus/dsh-move-to-workspace) · [工作区状态](https://github.com/Stijnus/dsh-workspace-status) · [提示词改写](https://github.com/Stijnus/dsh-prompt-optimizer)</sub>
82
+
83
+ <sub>⭐ 如果它帮你省了一步,点个 star 能让更多 DSH 用户发现它。</sub>