dsh-messager 0.3.4 → 0.3.5

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.
Files changed (3) hide show
  1. package/README.en.md +33 -207
  2. package/README.md +24 -287
  3. package/package.json +62 -62
package/README.en.md CHANGED
@@ -1,221 +1,47 @@
1
1
  # dsh-messager
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
4
- [![npm version](https://img.shields.io/npm/v/dsh-messager)](https://www.npmjs.com/package/dsh-messager)
5
- [![Node](https://img.shields.io/badge/node-%3E%3D20-blue.svg)](package.json)
3
+ [简体中文](README.md) | [English](README.en.md)
6
4
 
7
- > **Task-status notification plugin for DeepSeek Harness (DSH).** Get notified via **system notifications** (OS toast), **browser notifications**, and **Feishu / WeCom / Discord / DingTalk / Telegram** whenever a session needs attention, a task completes, or a task errors — no more staring at the status dots in the session list.
5
+ A task notification plugin for DeepSeek Harness (DSH). Get system, browser, Feishu, WeCom, Discord, DingTalk, or Telegram notifications when a session needs approval or input, a task completes, or a task fails.
8
6
 
9
- A single-package, dual-runtime design: the **host side** (Node server) handles system notifications and all third-party channels; the **client side** (browser) handles Web Notification. Both share one config source (settings namespace `messager`), editable live from the "Messenger" settings section — config flows through the plugin's own webserver route (`/dsh-messager/config`), so it works on all environments including release/npx/npm installs (no DSH settings allowlist dependency).
7
+ ## Compatibility
10
8
 
11
- ## Feature overview
9
+ **v0.3.5 supports DSH `0.2.0-rc.1` and compatible later 0.2.x releases.** Keep the matching older plugin version for DSH 0.1.x. Upgrade DSH before installing this version; existing notification settings need no migration.
12
10
 
13
- | Need | Implementation |
14
- | --- | --- |
15
- | Triggers | Needs-interaction (approval `approval/asked`, question/plan-review `ask_user_question`, client `pendingInteraction`), task completed (`agent/status` running→idle, root sessions only + `turn/end` reason), task errored (`agent/error`) |
16
- | Channels | System (node-notifier toast), browser (Notification API), Feishu (interactive card + HMAC-SHA256 signature), WeCom (markdown + optional signing), Discord (embed card), DingTalk (actionCard + optional signing), Telegram (Bot API HTML message); extensible via the `NotifyChannel` interface |
17
- | Configurable | Trigger toggles, per-channel enable/verbosity/icon, dedup cooldowns, title prefix, etc. — see [Configuration](#configuration) |
11
+ ## Install
18
12
 
19
- Trigger semantics align with the Web UI status dots: **orange = needs interaction** (`pendingInteraction`), **green = task completed** (`running→idle` and not the current session), **blue = running** (not notified).
13
+ **DSH desktop app:** Open **Plugins** in the top-left corner, choose **Add plugin**, enter `dsh-messager`, and install it. Restart DSH after installation.
20
14
 
21
- ## Installation
15
+ **CLI (npm package):** Requires Node.js 20+, pnpm, and the DSH CLI. Install into the Web profile:
22
16
 
23
- > 📖 A full step-by-step guide for **end users** is at [doc/用户安装指南.md](doc/用户安装指南.md) (Chinese) — covering **from source** (clone + local build) and **pnpm** (local checkout / tarball / git / npm) installs.
17
+ ```sh
18
+ dsh plugin --profile web add dsh-messager
19
+ dsh web
20
+ ```
24
21
 
25
- **One step for a formal install** (host + browser client both take effect; then just start with `dsh web` — **no** `--patch` needed):
22
+ When running DSH from its source repository, use `pnpm dsh` instead of `dsh`. Restart DSH if it was already running.
26
23
 
27
- ``sh
28
- # Build inside the plugin repo
24
+ **From source** (optional for developers):
25
+
26
+ ```sh
27
+ git clone https://github.com/ly6170/dsh-messager.git
28
+ cd dsh-messager
29
29
  pnpm install
30
30
  pnpm build
31
+ dsh plugin --profile web add .
32
+ dsh web
33
+ ```
34
+
35
+ ## Use
36
+
37
+ Open **Settings → Messenger** (「通知&信使」), choose the events and channels you want, enter any webhook or bot credentials, and save. System and browser notifications are enabled by default; third-party channels are disabled by default. Browser notifications require site permission.
38
+
39
+ Notifications cover interactions, root-session task completion, and task errors. Running status does not trigger a notification. Saved settings take effect immediately.
40
+
41
+ ## Troubleshooting
42
+
43
+ - **Settings section missing or config route returns 404:** Check the active `web` profile, restart DSH, and verify DSH/plugin version compatibility.
44
+ - **No browser notification:** Check site permission. By default, notifications appear only when the page is hidden or unfocused.
45
+ - **Settings unavailable with `--patch`:** That development mode loads only the host side. Install with `dsh plugin add` to use the settings page.
31
46
 
32
- dsh plugin --profile web add <plugin-path>
33
- dsh web # or dsh --profile web
34
- ``
35
-
36
- > `pnpm install` and `pnpm build` run inside your plugin checkout; replace `<plugin-path>` with that directory (absolute or relative both work).
37
-
38
- > - `--patch` is **not** an install step — it is an optional **development** tool (see "Local development" below): it loads only the host side, writes nothing to the profile, and applies to the current launch only. After installing the bundle, **do not** start the same plugin with `--patch` simultaneously (the host side loads twice and the settings namespace registration conflicts).
39
- > - When running DSH **from source** (from the deepseek-harness repo root), replace `dsh` with `pnpm dsh` — identical behavior: `pnpm dsh plugin --profile web add …`, `pnpm dsh web`. The profile directory stays `$DSH_HOME/profiles/web` (`dsh web` is the `--profile web` alias).
40
- > - Installing from git with pnpm ≥ 10 requires approving build scripts: add the package key pnpm prompts for to the profile's `pnpm-workspace.yaml` `allowBuilds` (see the official DSH publish tutorial).
41
-
42
- ### Settings section "Messenger" (available everywhere)
43
-
44
- After installation, a **「通知&信使」** (Messenger) section appears in the DSH settings sidebar (below "Agent presets"; its position is computed dynamically from existing sections, not hard-coded). It hosts the full config form, read/written through the plugin's own webserver route (`/dsh-messager/config`, same-origin check + redacted view) straight to the host `settings` service — **no dependency on the DSH settings allowlist; works out of the box on release (npx) installs**, no patches needed.
45
-
46
- > The config is the same source as `settings.yaml` (same namespace): any change applies instantly everywhere.
47
-
48
- ## Local development
49
-
50
- - **Host side (quick)**: from the DSH repo root run
51
- `pnpm dsh web --patch <plugin-path>/cordis.yml` — loads the TS source directly (HMR works). In source mode the host runs via tsx, so no build is needed to load that path.
52
- - **Full dual-runtime**: the browser (client) side requires the plugin to enter the Loader as a package for clientModules to scan it into the Web bundle (`--patch` file-path entries are not scanned), so do a full install into the profile:
53
- ``sh
54
- dsh plugin --profile web add <plugin-path> # source mode: pnpm dsh plugin ...
55
- pnpm dsh web # run from the DSH source repo
56
- ``
57
- **Restart** `pnpm dsh web` after `plugin add` (clientModules scans at startup; a running instance does not hot-add new bundles). After changing client code, re-run `pnpm run build:client` in your own repo and refresh the page (the bundle carries a rev hash so it is re-fetched; the DSH repo's `dev:web` watcher only watches in-workspace client plugins, not external ones).
58
-
59
- Browser notifications require user permission: the plugin requests it once on load when the permission is `default`; if denied, the browser channel degrades silently (other channels are unaffected) — re-authorize in the browser's site settings.
60
-
61
- ## Configuration
62
-
63
- Precedence: **schema defaults → base (that row's `config:`) → user layer (Web settings section)**. The host registers the Loader config as the `messager` namespace's base, therefore:
64
-
65
- - How to write base differs by usage: for dev debugging write `config:` on the row in `cordis.yml` (patch overlay); for formal installs override the row by `id: messager` in the **profile's `cordis.patch.yml`**, or edit the `cordis.patch.yml` inside the bundle package;
66
- - The user layer has three entry points, **same source, no conflicts, any change applies instantly** (host `watch` rebuilds channels; client refetches on `settings/document-updated`):
67
- 1. **Settings section**: Settings → "Messenger" (full field form, available in all environments);
68
- 2. **Settings document**: edit the `messager:` block of `$DSH_HOME/settings.yaml` directly (all fields, including dedup throttling not shown in the form);
69
- 3. **RPC**: settings.describe / settings.mutate (host side; the Web allowlist does not affect this plugin's section, since the section uses the plugin's own config route).
70
-
71
- > Config read/write path: settings section → `GET/POST /dsh-messager/config` (webserver route, same-origin check) → host `settings` service (describe redacted view / mutate per-field ops) → settings.yaml. After a write, the `settings/document-updated` event (built-in DSH forwarding) drives the frontend refresh.
72
- >
73
- > 🌐 **i18n**: the section menu and form follow the DSH display language (简体中文 / English); dictionaries are registered in `ctx.locale` (zh/en key sets identical; missing keys fail loud by showing the key name).
74
-
75
- | Field | Type | Default | Description |
76
- | --- | --- | --- | --- |
77
- | `triggers.interaction` | boolean | `true` | Notify when interaction is needed (approval/question/plan-review) |
78
- | `triggers.completed` | boolean | `true` | Notify when a task completes |
79
- | `triggers.error` | boolean | `true` | Notify when a task errors |
80
- | `system.enabled` | boolean | `true` | System notification channel |
81
- | `system.icon` | string | - | Absolute icon path (node-notifier needs a file path, **and the file must exist**) |
82
- | `system.verbosity` | `minimal\|normal\|detailed` | `normal` | System content verbosity |
83
- | `browser.enabled` | boolean | `true` | Browser notification channel |
84
- | `browser.icon` | string | - | Icon URL or data URL |
85
- | `browser.onlyWhenHidden` | boolean | `true` | Notify only when the page is hidden/unfocused |
86
- | `browser.verbosity` | `minimal\|normal\|detailed` | `normal` | Browser content verbosity |
87
- | `feishu.enabled` | boolean | `false` | Feishu bot (webhook) channel |
88
- | `feishu.webhookUrl` | string | - | Custom bot webhook URL |
89
- | `feishu.secret` | string (secret) | - | Signing secret (bot "security settings - signature") |
90
- | `feishu.timeoutMs` | number | `5000` | Per-request timeout |
91
- | `feishu.verbosity` | `minimal\|normal\|detailed` | `normal` | Card content verbosity |
92
- | `wecom.enabled` | boolean | `false` | WeCom group bot (webhook) channel |
93
- | `wecom.webhookUrl` | string | - | Group bot webhook URL (with `?key=`) |
94
- | `wecom.secret` | string (secret) | - | Signing secret ("security settings - signing", HMAC-SHA256, no URL encoding) |
95
- | `wecom.timeoutMs` | number | `5000` | Per-request timeout |
96
- | `wecom.verbosity` | `minimal\|normal\|detailed` | `normal` | Message content verbosity |
97
- | `discord.enabled` | boolean | `false` | Discord channel (webhook) |
98
- | `discord.webhookUrl` | string | - | Discord webhook URL (`.../api/webhooks/<id>/<token>`) |
99
- | `discord.timeoutMs` | number | `5000` | Per-request timeout |
100
- | `discord.verbosity` | `minimal\|normal\|detailed` | `normal` | Embed content verbosity |
101
- | `dingtalk.enabled` | boolean | `false` | DingTalk custom bot (webhook) channel |
102
- | `dingtalk.webhookUrl` | string | - | Custom bot webhook URL (with `?access_token=`) |
103
- | `dingtalk.secret` | string (secret) | - | Signing secret ("security settings - signing", HMAC-SHA256 + URL encoding) |
104
- | `dingtalk.timeoutMs` | number | `5000` | Per-request timeout |
105
- | `dingtalk.verbosity` | `minimal\|normal\|detailed` | `normal` | Card content verbosity |
106
- | `telegram.enabled` | boolean | `false` | Telegram channel (Bot API) |
107
- | `telegram.botToken` | string (secret) | - | Bot token (from @BotFather) |
108
- | `telegram.chatId` | string | - | Target chat_id (numeric ID or `@channel-username`) |
109
- | `telegram.timeoutMs` | number | `5000` | Per-request timeout |
110
- | `telegram.verbosity` | `minimal\|normal\|detailed` | `normal` | Message content verbosity |
111
- | `dedup.interactionCooldownMs` | number | `10000` | Cooldown for same session/trigger (also the cross-tab dedup window) |
112
- | `dedup.completedDebounceMs` | number | `1000` | Completion debounce (waits for the turn/end reason, merges boundary jitter) |
113
- | `dedup.perChannelPerMinute` | number | `20` | Per-channel per-minute cap (protects against third-party rate limits/spam) |
114
- | `message.titlePrefix` | string | - | Title prefix, e.g. `[DSH]` |
115
- | `message.includeSessionTitle` | boolean | `true` | Include session title in the body |
116
- | `message.guiUrl` | string | `http://127.0.0.1:3080` | "Open" link/button target |
117
-
118
- Verbosity: `minimal` = title only; `normal` adds session title/tool name/end reason/error summary; `detailed` adds turn/step, approval reason and the GUI link.
119
-
120
- ## Trigger signals (event → notification mapping)
121
-
122
- | Trigger | Host side (system/feishu/wecom/discord/dingtalk/telegram) | Client side (browser) |
123
- | --- | --- | --- |
124
- | Approval | `session/event` `approval/asked` | summary `pendingInteraction==='approval'` appears |
125
- | Question / plan-review | `session/event` `tool/call` (`ask_user_question`) | `pendingInteraction==='question'/'plan-review'` appears |
126
- | Task completed | `agent/status` running→idle (root sessions only) + `turn/end` reason | summary `running:true→false` and not the current session |
127
- | Task errored | `agent/error` | - (covered by the host side) |
128
-
129
- ## Channel extension
130
-
131
- Add a third-party channel (DingTalk / WeCom / Telegram…) by implementing the `NotifyChannel` interface and registering it in `buildChannels()` in `src/index.ts`:
132
-
133
- ``ts
134
- export interface NotifyChannel {
135
- readonly id: string
136
- send(payload: NotificationPayload): Promise<void>
137
- }
138
- ``
139
-
140
- ## Project structure
141
-
142
- ``
143
- dsh-messager/
144
- ├── package.json # dsh.bundle + dsh.client dual declarations; exports["./client"]
145
- ├── tsconfig.json # host side (Node)
146
- ├── tsconfig.client.json # client declaration output (lib/types/client)
147
- ├── tsdown.config.ts # client bundle (__ModuleLoader__.load contract)
148
- ├── cordis.yml # local development overlay (host side)
149
- ├── cordis.patch.yml # bundle config layer (applies after install)
150
- ├── assets/icon.png # default notification icon
151
- ├── src/
152
- │ ├── index.ts # host apply: event wiring + settings registration + channel building + route mounting
153
- │ ├── config.ts # Config schema (shared by Loader config and settings)
154
- │ ├── config-shared.ts # cross-end shared types for the config route (host/client)
155
- │ ├── config-route.ts # webserver config route (GET view / POST ops, same-origin check)
156
- │ ├── signals.ts # event → Signal extraction (pure functions)
157
- │ ├── notify.ts # dispatch: filter/cooldown/debounce/rate-limit + NotifyChannel interface
158
- │ ├── templates.ts # verbosity template rendering (pure functions)
159
- │ ├── settings.ts # settings namespace registration (base = Loader config)
160
- │ ├── channels/ # system (node-notifier), feishu/wecom/discord/dingtalk/telegram (webhook/Bot API + signing)
161
- │ └── client/ # browser side: sessions diff, Notification, settings section, config sync
162
- │ ├── index.ts # section registration (dynamic order) + browser notifications + config route accessor
163
- │ ├── section.tsx # "Messenger" settings section component
164
- │ ├── settings-form.tsx # shared form body (groups + FieldRow + action bar)
165
- │ ├── card-controller.ts # form controller (pure logic, unit-testable)
166
- │ ├── fetch-scope.ts # fetch adapter for ScopeLike (config route)
167
- │ ├── locales.ts # zh/en dictionaries (ctx.locale registration)
168
- │ ├── config.ts # browser-notification config handle (via the config route)
169
- │ └── diff.ts # session summary diff (pure functions)
170
- └── tests/ # vitest unit tests (126)
171
- ``
172
-
173
- ## Testing
174
-
175
- ``sh
176
- pnpm test # 147 unit tests: signal extraction/templates/dispatch/channel payloads & signatures/config parsing/client diff/config route/fetch scope/locale consistency/form gating
177
- pnpm typecheck # host side
178
- pnpm build # host tsc + client declarations + client bundle (lib/)
179
- ``
180
-
181
- ## Version compatibility (dsh-messager 0.3.4 / DSH 0.1.7-rc.1)
182
-
183
- - **v0.3.4 supports DSH `0.1.7-rc.1` and compatible later `0.1.x` releases.** All `@deepseek-ai/dsh-*` peer dependencies use the range `^0.1.7-rc.1`; the range excludes DSH `0.1.7-alpha.1` and earlier versions. Upgrade DSH to `0.1.7-rc.1` or a compatible later `0.1.x` release before upgrading this plugin.
184
- - DSH `0.1.7-rc.1` checks a bundle's own peer dependencies and skips incompatible bundles. v0.3.4 replaces the old exact alpha.1 pins with version ranges, aligns companion Cordis and Schemastery dependencies, and adds the required `@deepseek-ai/cordis-plugin-group` peer.
185
- - The relevant host APIs did not change from DSH alpha.1 to rc.1. This release requires no plugin API migration or notification configuration reset.
186
- - The removed `dsh-client-runtime` is no longer used. Client session lists use `dsh-api-session-controller`, interaction state uses `dsh-client-ui-session`, and slot services use `dsh-client-ui-renderer`.
187
- - The settings namespace is the profile entry ID (`messager` by default). Configuration remains available through the plugin's own `/dsh-messager/config` route. DSH 0.1.7 loads the schema from the entry module's exported `Config`, requires editable fields to be `.volatile()`, and broadcasts changes through `settings/document-updated`.
188
- - DSH 0.1.7 imports an existing legacy `settings.yaml` into the profile at startup and renames it to `settings.yaml.imported`.
189
- - v0.3.3 reads the live volatile configuration when each notification is delivered, keeps browser notifications disabled until the host configuration loads, honors trigger filters in the browser, and refreshes configuration when a background tab becomes visible.
190
- - The settings form keeps its save controls visible and shows the number of unsaved changes.
191
-
192
- ## Known limitations
193
-
194
- - Browser notifications require site permission; with `onlyWhenHidden=false` they also pop while visible.
195
- - Multi-tab dedup uses a localStorage cooldown; different browsers notify independently.
196
- - Subagent completions are not notified (root sessions only), to avoid noise.
197
- - Channel failures (webhook timeouts, unavailable toasts) are only logged; they don't affect other channels or the plugin.
198
- - Completion/interaction dedup state is in-memory and resets on DSH restart (acceptable).
199
-
200
- ### System notification (node-notifier) cross-platform prerequisites
201
-
202
- `node-notifier` invokes completely different underlying programs on the three platforms:
203
-
204
- | Platform | Backend | Prerequisites / differences |
205
- | --- | --- | --- |
206
- | Windows | PowerShell ToastNotification | Built in, nothing to install; `sound` maps reliably only on Windows |
207
- | macOS | terminal-notifier | First use **downloads** a third-party binary, and a logged-in GUI session (Dock present) is required; `sound` has no effect |
208
- | Linux | notify-send (libnotify) | Requires `libnotify-bin` and a **running notification daemon** (GNOME Shell / Plasma / mako / dunst etc.); `sound` has no effect |
209
-
210
- - **Icon**: `system.icon` must be an **existing file path**. Windows usually degrades silently on a missing path, but Linux/macOS may fail outright — the channel layer validates existence and falls back to no icon.
211
- - **Environment differences are not plugin bugs**: on Linux without a notification daemon, or macOS unable to download terminal-notifier / not in a GUI session, notifications may not pop or fail silently — check those prerequisites first, not the plugin; on failure the dispatcher logs the concrete error via `logWarn`.
212
-
213
- ## Roadmap
214
-
215
- - Third-party channel extension: email
216
- - Trigger extension: background job completion, goal round completion
217
- - Notification history, per-session mute, do-not-disturb windows
218
-
219
- ## License
220
-
221
- [MIT](LICENSE) © [ly6170](https://github.com/ly6170)
47
+ [v0.3.5 release notes](RELEASE_NOTES_v0.3.5.md) · [中文](README.md) · [MIT License](LICENSE)
package/README.md CHANGED
@@ -1,310 +1,47 @@
1
1
  # dsh-messager
2
2
 
3
- DeepSeek Harness(DSH)**任务状态通知插件**:会话需要交互、任务完成、任务出错时,通过
4
- **系统通知**(OS toast)、**浏览器通知**、**飞书 / 企业微信 / Discord / 钉钉 / Telegram** 推送提醒,
5
- 不再依赖盯着会话列表的圆点。
3
+ [简体中文](README.md) | [English](README.en.md)
6
4
 
7
- 单包双运行端(dual-runtime)结构:**host 端**(Node,服务端)负责系统通知与全部第三方通道,
8
- **client 端**(浏览器)负责 Web Notification;两者配置同源(settings 命名空间 `messager`),
9
- 设置页「通知&信使」分区可编辑、实时生效 —— 配置通道经插件自身的 webServer 路由
10
- (`/dsh-messager/config`),**不受 DSH 设置白名单限制,发行版(npx 安装)同样可用**。
5
+ DeepSeek Harness(DSH)的任务通知插件。会话需要审批、提问或计划审核,任务完成或出错时,可发送系统通知、浏览器通知,以及飞书、企业微信、Discord、钉钉、Telegram 消息。
11
6
 
12
- ## 能力一览
7
+ ## 兼容版本
13
8
 
14
- | 需求 | 实现 |
15
- | --- | --- |
16
- | 触发时机 | 需要交互(审批 `approval/asked`、提问/计划待审 `ask_user_question`、客户端 `uiSession.sessionStatus`)、任务完成(`agent/status` running→idle 且仅根会话 + `turn/end` 原因)、任务出错(`agent/error`) |
17
- | 推送路径 | 系统通知(node-notifier toast)、浏览器通知(Notification API)、飞书(interactive 卡片 + HMAC-SHA256 签名)、企业微信(markdown + 可选加签)、Discord(embed 卡片)、钉钉(actionCard + 可选加签)、Telegram(Bot API HTML 消息);`NotifyChannel` 接口可扩展 |
18
- | 可配置 | 触发开关、各通道启停/verbosity/icon、去重冷却、标题前缀等,见[配置](#配置) |
19
-
20
- 触发语义与 Web UI 状态圆点完全对齐:**橙点 = 需要交互**(`uiSession.sessionStatus`),**绿点 = 任务完成**
21
- (`running→idle` 且不在主视图),**蓝点 = 运行中**(不通知)。
9
+ **v0.3.5 支持 DSH `0.2.0-rc.1` 及兼容的后续 0.2.x 版本。** 使用 DSH 0.1.x 请保留对应的旧版插件。升级到 DSH 0.2.x 后再安装本版本;现有通知配置无需迁移。
22
10
 
23
11
  ## 安装
24
12
 
25
- > 📖 面向**使用方**的完整分步指南见 [doc/用户安装指南.md](doc/用户安装指南.md) —— 覆盖
26
- > **源码方式**(clone + 本地构建)与 **pnpm 方式**(本地 checkout / tarball / git / npm)两类安装。
13
+ **DSH 桌面版:**点击左上角「插件」→「添加插件」,输入 `dsh-messager` 并安装。安装后重启 DSH。
27
14
 
28
- **正式安装只需一步**(host 端 + 浏览器 client 端都会生效,之后直接 `dsh web` 启动即可,
29
- **不需要** `--patch`):
15
+ **命令行版(npm 包):**需要 Node.js 20+、pnpm 和 DSH CLI。将包安装到 Web profile:
30
16
 
31
17
  ```sh
32
- # 在插件仓库构建产物
33
- pnpm install
34
- pnpm build
35
-
36
- dsh plugin --profile web add <插件路径>
37
- dsh web # 或 dsh --profile web
38
- ```
39
-
40
- > `pnpm install` 与 `pnpm build` 在你的插件仓库目录内执行;`<插件路径>` 替换为该目录
41
- > (绝对或相对路径均可)。完整的分步安装指南见 [doc/用户安装指南.md](doc/用户安装指南.md)。
42
-
43
- > - `--patch` 不是安装步骤,而是可选的**开发调试**手段(见下节「本地开发」):
44
- > 它只加载 host 端、不写 profile、仅对本次启动生效。装了 bundle 之后**请勿再同时
45
- > 带 `--patch` 启动同一插件**(host 端会加载两份,同一事件重复通知)。
46
- > ⚠️ 另外,经 `--patch` 装入的条目 id 会带 `include:` 前缀、且**不会进入
47
- > `settings.describe()`**,因此 `--patch` 模式下设置页分区必然显示「不可用」——
48
- > 这是该调试路径的固有限制,验证设置页请走 `dsh plugin add` 安装。
49
- > - 以**源码方式运行 DSH**(从 deepseek-harness 仓库根目录)时,把上述 `dsh` 换成
50
- > `pnpm dsh` 即可,命令与行为完全一致:`pnpm dsh plugin --profile web add …`、
51
- > `pnpm dsh web`。profile 目录仍为 `$DSH_HOME/profiles/web`(`dsh web` 即
52
- > `--profile web` 别名)。
53
- > - 从 git 安装时 pnpm ≥ 10 需要放行构建脚本:把 pnpm 提示的包名加入 profile 的
54
- > `pnpm-workspace.yaml` 的 `allowBuilds`(见 DSH 官方 publish 教程)。
55
-
56
- ### 设置分区「通知&信使」(所有环境可用)
57
-
58
- 安装后 DSH 设置页左侧菜单会出现 **「通知&信使」** 分区(排在「Agent预设」下方,位置
59
- 随已有分区动态计算,不写死)。分区内是完整的配置表单,读写经插件自身的
60
- webServer 路由(`/dsh-messager/config`,同源校验 + 脱敏视图)直达 host 端
61
- `settings` 服务 —— **不依赖 DSH 的设置白名单,发行版(npx 安装)开箱即用**,
62
- 无需任何补丁。
63
-
64
- > 配置与 host 端**同源**(同一 settings 命名空间):任一处变更均实时生效。
65
-
66
- ## 本地开发
67
-
68
- - **host 端(快速)**:从 DSH 仓库根目录运行
69
- `pnpm dsh web --patch <插件路径>/cordis.yml`,直接加载 TS 源码(HMR 生效)。
70
- 源码模式下的 host 经 tsx 运行,该路径无需构建即可加载。
71
- - **完整双运行端**:浏览器(client)端要求插件以包身份进入 Loader 才会被 clientModules
72
- 扫描编入 Web bundle(`--patch` 的文件路径入口不会被扫描),因此完整开发请安装到 profile:
73
- ```sh
74
- dsh plugin --profile web add <插件路径> # 源码模式:pnpm dsh plugin ...
75
- pnpm dsh web # 从 DSH 源码仓库运行
76
- ```
77
- `plugin add` 后需要**重启** `pnpm dsh web`(clientModules 启动时扫描,运行中的实例
78
- 不会热加入新 bundle)。修改 client 端代码后在自己的仓库重新 `pnpm run build:client`
79
- 并刷新页面即可(bundle 带 rev hash 会重新拉取;DSH 仓库的 `dev:web` watcher 只盯
80
- workspace 内的 client 插件,不盯外部插件)。
81
-
82
- 浏览器通知需要用户授予权限:首次加载插件时若权限为 `default` 会自动请求一次;
83
- 被拒绝时浏览器通道静默降级(其余通道不受影响),可在浏览器站点设置中重新授权。
84
-
85
- ## 配置
86
-
87
- 配置优先级:**schema 默认值 → base(该插件行的 `config:`)→ 用户层(Web 设置页)**。
88
-
89
- > ⚠️ **DSH 0.1.7 的配置模型**(与旧版不同,务必知悉):
90
- > - settings 命名空间 = 插件在 profile 中的**条目 id**(本包 `cordis.patch.yml`
91
- > 声明为 `messager`),**不是**插件自己注册的字符串;
92
- > - schema 由 Loader 直接读取**插件入口模块导出的 `Config`**,因此 `src/index.ts`
93
- > 必须 `export { Config }`——不导出则该条目被 `describe()` 静默跳过,设置页与
94
- > 配置路由一律显示「不可用」且**不报错**;
95
- > - 所有可编辑字段必须标记 `.volatile()`:DSH 用 volatile 门控写入,非 volatile
96
- > 路径会被 `settings.mutate` 拒绝,且无 volatile 字段时整个命名空间判为不可配置;
97
- > - 已**没有** `ctx.settings.register(...)` 这种 API;配置热更新改由
98
- > `settings/document-updated` 事件驱动。
99
-
100
- - base 的写法按使用方式不同:dev 调试写在 `cordis.yml`(patch 覆盖层)里该行的
101
- `config:`;正式安装写在 **profile 的 `cordis.patch.yml`** 里按 `id: messager`
102
- 覆盖该行,或直接改 bundle 包内的 `cordis.patch.yml`;
103
- - 用户层两处入口,**同源不冲突、任一处变更均实时生效**(host 端订阅
104
- `settings/document-updated` 重建通道;client 端同样据此失效重拉):
105
- 1. **设置页分区**:设置 →「通知&信使」分区(完整字段表单,所有环境可用);
106
- 2. **RPC**:settings.describe / settings.mutate(host 侧可用;Web 端白名单不影响
107
- 本插件的分区,因为分区走插件自己的配置路由)。
108
-
109
- > 配置读写链路:设置分区 → `GET/POST /dsh-messager/config`(webServer 路由,同源校验)
110
- > → host 端 `settings` 服务(describe 脱敏视图 / mutate 逐字段 ops)→ profile 的
111
- > `cordis.patch.yml`。写后 `settings/document-updated` 事件(DSH 内置转发)驱动前端刷新。
112
- >
113
- > 📌 DSH 0.1.7 已废弃 `$DSH_HOME/settings.yaml` 作为配置源:启动时若存在会被自动
114
- > 导入 profile 并**重命名为 `settings.yaml.imported`**。请改编辑 profile 的
115
- > `cordis.patch.yml`(或用设置页)。
116
- >
117
- > 🌐 **国际化**:分区菜单与表单文案随 DSH 设置的语言切换(中文 / English),
118
- > 字典注册在 `ctx.locale`(zh/en 键集一致,缺失键 fail loud 显示键名)。
119
-
120
- | 字段 | 类型 | 默认值 | 说明 |
121
- | --- | --- | --- | --- |
122
- | `triggers.interaction` | boolean | `true` | 需要交互时通知(审批/提问/计划待审) |
123
- | `triggers.completed` | boolean | `true` | 任务完成时通知 |
124
- | `triggers.error` | boolean | `true` | 任务出错时通知 |
125
- | `system.enabled` | boolean | `true` | 系统通知通道 |
126
- | `system.icon` | string | - | 图标绝对路径(node-notifier 需要文件路径,**且该文件必须存在**) |
127
- | `system.verbosity` | `minimal\|normal\|detailed` | `normal` | 系统通知内容繁复度 |
128
- | `browser.enabled` | boolean | `true` | 浏览器通知通道 |
129
- | `browser.icon` | string | - | 图标 URL 或 data URL |
130
- | `browser.onlyWhenHidden` | boolean | `true` | 仅页面隐藏/未聚焦时弹(看着界面不打扰) |
131
- | `browser.verbosity` | `minimal\|normal\|detailed` | `normal` | 浏览器通知内容繁复度 |
132
- | `feishu.enabled` | boolean | `false` | 飞书机器人(webhook)通道 |
133
- | `feishu.webhookUrl` | string | - | 自定义机器人 webhook 地址 |
134
- | `feishu.secret` | string(secret) | - | 签名密钥(机器人「安全设置-签名校验」) |
135
- | `feishu.timeoutMs` | number | `5000` | 单次请求超时 |
136
- | `feishu.verbosity` | `minimal\|normal\|detailed` | `normal` | 卡片内容繁复度 |
137
- | `wecom.enabled` | boolean | `false` | 企业微信群机器人(webhook)通道 |
138
- | `wecom.webhookUrl` | string | - | 群机器人 webhook 地址(含 `?key=`) |
139
- | `wecom.secret` | string(secret) | - | 加签密钥(「安全设置-加签」,HMAC-SHA256,无需 URL 编码) |
140
- | `wecom.timeoutMs` | number | `5000` | 单次请求超时 |
141
- | `wecom.verbosity` | `minimal\|normal\|detailed` | `normal` | 消息内容繁复度 |
142
- | `discord.enabled` | boolean | `false` | Discord 通道(webhook) |
143
- | `discord.webhookUrl` | string | - | Discord webhook 地址(`.../api/webhooks/<id>/<token>`) |
144
- | `discord.timeoutMs` | number | `5000` | 单次请求超时 |
145
- | `discord.verbosity` | `minimal\|normal\|detailed` | `normal` | embed 内容繁复度 |
146
- | `dingtalk.enabled` | boolean | `false` | 钉钉自定义机器人(webhook)通道 |
147
- | `dingtalk.webhookUrl` | string | - | 自定义机器人 webhook 地址(含 `?access_token=`) |
148
- | `dingtalk.secret` | string(secret) | - | 加签密钥(「安全设置-加签」,HMAC-SHA256 + URL 编码) |
149
- | `dingtalk.timeoutMs` | number | `5000` | 单次请求超时 |
150
- | `dingtalk.verbosity` | `minimal\|normal\|detailed` | `normal` | 卡片内容繁复度 |
151
- | `telegram.enabled` | boolean | `false` | Telegram 通道(Bot API) |
152
- | `telegram.botToken` | string(secret) | - | Bot Token(@BotFather 获取) |
153
- | `telegram.chatId` | string | - | 接收 chat_id(数字 ID 或 `@频道用户名`) |
154
- | `telegram.timeoutMs` | number | `5000` | 单次请求超时 |
155
- | `telegram.verbosity` | `minimal\|normal\|detailed` | `normal` | 消息内容繁复度 |
156
- | `dedup.interactionCooldownMs` | number | `10000` | 同会话同触发冷却(也用于跨标签去重窗口) |
157
- | `dedup.completedDebounceMs` | number | `1000` | 完成通知防抖(等待 turn/end 原因、合并边界) |
158
- | `dedup.perChannelPerMinute` | number | `20` | 每通道每分钟上限(防第三方限流/刷屏) |
159
- | `message.titlePrefix` | string | - | 标题前缀,如 `[DSH]` |
160
- | `message.includeSessionTitle` | boolean | `true` | 正文附带会话标题 |
161
- | `message.guiUrl` | string | `http://127.0.0.1:3080` | 通知「打开」链接/按钮目标 |
162
-
163
- 内容繁复度:`minimal` 只有标题;`normal` 增加会话标题/工具名/结束原因/错误摘要;
164
- `detailed` 再增加 turn/step、审批原因与 GUI 链接。
165
-
166
- ## 触发信号(事件 → 通知映射)
167
-
168
- | 触发 | host 端(system/feishu/wecom/discord/dingtalk/telegram) | client 端(browser) |
169
- | --- | --- | --- |
170
- | 审批 | `session/event` `approval/asked` | `ctx.uiSession.sessionStatus` 中 `pendingInteraction.kind==='approval'` 从无到有 |
171
- | 提问/计划待审 | `session/event` `tool/call`(`ask_user_question`) | `ctx.uiSession.sessionStatus` 中 `pendingInteraction.kind==='question'/'plan-review'` 从无到有 |
172
- | 任务完成 | `agent/status` running→idle(仅根会话)+`turn/end` 原因 | 摘要 `running:true→false` 且 `retainedBy.mainView` 为空 |
173
- | 任务出错 | `agent/error` | -(host 端覆盖) |
174
-
175
- ## 通道扩展
176
-
177
- 新增第三方通道(钉钉/企业微信/Telegram…)实现 `NotifyChannel` 接口并在
178
- `src/index.ts` 的 `buildChannels()` 注册即可:
179
-
180
- ```ts
181
- export interface NotifyChannel {
182
- readonly id: string
183
- send(payload: NotificationPayload): Promise<void>
184
- }
18
+ dsh plugin --profile web add dsh-messager
19
+ dsh web
185
20
  ```
186
21
 
187
- ## 项目结构
22
+ 如果从 DSH 源码仓库运行,将 `dsh` 换为 `pnpm dsh`。安装后若 DSH 已在运行,请重启。
188
23
 
189
- ```
190
- dsh-messager/
191
- ├── package.json # dsh.bundle + dsh.client 双声明;exports["./client"]
192
- ├── tsconfig.json # host 端(Node)
193
- ├── tsconfig.client.json # client 端声明输出(lib/types/client)
194
- ├── tsdown.config.ts # client bundle(__ModuleLoader__.load 契约)
195
- ├── cordis.yml # 本地开发覆盖层(host 端)
196
- ├── cordis.patch.yml # 分发包配置层(安装后生效)
197
- ├── assets/icon.png # 默认通知图标
198
- ├── doc/plan/ # 规划存档(01 起编号)
199
- ├── src/
200
- │ ├── index.ts # host apply:事件接线 + 通道构建 + 路由挂载(并导出 Config schema)
201
- │ ├── config.ts # Config schema(全字段 .volatile();Loader config 与 settings 共用)
202
- │ ├── config-shared.ts # 配置路由的跨端共享类型(host/client 共用)
203
- │ ├── config-route.ts # webServer 配置路由(GET 视图 / POST ops,同源校验)
204
- │ ├── signals.ts # 事件 → Signal 提取(纯函数)
205
- │ ├── notify.ts # 调度:过滤/冷却/防抖/限流 + NotifyChannel 接口
206
- │ ├── templates.ts # verbosity 模板渲染(纯函数)
207
- │ ├── settings.ts # 条目 id(settings 命名空间)解析,供配置路由使用
208
- │ ├── channels/ # system(node-notifier)、feishu/wecom/discord/dingtalk/telegram(webhook/Bot API+签名)
209
- │ └── client/ # 浏览器端:sessions diff、Notification、设置分区、配置同步
210
- │ ├── index.ts # 分区注册(动态 order)+ 浏览器通知 + 配置路由访问器
211
- │ ├── section.tsx # 设置页「通知&信使」分区组件
212
- │ ├── settings-form.tsx # 共享表单体(分组 + FieldRow + 操作栏)
213
- │ ├── card-controller.ts # 表单控制器(纯逻辑,可单测)
214
- │ ├── fetch-scope.ts # ScopeLike 的 fetch 适配层(配置路由)
215
- │ ├── locales.ts # zh/en 字典(ctx.locale 注册)
216
- │ ├── config.ts # 浏览器通知的配置句柄(走配置路由)
217
- │ └── diff.ts # 完成摘要 / 待交互状态 diff(纯函数)
218
- └── tests/ # vitest 单元测试(147 个)
219
- ```
220
-
221
- ## 测试
24
+ **从源码安装**(开发者可选):
222
25
 
223
26
  ```sh
224
- pnpm test # 147 个单元测试:信号提取/模板/调度/各通道签名与载荷/配置解析与 volatile 契约/client diff/配置路由/fetch scope/字典一致性/表单门控
225
- pnpm typecheck # host 端
226
- pnpm build # host tsc + client 声明 + client bundle(lib/)
27
+ git clone https://github.com/ly6170/dsh-messager.git
28
+ cd dsh-messager
29
+ pnpm install
30
+ pnpm build
31
+ dsh plugin --profile web add .
32
+ dsh web
227
33
  ```
228
34
 
229
- > ⚠️ 测试**不会**投递真实系统通知:`vitest.config.ts` 用 `resolve.alias` 把
230
- > `node-notifier` 换成 no-op 桩(`tests/stubs/node-notifier.ts`)。系统通道的 schema
231
- > 默认值就是 `enabled: true`,不换桩的话 `pnpm test` 会真的弹 Windows toast。
232
-
233
- ## 版本兼容(dsh-messager 0.3.4 / DSH 0.1.7-rc.1)
234
-
235
- - **v0.3.4 支持 DSH `0.1.7-rc.1`**;所有 `@deepseek-ai/dsh-*` peerDependencies 统一写
236
- `^0.1.7-rc.1` **范围**(覆盖整条 0.1.x 线),**不再精确锁单个版本**。
237
- - 该兼容范围不包含 DSH `0.1.7-alpha.1` 及更早版本。仍在使用这些版本的用户,请先将 DSH
238
- 升级到 `0.1.7-rc.1` 或兼容的后续 `0.1.x` 版本,再升级插件;此版本无需迁移插件 API 或重置通知配置。
239
- - ⚠️ **为什么必须用范围**:DSH `0.1.7-rc.1` 起,启动时会读 **bundle 自己的**
240
- `peerDependencies` 做兼容性判定,不通过就**整个 bundle 层被跳过** —— 插件表现为完全
241
- 不加载(配置路由 404、设置页「通知&信使」分区消失、通知全无),只在启动 stderr 留一行
242
- `dsh: skipping profile bundle "dsh-messager"`。v0.3.3 把 peer 精确锁在 `0.1.7-alpha.1`,
243
- rc.1 一发布即 47 条 peer 全数判为不兼容而整体停摆。
244
- - ⚠️ **非 `dsh-` 前缀的配套包**(`cordis` / `cosmokit` / `cordis-plugin-group` /
245
- `cordis-plugin-include` / `cordis-plugin-loader` / `schemastery`)不受该门禁管辖,但必须
246
- 与 DSH 出货版本对齐,否则产生**双实例**:症状是 `pnpm build` 的声明产出报
247
- `TS2883: The inferred type of 'Config' cannot be named without a reference to 'Schema'`
248
- (而 `pnpm typecheck` 却通过,极易误判)。其中 `@deepseek-ai/cordis-plugin-group` 是 rc.1
249
- `dsh-app-boot` 的**必需 peer**,必须显式声明,否则 `pnpm peers check` 报 unmet peer。
250
- - **应急放行**(不改插件、临时让它启动起来,仅救急):门禁支持按「精确插件@版本 × 精确 DSH
251
- 版本」授权,写入 `$DSH_HOME/profiles/<profile>/compatibility.json`:
252
-
253
- ```sh
254
- dsh plugin --profile web allow-version <name>@<version> --dsh-version <exact-dsh> --accept-risk
255
- ```
256
-
257
- 插件每次升版都需重新授权,属救急而非修法 —— 正解仍是把 peer 写成范围。
258
- - client 端适配新版拆分:会话列表来自 `dsh-api-session-controller`,交互状态来自
259
- `dsh-client-ui-session` 的 `ctx.uiSession.sessionStatus`,`ctx.slots` 由
260
- `dsh-client-ui-renderer` 提供;不再依赖已移除的 `dsh-client-runtime`。
261
- - 完成通知仍按会话摘要 `running: true → false` 且不在主视图触发;交互通知仅在
262
- `approval` / `question` / `plan-review` 从无到有时触发,首次订阅只建立基线。
263
- - host 设置使用 profile 条目 id 作为命名空间(本包为 `messager`);配置读写继续走插件
264
- 自有 webServer 路由 `/dsh-messager/config`,现有 schema 与第三方通道配置无需迁移或重置。
265
- - **0.1.7 配置模型迁移**(v0.3.2):移除已不存在的 `ctx.settings.register`;schema 改由
266
- Loader 读取入口导出的 `Config`;全部可编辑字段标记 `.volatile()`;命名空间由
267
- `ctx.fiber.entry.options.id` 动态解析(不再硬编码)。`@deepseek-ai/cordis` 升至
268
- `^4.0.3`(4.0.2 不导出 `Volatile`),`schemastery` 对齐 `^3.18.3`(避免双实例)。
269
- - **v0.3.3**:host 调度器改为**投递时读取 volatile 引用**(不再缓存配置快照,也不再依赖
270
- `settings/document-updated` 的时序),配置一改立即生效;client 端修掉「拉取失败静默开启
271
- 浏览器通知」与「浏览器通道忽略 `triggers.*`」两个缺陷,并在标签页恢复可见时补拉配置。
272
- - **v0.3.4**:适配 DSH `0.1.7-rc.1`。修复 DSH 新增 bundle 兼容性门禁导致的整体停摆
273
- (peer 由精确锁改为 `^0.1.7-rc.1` 范围);顺带把 `schemastery` / `cordis` /
274
- `cordis-plugin-include` / `cordis-plugin-loader` / `cosmokit` 对齐到 rc.1 出货版本以消除
275
- 双实例,并补上 rc.1 `dsh-app-boot` 新增的必需 peer `@deepseek-ai/cordis-plugin-group`。
276
- **宿主端 API 无破坏性变更**:`dsh-settings` / `dsh-host-webserver` / `dsh-client-ui-session` /
277
- `dsh-client-ui-renderer` / `dsh-client-ui-settings` / `dsh-client-ui-slots` 的源码在
278
- alpha.1 → rc.1 之间一行未改,插件逻辑与配置 schema 均无需迁移。
279
-
280
- ## 已知边界
281
-
282
- - 浏览器通知需站点权限;`onlyWhenHidden=false` 时页面可见也会弹。
283
- - 多标签页经 localStorage 冷却去重;不同浏览器各自通知。
284
- - 子代理结束不触发完成通知(仅根会话),避免噪音。
285
- - 通道失败(webhook 超时、toast 不可用)只记日志,不影响其他通道与插件运行。
286
- - 完成/交互的去重状态为内存态,DSH 重启后重置(可接受)。
287
-
288
- ### 系统通知(node-notifier)跨平台前提
289
-
290
- `node-notifier` 在三个平台调用**完全不同的底层程序**,平台差异如下:
35
+ ## 使用
291
36
 
292
- | 平台 | 底层 | 前提条件 / 差异 |
293
- | --- | --- | --- |
294
- | Windows | PowerShell ToastNotification | 内建,无需额外安装;`sound` 仅在 Windows 有可靠映射 |
295
- | macOS | terminal-notifier | 首次使用需**联网下载**第三方二进制,且需登录图形会话(Dock 存在);`sound` 不生效 |
296
- | Linux | notify-send(libnotify) | 需安装 `libnotify-bin`,并有一个**运行中的通知守护进程**(GNOME Shell / Plasma / mako / dunst 等);`sound` 不生效 |
37
+ 打开 DSH 设置页的「通知&信使」分区,选择触发时机、启用通道并填写对应的 webhook 或 Bot 信息,然后保存。系统通知和浏览器通知默认开启;第三方通道默认关闭。浏览器通知还需要授予站点通知权限。
297
38
 
298
- - **图标**:`system.icon` 需是**存在的文件路径**。Windows 对缺失路径多会静默降级,但
299
- Linux/macOS 可能直接报错,故通道层已做存在性校验,无效时降级为不带图标。
300
- - **环境差异不是插件 bug**:Linux 若缺通知守护进程、macOS 若无法联网下载
301
- terminal-notifier 或不在图形会话中,通知可能不弹出或静默失败——此时请先排查上述前提,
302
- 而非插件;失败时调度层会 `logWarn` 记录具体错误。
39
+ 通知只针对需要交互、根会话任务完成和任务出错;运行中的蓝色状态不会触发通知。配置修改保存后即可生效。
303
40
 
304
- ## 后续规划
41
+ ## 常见问题
305
42
 
306
- - 第三方通道扩展:邮件
307
- - 触发扩展:后台 job 完成、goal 轮次完成
308
- - 通知历史、按会话静音、勿扰时段
43
+ - **设置分区未出现或配置路由返回 404**:检查插件是否安装到当前使用的 `web` profile、DSH 是否已重启,以及 DSH 与插件版本是否兼容。
44
+ - **浏览器通知未出现**:检查站点通知权限;默认仅在页面隐藏或失焦时发送。
45
+ - **用 `--patch` 调试时设置不可用**:该模式只加载 host 端。要使用设置页,请通过 `dsh plugin add` 安装。
309
46
 
310
- 规划存档见 `doc/plan/01-通知插件实施规划.md`。
47
+ [v0.3.5 更新说明](RELEASE_NOTES_v0.3.5.md) · [English](README.en.md) · [MIT License](LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-messager",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "DeepSeek Harness 通知插件:会话交互/任务完成/出错时通过系统通知、浏览器通知、飞书/企业微信/Discord/钉钉/Telegram 推送提醒",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -42,53 +42,53 @@
42
42
  "@deepseek-ai/cordis-plugin-include": "^1.0.9",
43
43
  "@deepseek-ai/cordis-plugin-loader": "^1.0.5",
44
44
  "@deepseek-ai/cosmokit": "^1.8.5",
45
- "@deepseek-ai/dsh-agent": "^0.1.7-rc.1",
46
- "@deepseek-ai/dsh-agent-default-model": "^0.1.7-rc.1",
47
- "@deepseek-ai/dsh-agent-preset-registry": "^0.1.7-rc.1",
48
- "@deepseek-ai/dsh-api-gateway": "^0.1.7-rc.1",
49
- "@deepseek-ai/dsh-api-remotes": "^0.1.7-rc.1",
50
- "@deepseek-ai/dsh-api-session-controller": "^0.1.7-rc.1",
51
- "@deepseek-ai/dsh-atomic-write": "^0.1.7-rc.1",
52
- "@deepseek-ai/dsh-attachment": "^0.1.7-rc.1",
53
- "@deepseek-ai/dsh-client-connection": "^0.1.7-rc.1",
54
- "@deepseek-ai/dsh-client-locale": "^0.1.7-rc.1",
55
- "@deepseek-ai/dsh-client-store": "^0.1.7-rc.1",
56
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-rc.1",
57
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-rc.1",
58
- "@deepseek-ai/dsh-client-ui-session": "^0.1.7-rc.1",
59
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.7-rc.1",
60
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.1",
61
- "@deepseek-ai/dsh-commands": "^0.1.7-rc.1",
62
- "@deepseek-ai/dsh-compaction": "^0.1.7-rc.1",
63
- "@deepseek-ai/dsh-cordis-host-runner": "^0.1.7-rc.1",
64
- "@deepseek-ai/dsh-credentials": "^0.1.7-rc.1",
65
- "@deepseek-ai/dsh-file-reference": "^0.1.7-rc.1",
66
- "@deepseek-ai/dsh-goal": "^0.1.7-rc.1",
67
- "@deepseek-ai/dsh-home-paths": "^0.1.7-rc.1",
68
- "@deepseek-ai/dsh-host-plugin-inventory": "^0.1.7-rc.1",
69
- "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1",
70
- "@deepseek-ai/dsh-invariants": "^0.1.7-rc.1",
71
- "@deepseek-ai/dsh-llm": "^0.1.7-rc.1",
72
- "@deepseek-ai/dsh-message-feedback": "^0.1.7-rc.1",
73
- "@deepseek-ai/dsh-native-command": "^0.1.7-rc.1",
74
- "@deepseek-ai/dsh-output-retention": "^0.1.7-rc.1",
75
- "@deepseek-ai/dsh-scope": "^0.1.7-rc.1",
76
- "@deepseek-ai/dsh-session": "^0.1.7-rc.1",
77
- "@deepseek-ai/dsh-session-persistence": "^0.1.7-rc.1",
78
- "@deepseek-ai/dsh-session-projection": "^0.1.7-rc.1",
79
- "@deepseek-ai/dsh-session-query": "^0.1.7-rc.1",
80
- "@deepseek-ai/dsh-session-reference": "^0.1.7-rc.1",
81
- "@deepseek-ai/dsh-session-title": "^0.1.7-rc.1",
82
- "@deepseek-ai/dsh-settings": "^0.1.7-rc.1",
83
- "@deepseek-ai/dsh-skill": "^0.1.7-rc.1",
84
- "@deepseek-ai/dsh-storage": "^0.1.7-rc.1",
85
- "@deepseek-ai/dsh-storage-domain": "^0.1.7-rc.1",
86
- "@deepseek-ai/dsh-subagent": "^0.1.7-rc.1",
87
- "@deepseek-ai/dsh-system-prompt": "^0.1.7-rc.1",
88
- "@deepseek-ai/dsh-tools": "^0.1.7-rc.1",
89
- "@deepseek-ai/dsh-typert-registry": "^0.1.7-rc.1",
90
- "@deepseek-ai/dsh-user-approval": "^0.1.7-rc.1",
91
- "@deepseek-ai/dsh-workspace": "^0.1.7-rc.1",
45
+ "@deepseek-ai/dsh-agent": "^0.2.0-rc.1",
46
+ "@deepseek-ai/dsh-agent-default-model": "^0.2.0-rc.1",
47
+ "@deepseek-ai/dsh-agent-preset-registry": "^0.2.0-rc.1",
48
+ "@deepseek-ai/dsh-api-gateway": "^0.2.0-rc.1",
49
+ "@deepseek-ai/dsh-api-remotes": "^0.2.0-rc.1",
50
+ "@deepseek-ai/dsh-api-session-controller": "^0.2.0-rc.1",
51
+ "@deepseek-ai/dsh-atomic-write": "^0.2.0-rc.1",
52
+ "@deepseek-ai/dsh-attachment": "^0.2.0-rc.1",
53
+ "@deepseek-ai/dsh-client-connection": "^0.2.0-rc.1",
54
+ "@deepseek-ai/dsh-client-locale": "^0.2.0-rc.1",
55
+ "@deepseek-ai/dsh-client-store": "^0.2.0-rc.1",
56
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.1",
57
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.2.0-rc.1",
58
+ "@deepseek-ai/dsh-client-ui-session": "^0.2.0-rc.1",
59
+ "@deepseek-ai/dsh-client-ui-settings": "^0.2.0-rc.1",
60
+ "@deepseek-ai/dsh-client-ui-slots": "^0.2.0-rc.1",
61
+ "@deepseek-ai/dsh-commands": "^0.2.0-rc.1",
62
+ "@deepseek-ai/dsh-compaction": "^0.2.0-rc.1",
63
+ "@deepseek-ai/dsh-cordis-host-runner": "^0.2.0-rc.1",
64
+ "@deepseek-ai/dsh-credentials": "^0.2.0-rc.1",
65
+ "@deepseek-ai/dsh-file-reference": "^0.2.0-rc.1",
66
+ "@deepseek-ai/dsh-goal": "^0.2.0-rc.1",
67
+ "@deepseek-ai/dsh-home-paths": "^0.2.0-rc.1",
68
+ "@deepseek-ai/dsh-host-plugin-inventory": "^0.2.0-rc.1",
69
+ "@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.1",
70
+ "@deepseek-ai/dsh-invariants": "^0.2.0-rc.1",
71
+ "@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
72
+ "@deepseek-ai/dsh-message-feedback": "^0.2.0-rc.1",
73
+ "@deepseek-ai/dsh-native-command": "^0.2.0-rc.1",
74
+ "@deepseek-ai/dsh-output-retention": "^0.2.0-rc.1",
75
+ "@deepseek-ai/dsh-scope": "^0.2.0-rc.1",
76
+ "@deepseek-ai/dsh-session": "^0.2.0-rc.1",
77
+ "@deepseek-ai/dsh-session-persistence": "^0.2.0-rc.1",
78
+ "@deepseek-ai/dsh-session-projection": "^0.2.0-rc.1",
79
+ "@deepseek-ai/dsh-session-query": "^0.2.0-rc.1",
80
+ "@deepseek-ai/dsh-session-reference": "^0.2.0-rc.1",
81
+ "@deepseek-ai/dsh-session-title": "^0.2.0-rc.1",
82
+ "@deepseek-ai/dsh-settings": "^0.2.0-rc.1",
83
+ "@deepseek-ai/dsh-skill": "^0.2.0-rc.1",
84
+ "@deepseek-ai/dsh-storage": "^0.2.0-rc.1",
85
+ "@deepseek-ai/dsh-storage-domain": "^0.2.0-rc.1",
86
+ "@deepseek-ai/dsh-subagent": "^0.2.0-rc.1",
87
+ "@deepseek-ai/dsh-system-prompt": "^0.2.0-rc.1",
88
+ "@deepseek-ai/dsh-tools": "^0.2.0-rc.1",
89
+ "@deepseek-ai/dsh-typert-registry": "^0.2.0-rc.1",
90
+ "@deepseek-ai/dsh-user-approval": "^0.2.0-rc.1",
91
+ "@deepseek-ai/dsh-workspace": "^0.2.0-rc.1",
92
92
  "@deepseek-ai/schemastery": "^3.18.4"
93
93
  },
94
94
  "peerDependenciesMeta": {
@@ -254,20 +254,20 @@
254
254
  },
255
255
  "devDependencies": {
256
256
  "@deepseek-ai/cosmokit": "^1.8.5",
257
- "@deepseek-ai/dsh-agent": "^0.1.7-rc.1",
258
- "@deepseek-ai/dsh-api-remotes": "^0.1.7-rc.1",
259
- "@deepseek-ai/dsh-api-session-controller": "^0.1.7-rc.1",
260
- "@deepseek-ai/dsh-client-locale": "^0.1.7-rc.1",
261
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-rc.1",
262
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-rc.1",
263
- "@deepseek-ai/dsh-client-ui-session": "^0.1.7-rc.1",
264
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.7-rc.1",
265
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.1",
266
- "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1",
267
- "@deepseek-ai/dsh-session": "^0.1.7-rc.1",
268
- "@deepseek-ai/dsh-session-title": "^0.1.7-rc.1",
269
- "@deepseek-ai/dsh-settings": "^0.1.7-rc.1",
270
- "@deepseek-ai/dsh-user-approval": "^0.1.7-rc.1",
257
+ "@deepseek-ai/dsh-agent": "^0.2.0-rc.1",
258
+ "@deepseek-ai/dsh-api-remotes": "^0.2.0-rc.1",
259
+ "@deepseek-ai/dsh-api-session-controller": "^0.2.0-rc.1",
260
+ "@deepseek-ai/dsh-client-locale": "^0.2.0-rc.1",
261
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.1",
262
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.2.0-rc.1",
263
+ "@deepseek-ai/dsh-client-ui-session": "^0.2.0-rc.1",
264
+ "@deepseek-ai/dsh-client-ui-settings": "^0.2.0-rc.1",
265
+ "@deepseek-ai/dsh-client-ui-slots": "^0.2.0-rc.1",
266
+ "@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.1",
267
+ "@deepseek-ai/dsh-session": "^0.2.0-rc.1",
268
+ "@deepseek-ai/dsh-session-title": "^0.2.0-rc.1",
269
+ "@deepseek-ai/dsh-settings": "^0.2.0-rc.1",
270
+ "@deepseek-ai/dsh-user-approval": "^0.2.0-rc.1",
271
271
  "@deepseek-ai/schemastery": "^3.18.4",
272
272
  "@types/node": "^26.2.0",
273
273
  "@types/node-notifier": "^8.0.5",