dsh-slack 0.3.3 → 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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ # 更新记录
2
+
3
+ [返回简介](README.md) · [使用说明](docs/USAGE.md) · [验证记录](docs/VALIDATION.md)
4
+
5
+ [历史英文记录](docs/CHANGELOG.en.md)
6
+
7
+ ## 0.3.5(2026-10-26)
8
+
9
+ - Socket Mode 重连改为插件管理的有界退避;捕获启动与重连错误,凭据撤销等永久错误停止重试,卸载取消重连。自检区分凭据已配置、连接中、连接成功与认证失败。
10
+ - Windows 回归 49 项通过、0 项跳过;宿主与未验收范围见[本次记录](docs/validation-0.3.5.md)。
11
+
12
+ ## 0.3.4 (2026-10-05)
13
+
14
+ - 标记已读只移除本次展示的消息,保留剩余未读与已读重投去重;发送不隐式重试,缺少消息回执时提示先检查频道。
15
+
16
+ ## 0.3.3 (2026-10-01)
17
+
18
+ - 更新并对齐 Socket Mode 的传输依赖,修复依赖解析问题。
19
+
20
+ ## 0.3.0 (2026-08-26)
21
+
22
+ - 新增 `slack_health` 自检(令牌/Socket Mode 配置一键体检);修复只配置部分字段(如只有 token 没有 appToken)时可选链导致的启动崩溃。
23
+
24
+ ## 0.2.3 (2026-08-15)
25
+
26
+ - `slack_channels` 自动分页:频道很多时不再只返回第一页。
27
+ - `slack_inbox` 去重 + `drain` 原子消费:Slack 重投的事件不会重复入队,`markRead` 期间新到的消息也不会被误清。
28
+ - WebClient 复用:同一 `token + slackApiUrl` 只创建一个客户端,减少重复初始化。
29
+ - 分页增加页数上限,防止异常 `next_cursor` 导致死循环。
30
+ - 错误映射补充 `not_authed` / `is_archived` / `msg_too_long` / `ratelimited`。
31
+
32
+ ## 更早的改动
33
+
34
+ 完整历史可查阅 [GitHub 提交记录](https://github.com/STARDUSTLC666/dsh-slack/commits/main)。
package/README.en.md CHANGED
@@ -1,210 +1,48 @@
1
- [中文](README.md)
2
-
3
- ![npm](https://img.shields.io/npm/v/dsh-slack) ![downloads](https://img.shields.io/npm/dm/dsh-slack) ![license](https://img.shields.io/github/license/STARDUSTLC666/dsh-slack) ![stars](https://img.shields.io/github/stars/STARDUSTLC666/dsh-slack?style=social)
4
-
5
1
  # dsh-slack
6
2
 
7
- [![Awesome DSH Plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
8
-
9
- DSH (DeepSeek Harness) community plugin: lets the agent communicate with Slack bidirectionally.
10
-
11
- > **v0.2 scope (two-way)**: v0.1 only did one-way "agent → Slack" notifications; v0.2 adds Socket Mode,
12
- > enabling "Slack message → agent": `slack_inbox` receives messages, `slack_reply` replies in threads.
13
- > RTM and interactive components (buttons/modals/slash command replies) are out of scope for v0.2 — see
14
- > [Known limitations and roadmap](#known-limitations-and-roadmap) below.
15
-
16
- ## Features
17
-
18
- - `slack_notify`: send a Markdown text message to a channel (or thread), returning the message `ts`.
19
- - `slack_channels`: list the channels currently visible to the bot (`conversations.list`, paginating through `next_cursor` until complete).
20
- - `slack_inbox`: read messages received via Socket Mode (in-memory queue, keeps up to 200; deduplicates retries and consumes atomically with `markRead=true`).
21
- - `slack_reply`: reply to an inbox message as a thread (`chat.postMessage` with `thread_ts`).
22
- - WebClient instances are cached by `token + slackApiUrl` and rebuilt automatically when configuration changes.
23
- - Configuration via `cordis.patch.yml`; tokens support environment-variable fallback (`DSH_SLACK_TOKEN` / `DSH_SLACK_APP_TOKEN`).
24
-
25
- ## Changelog
26
-
27
- - **0.3.0**: new `slack_health` self-check (one-call token / Socket Mode config health); fixed a startup crash from optional chaining when only some config fields are set (e.g. token without appToken).
28
- - **0.2.3**:
29
- - `slack_channels` paginates automatically so large workspaces no longer lose channels after the first page.
30
- - `slack_inbox` deduplicates Slack's at-least-once event deliveries and drains atomically on `markRead`.
31
- - WebClient reuse avoids rebuilding clients on every tool call.
32
- - Pagination has a page cap to prevent loops from a misbehaving `next_cursor`.
33
- - Error mapping adds `not_authed` / `is_archived` / `msg_too_long` / `ratelimited`.
34
-
3
+ [中文](README.md)
35
4
 
36
- ## Compatibility
5
+ ![dsh-slack whale girl plugin cover](https://raw.githubusercontent.com/STARDUSTLC666/dsh-slack/main/assets/cover-whale-girl.png)
37
6
 
38
- Validation host: Harness `0.2.0-rc.2` built from its official release tag (commit `639ed01539`), Windows and Node `24.16.0`. All 43 plugin tests pass; all 18 plugins mount together and this plugin registers all five tools, with tool schemas and health-check contracts passing. Real Slack authorization, Socket Mode delivery and sending have not been verified.
7
+ Connect Slack for notifications, a Socket Mode inbox and thread replies.
39
8
 
40
- Version 0.3.3 requires the official Socket Mode SDK 3.1 or newer, which supports Undici 7/8, and explicitly declares its transport dependency. This fixes combined installations that paired an older SDK with the host's Undici 8. Both language versions of this README are included in the npm package.
9
+ [![npm](https://img.shields.io/npm/v/dsh-slack)](https://www.npmjs.com/package/dsh-slack) [![downloads](https://raw.githubusercontent.com/STARDUSTLC666/dsh-suite/npm-downloads/assets/dsh-slack-downloads.svg)](https://www.npmjs.com/package/dsh-slack)
41
10
 
42
- ## Installation
11
+ Feedback and contributions are welcome: report [issues](https://github.com/STARDUSTLC666/dsh-slack/issues) or submit [pull requests](https://github.com/STARDUSTLC666/dsh-slack/pulls).
43
12
 
44
- The plugin runs inside the host process, is installed into the profile via `dsh plugin`, and takes effect after a restart:
13
+ ## What it does
45
14
 
46
- ```sh
47
- dsh plugin --profile web add dsh-slack
48
- ```
15
+ - Send Markdown notifications to channels or threads.
16
+ - List visible channels and read the Socket Mode inbox.
17
+ - Reply in threads and check connection or token configuration.
49
18
 
50
- After installing, restart your dsh Web service; the four tools `slack_notify` / `slack_channels` / `slack_inbox` / `slack_reply` become visible to the model.
19
+ ## Install
51
20
 
52
- ## Uninstall
21
+ In DSH Desktop, install `dsh-slack` from the Plugins panel. If the bundled dsh command is available:
53
22
 
54
23
  ```bash
55
- dsh plugin --profile web remove dsh-slack
56
- ```
57
-
58
- Then restart the web service. To clean up fully, also remove the plugin entry from your profile `cordis.patch.yml` if you overrode it.
59
-
60
-
61
- ## Configuration
62
-
63
- Configuration lives in the profile's `cordis.patch.yml`; override this plugin's line by `id: slack` (overriding replaces that line's `config` wholesale — it does not merge). Available options:
64
-
65
- | Key | Type | Required | Description |
66
- | --- | --- | --- | --- |
67
- | `token` | string | yes* | Slack token: bot token (`xoxb-`) or user token (`xoxp-`). When empty, falls back to the `DSH_SLACK_TOKEN` env var. |
68
- | `appToken` | string | no* | App-Level Token (starts with `xapp-`); used to receive messages after enabling Socket Mode. When empty, falls back to the `DSH_SLACK_APP_TOKEN` env var. |
69
- | `defaultChannel` | string | no | Default channel (e.g. `#general`). The default target when the model doesn't specify a channel; written into the `channel` parameter description. |
70
-
71
- `*` `token` may be left empty at the "config layer", in which case it falls back to the env var; when both are empty the plugin still loads, but calling the send/list/reply tools returns a Chinese error. An empty `appToken` only warns — no crash — and `slack_inbox` returns an empty queue (one-way mode).
72
-
73
- **Method 1: environment variables (recommended, no hard-coded tokens)**
74
-
75
- ```sh
76
- # 在启动 dsh 的进程里设置
77
- export DSH_SLACK_TOKEN=xoxb-你的机器人令牌
78
- export DSH_SLACK_APP_TOKEN=xapp-你的App级令牌
79
- ```
80
-
81
- **Method 2: override in the profile's cordis.patch.yml**
82
-
83
- In your profile directory (`$DSH_HOME/profiles/web/cordis.patch.yml`) append:
84
-
85
- ```yaml
86
- # 覆盖 dsh-slack 的 slack 行配置(整体替换)
87
- - id: slack
88
- config:
89
- token: 'xoxb-你的机器人令牌'
90
- appToken: 'xapp-你的App级令牌'
91
- defaultChannel: '#general'
24
+ dsh plugin --profile desktop add dsh-slack
92
25
  ```
93
26
 
94
- > Priority: `config.token` > env var `DSH_SLACK_TOKEN`; `config.appToken` > env var
95
- > `DSH_SLACK_APP_TOKEN`.
96
-
97
- ### Create a Slack App and get a token
27
+ For the web version, replace `desktop` with `web`. Restart DSH after installation.
98
28
 
99
- 1. Open <https://api.slack.com/apps>, click **Create New App** (choose `From scratch`, name the app, select the workspace).
100
- 2. On the **OAuth & Permissions** page, under **Scopes → Bot Token Scopes** check:
101
- - `chat:write` (required to send messages)
102
- - `channels:read` (required to list channels)
103
- 3. Back at the top, click **Install to Workspace** (authorize).
104
- 4. Grab the **Bot User OAuth Token** (starts with `xoxb-`).
105
- 5. Add the bot (App) to the channels it should post in: `/invite @your-bot` in the channel (required for private channels).
106
-
107
- ### Enable Socket Mode (two-way message receiving)
108
-
109
- To receive Slack messages (`slack_inbox` / `slack_reply`), enable Socket Mode and generate an App-Level Token:
110
-
111
- 1. Open <https://api.slack.com/apps> and open your App.
112
- 2. Open the **Socket Mode** page → turn on the toggle (**Enable Socket Mode**).
113
- 3. Click **Generate Token and Scopes** to create an App-Level Token: name the token, check the `connections:write` scope.
114
- Copy the `xapp-` App-Level Token (shown only once — save it immediately).
115
- 4. Open the **Event Subscriptions** page, enable events, and under **Subscribe to bot events → Add Bot User Event** add:
116
- - `message.channels` (public channel messages)
117
- - `message.im` (bot DMs)
118
- 5. Put the App-Level Token into `appToken` (or the `DSH_SLACK_APP_TOKEN` env var).
119
- 6. Restart the dsh Web service; the plugin connects automatically via Socket Mode and starts receiving messages.
120
-
121
- > Without `appToken` the plugin **won't crash**: it only prints a warning and `slack_inbox` returns an empty queue (with a Chinese hint).
122
- > Socket Mode network errors are auto-reconnected by the SDK; the plugin only logs a warning and never throws.
123
-
124
- ## Tool reference
125
-
126
- ### `slack_notify`
127
-
128
- Send Markdown text to a channel/thread (underlying `chat.postMessage`).
129
-
130
- | Param | Type | Required | Description |
131
- | --- | --- | --- | --- |
132
- | `channel` | string | yes | Channel name (e.g. `#general`) or channel ID. |
133
- | `text` | string | yes | The Markdown text to send. |
134
- | `thread_ts` | string | no | The `ts` of the thread to reply to. |
135
-
136
- Returns: `{ "ts": "...", "channel": "#general" }` (`ts` for later `thread_ts` reference).
137
-
138
- ### `slack_channels`
139
-
140
- List channels visible to the bot (underlying `conversations.list`).
141
-
142
- No parameters. Returns: `{ "channels": [{ "id": "...", "name": "..." }, ...] }`.
143
-
144
- ### `slack_inbox`
145
-
146
- Read messages received via Socket Mode (in-memory queue, keeps up to 200, newest first).
147
-
148
- | Param | Type | Required | Description |
149
- | --- | --- | --- | --- |
150
- | `limit` | integer | no | Maximum number of messages to return (default 10, range 1-50). |
151
- | `markRead` | boolean | no | When `true`, clears the inbox queue after returning (mark as read). |
152
-
153
- Returns: `{ "messages": [{ "ts": "...", "channel": "...", "user": "...", "text": "..." }, ...] }`.
154
-
155
- ### `slack_reply`
156
-
157
- Reply to an inbox message as a thread (underlying `chat.postMessage` with `thread_ts`).
158
-
159
- | Param | Type | Required | Description |
160
- | --- | --- | --- | --- |
161
- | `channel` | string | yes | Channel name (e.g. `#general`) or channel ID. |
162
- | `text` | string | yes | Reply content (Markdown text). |
163
- | `thread_ts` | string | yes | The `ts` of the message to reply to (from `slack_inbox`). |
164
-
165
- Returns: `{ "ts": "...", "channel": "#general" }`.
166
-
167
- ## Error handling
168
-
169
- All error messages are in Chinese, readable by both the model and the user:
170
-
171
- - Unconfigured token: `token 未配置:缺少 Slack 机器人令牌(xoxb-)…请在 profile 的 cordis.patch.yml 覆盖 slack 行的 config.token 并重启,或设置环境变量 DSH_SLACK_TOKEN。`
172
- - Unconfigured App-Level Token: only a warning; `slack_inbox` returns an empty queue (with a Chinese hint) and other tools are unaffected.
173
- - `invalid_auth`: hints to check/regenerate the token.
174
- - `channel_not_found`: hints the channel name or ID is wrong.
175
- - `not_in_channel`: hints to invite the bot App into the channel first.
176
- - `token_revoked` / `account_inactive` / `missing_scope` / `not_authed`: hints permission or token expiry, reinstall the App.
177
- - `is_archived`: hints the channel is archived and cannot receive messages.
178
- - `msg_too_long`: hints the message exceeds Slack's 40,000-character limit.
179
- - `ratelimited`: hints to retry after a short wait.
180
-
181
- ## Development and testing
182
-
183
- ```sh
184
- pnpm install # 安装依赖并触发 prepare(tsc 构建)
185
- pnpm build # tsc 编译 src → lib
186
- pnpm test # 先 build,再用 node:test 跑 test/*.test.mjs
187
- ```
29
+ ## Start using it
188
30
 
189
- Tests need no real token: parameter compilation, config parsing (incl. env fallback), tool registration (4 tools + Chinese error on missing config),
190
- injecting a fake client to assert `postMessage` arguments (incl. `thread_ts`), output schema pure-JSON validation,
191
- inbox queue capacity/clear/deduplication/atomic drain, Socket Mode event parsing (fake event objects), and no-crash on missing appToken.
31
+ Configure your Slack App and tokens, then ask to review the inbox and identify messages that need a reply.
192
32
 
193
- ## Known limitations and roadmap
33
+ ## Requirements and configuration
194
34
 
195
- - **v0.1 is one-way notification (agent→Slack)**; **v0.2 is two-way via Socket Mode** (`slack_inbox` / `slack_reply`).
196
- - **No** RTM or interactive components (buttons/modals/slash command replies).
197
- - `slack_inbox` is an in-process memory queue: cleared on restart, not persisted; keeps up to 200, dropping the oldest when full.
198
- - `channel` is a required parameter; `defaultChannel` is currently only written into the `channel` parameter description as a hint — it does not replace the required `channel`.
199
- - With a missing token the plugin still loads (lazy loading); the error is only thrown when the tool is called; a missing appToken only warns.
35
+ Requires a bot token. Socket Mode also needs an app token and permissions; the inbox is stored in memory.
200
36
 
201
- Roadmap: v0.3 plans to introduce interactive components (buttons/modals) and a persisted inbox.
37
+ Detailed configuration, tool arguments and troubleshooting are in the [usage guide](docs/USAGE.en.md). For standalone development, follow the Node requirement in [package.json](package.json).
202
38
 
203
- ## Dependencies
39
+ ## Documentation
204
40
 
205
- - Runtime: `@slack/web-api` (official WebClient), `@slack/socket-mode` (Socket Mode client)
206
- - peer (provided by the host; not imported directly by the plugin at runtime): `@deepseek-ai/cordis`, `@deepseek-ai/dsh-tools`
41
+ - [Usage and troubleshooting](docs/USAGE.en.md)
42
+ - [Changelog](CHANGELOG.md)
43
+ - [Validation scope and history](docs/VALIDATION.md)
44
+ - [Report a problem or suggest a feature](https://github.com/STARDUSTLC666/dsh-slack/issues)
207
45
 
208
46
  ## License
209
47
 
210
- MIT
48
+ [MIT](LICENSE)
package/README.md CHANGED
@@ -1,214 +1,48 @@
1
- [English](README.en.md)
2
-
3
1
  # dsh-slack
4
2
 
5
- > **让 agent 进你的 Slack**:发消息、看频道、收消息、回线程,双向通信。
6
-
7
- ![npm version](https://img.shields.io/npm/v/dsh-slack?label=npm&color=blue) ![npm downloads](https://img.shields.io/npm/dm/dsh-slack) ![license](https://img.shields.io/npm/l/dsh-slack) ![stars](https://img.shields.io/github/stars/STARDUSTLC666/dsh-slack?style=social)
8
-
9
- [![Awesome DSH Plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
10
-
11
- DSH(DeepSeek Harness)社区插件:让 agent 与 Slack 双向通信。
3
+ [English](README.en.md)
12
4
 
13
- ## 兼容性
5
+ ![dsh-slack 鲸鱼娘插件封面](https://raw.githubusercontent.com/STARDUSTLC666/dsh-slack/main/assets/cover-whale-girl.png)
14
6
 
15
- 验证宿主:官方发布标签源码构建的 Harness `0.2.0-rc.2`(commit `639ed01539`)+ Windows / Node `24.16.0`。43 项插件测试通过;同一个宿主里 18 个插件共同加载,本插件的 5 个工具全部注册,工具 schema 与健康检查契约通过。真实 Slack 登录、Socket Mode 收件和发送尚未验收。
7
+ 连接 Slack,发送通知并处理 Socket Mode 收件箱与线程回复。
16
8
 
17
- 0.3.3 使用支持 Undici 7/8 的官方 Socket Mode SDK 3.1 或更新版本,并显式声明匹配的传输依赖,修复组合安装中旧 SDK 与宿主 Undici 8 的依赖不匹配;npm 包同时包含中英文说明。
9
+ [![npm](https://img.shields.io/npm/v/dsh-slack)](https://www.npmjs.com/package/dsh-slack) [![downloads](https://raw.githubusercontent.com/STARDUSTLC666/dsh-suite/npm-downloads/assets/dsh-slack-downloads.svg)](https://www.npmjs.com/package/dsh-slack)
18
10
 
19
- > **v0.2 范围(双向)**:v0.1 只做「agent → Slack」单向通知;v0.2 新增 Socket Mode,
20
- > 支持「Slack 消息 → agent」:`slack_inbox` 收取消息、`slack_reply` 线程回复。
21
- > RTM、交互组件(按钮/弹窗/slash command 回复)不在 v0.2,见下方
22
- > [已知限制与路线图](#已知限制与路线图)。
11
+ 欢迎使用,遇到问题或有改进建议,请提交 [issues](https://github.com/STARDUSTLC666/dsh-slack/issues) 和 [PR](https://github.com/STARDUSTLC666/dsh-slack/pulls)。
23
12
 
24
13
  ## 功能
25
14
 
26
- - `slack_notify`:向指定频道(或线程)发送一条 Markdown 文本消息,返回消息 `ts`。
27
- - `slack_channels`:列出机器人当前可见的频道(`conversations.list`,自动沿 `next_cursor` 翻页拉全)。
28
- - `slack_inbox`:读取通过 Socket Mode 收到的消息(内存队列,最多保留 200 条;自动去重,`markRead=true` 原子消费)。
29
- - `slack_reply`:以线程回复形式回复某条收件箱消息(`chat.postMessage` 带 `thread_ts`)。
30
- - WebClient 按 `token + slackApiUrl` 缓存复用,配置变更时自动重建。
31
- - 配置走 `cordis.patch.yml`,令牌支持环境变量回退(`DSH_SLACK_TOKEN` / `DSH_SLACK_APP_TOKEN`)。
32
-
33
- ## 版本记录
34
-
35
- - **0.3.0**:新增 `slack_health` 自检(令牌/Socket Mode 配置一键体检);修复只配置部分字段(如只有 token 没有 appToken)时可选链导致的启动崩溃。
36
- - **0.2.3**:
37
- - `slack_channels` 自动分页:频道很多时不再只返回第一页。
38
- - `slack_inbox` 去重 + `drain` 原子消费:Slack 重投的事件不会重复入队,`markRead` 期间新到的消息也不会被误清。
39
- - WebClient 复用:同一 `token + slackApiUrl` 只创建一个客户端,减少重复初始化。
40
- - 分页增加页数上限,防止异常 `next_cursor` 导致死循环。
41
- - 错误映射补充 `not_authed` / `is_archived` / `msg_too_long` / `ratelimited`。
15
+ - 向频道或线程发送 Markdown 通知。
16
+ - 读取机器人可见频道和 Socket Mode 收件箱。
17
+ - 回复线程,按配置检查连接与令牌。
42
18
 
43
19
  ## 安装
44
20
 
45
- 插件运行在宿主进程内,通过 `dsh plugin` 安装进 profile,重启后生效:
46
-
47
- ```sh
48
- dsh plugin --profile web add dsh-slack
49
- ```
50
-
51
- 安装后重启你的 dsh Web 服务,`slack_notify` / `slack_channels` / `slack_inbox` / `slack_reply`
52
- 四个工具即对模型可见。
53
-
54
- ## 配置
55
-
56
- 配置在 profile 的 `cordis.patch.yml` 里按 `id: slack` 覆盖本插件的行(覆盖会整体替换该行的
57
- `config`,不会合并)。可用配置项:
58
-
59
- | 键 | 类型 | 必填 | 说明 |
60
- | --- | --- | --- | --- |
61
- | `token` | string | 是* | Slack 令牌:机器人令牌(`xoxb-`)或用户令牌(`xoxp-`)。留空时回退到环境变量 `DSH_SLACK_TOKEN`。 |
62
- | `appToken` | string | 否* | App-Level Token(`xapp-` 开头),开启 Socket Mode 后用于接收消息。留空时回退到环境变量 `DSH_SLACK_APP_TOKEN`。 |
63
- | `defaultChannel` | string | 否 | 默认频道(如 `#general`)。模型未特别指定频道时的默认目标,写进 `channel` 参数说明里。 |
64
-
65
- `*` `token` 在「配置层」可留空,此时回退环境变量;两者都为空时插件照常加载,但调用发消息/列频道/
66
- 回复工具时会返回中文报错。`appToken` 留空则只告警、不崩溃,`slack_inbox` 返回空队列(单向模式)。
67
-
68
- **方式一:环境变量(推荐,不写死令牌)**
69
-
70
- ```sh
71
- # 在启动 dsh 的进程里设置
72
- export DSH_SLACK_TOKEN=xoxb-你的机器人令牌
73
- export DSH_SLACK_APP_TOKEN=xapp-你的App级令牌
74
- ```
75
-
76
- **方式二:profile 的 cordis.patch.yml 直接覆盖**
77
-
78
- 在你的 profile 目录(`$DSH_HOME/profiles/web/cordis.patch.yml`)追加:
79
-
80
- ```yaml
81
- # 覆盖 dsh-slack 的 slack 行配置(整体替换)
82
- - id: slack
83
- config:
84
- token: 'xoxb-你的机器人令牌'
85
- appToken: 'xapp-你的App级令牌'
86
- defaultChannel: '#general'
87
- ```
88
-
89
- > 优先级:`config.token` > 环境变量 `DSH_SLACK_TOKEN`;`config.appToken` > 环境变量
90
- > `DSH_SLACK_APP_TOKEN`。
91
-
92
- ### 创建 Slack App 并拿令牌
93
-
94
- 1. 打开 <https://api.slack.com/apps>,点 **Create New App**(选 `From scratch`,给 App 起名、选工作区)。
95
- 2. 进入 **OAuth & Permissions** 页,在 **Scopes → Bot Token Scopes** 下勾选:
96
- - `chat:write`(发消息必需)
97
- - `channels:read`(列频道必需)
98
- 3. 回到顶部点 **Install to Workspace**(授权)。
99
- 4. 拿到 **Bot User OAuth Token**(以 `xoxb-` 开头)。
100
- 5. 把机器人(App)加进它要发消息的频道:在频道里 `/invite @你的机器人`(私有频道必需)。
101
-
102
- ### 开启 Socket Mode(双向收消息)
103
-
104
- 要接收 Slack 消息(`slack_inbox` / `slack_reply`),需要开启 Socket Mode 并生成 App-Level Token:
105
-
106
- 1. 打开 <https://api.slack.com/apps>,进入你的 App。
107
- 2. 左侧 **Socket Mode** 页 → 打开开关(**Enable Socket Mode**)。
108
- 3. 点 **Generate Token and Scopes** 生成 App-Level Token:给 Token 起名,勾选 `connections:write` scope。
109
- 生成后拿到以 `xapp-` 开头的 App-Level Token(只显示一次,请立即保存)。
110
- 4. 进入 **Event Subscriptions** 页,开启事件订阅,在 **Subscribe to bot events → Add Bot User Event** 添加:
111
- - `message.channels`(公开频道消息)
112
- - `message.im`(机器人私信)
113
- 5. 把 App-Level Token 配进 `appToken`(或环境变量 `DSH_SLACK_APP_TOKEN`)。
114
- 6. 重启 dsh Web 服务,插件自动通过 Socket Mode 建立连接并开始收消息。
115
-
116
- > 未配置 `appToken` 时插件**不会崩溃**:只打印告警,`slack_inbox` 返回空队列(中文提示)。
117
- > Socket Mode 网络错误由 SDK 自动重连,插件只记录告警、不抛崩。
118
-
119
- ## 卸载
21
+ 桌面版可在「插件」面板按包名 `dsh-slack` 安装。已配置 dsh 命令时也可使用:
120
22
 
121
23
  ```bash
122
- dsh plugin --profile web remove dsh-slack
24
+ dsh plugin --profile desktop add dsh-slack
123
25
  ```
124
26
 
125
- 卸载后重启 Web 服务。如需彻底清理,可再手动删除自己 profile `cordis.patch.yml` 中的对应插件行。
126
-
127
- ## 工具清单
128
-
129
- ### `slack_notify`
130
-
131
- 向指定频道/线程发送 Markdown 文本(底层 `chat.postMessage`)。
132
-
133
- | 参数 | 类型 | 必填 | 说明 |
134
- | --- | --- | --- | --- |
135
- | `channel` | string | 是 | 频道名(如 `#general`)或频道 ID。 |
136
- | `text` | string | 是 | 要发送的 Markdown 文本。 |
137
- | `thread_ts` | string | 否 | 回复某条消息所在线程的 `ts`。 |
138
-
139
- 返回:`{ "ts": "...", "channel": "#general" }`(`ts` 供后续 `thread_ts` 引用)。
140
-
141
- ### `slack_channels`
142
-
143
- 列出机器人可见频道(底层 `conversations.list`)。
144
-
145
- 无参数。返回:`{ "channels": [{ "id": "...", "name": "..." }, ...] }`。
146
-
147
- ### `slack_inbox`
27
+ 网页版把命令中的 `desktop` 改为 `web`。安装后重启 DSH。
148
28
 
149
- 读取通过 Socket Mode 收到的消息(内存队列,最多保留 200 条,新的在前)。
150
-
151
- | 参数 | 类型 | 必填 | 说明 |
152
- | --- | --- | --- | --- |
153
- | `limit` | integer | 否 | 最多返回的消息数(默认 10,范围 1-50)。 |
154
- | `markRead` | boolean | 否 | 为 `true` 时,返回后清空收件箱队列(标记已读)。 |
155
-
156
- 返回:`{ "messages": [{ "ts": "...", "channel": "...", "user": "...", "text": "..." }, ...] }`。
157
-
158
- ### `slack_reply`
159
-
160
- 以线程回复形式回复某条收件箱消息(底层 `chat.postMessage` 带 `thread_ts`)。
161
-
162
- | 参数 | 类型 | 必填 | 说明 |
163
- | --- | --- | --- | --- |
164
- | `channel` | string | 是 | 频道名(如 `#general`)或频道 ID。 |
165
- | `text` | string | 是 | 回复内容(Markdown 文本)。 |
166
- | `thread_ts` | string | 是 | 要回复消息的 `ts`(来自 `slack_inbox` 返回的 `ts`)。 |
167
-
168
- 返回:`{ "ts": "...", "channel": "#general" }`。
169
-
170
- ## 错误处理
171
-
172
- 所有错误信息均为中文,模型与用户都能直接读懂:
173
-
174
- - 未配置令牌:`token 未配置:缺少 Slack 机器人令牌(xoxb-)…请在 profile 的 cordis.patch.yml 覆盖 slack 行的 config.token 并重启,或设置环境变量 DSH_SLACK_TOKEN。`
175
- - 未配置 App-Level Token:只告警,`slack_inbox` 返回空队列(含中文提示),不影响其它工具。
176
- - `invalid_auth`:提示检查/重新生成 token。
177
- - `channel_not_found`:提示频道名或频道 ID 错误。
178
- - `not_in_channel`:提示先把机器人 App 邀请进频道。
179
- - `token_revoked` / `account_inactive` / `missing_scope` / `not_authed`:提示权限或令牌失效,需重新安装 App。
180
- - `is_archived`:提示频道已归档,不能发消息。
181
- - `msg_too_long`:提示 Slack 单条消息超过 40,000 字符。
182
- - `ratelimited`:提示请求太频繁,稍后重试。
183
-
184
- ## 开发与测试
185
-
186
- ```sh
187
- pnpm install # 安装依赖并触发 prepare(tsc 构建)
188
- pnpm build # tsc 编译 src → lib
189
- pnpm test # 先 build,再用 node:test 跑 test/*.test.mjs
190
- ```
29
+ ## 开始使用
191
30
 
192
- 测试无需真实 token:参数编译、配置解析(含 env 回退)、工具注册(4 个工具 + 缺配置中文报错)、
193
- 注入 fake client 断言 `postMessage` 参数(含 `thread_ts`)、输出 schema 纯 JSON 校验、
194
- 收件箱队列容量/清空/去重/原子 drain、Socket Mode 事件解析(fake event 对象)、appToken 缺失不崩。
31
+ 配置 Slack App 和令牌后,可说:“查看 Slack 收件箱,整理需要回复的消息。”
195
32
 
196
- ## 已知限制与路线图
33
+ ## 依赖与配置
197
34
 
198
- - **v0.1 是单向通知(agent→Slack)**;**v0.2 通过 Socket Mode 实现双向**(`slack_inbox` / `slack_reply`)。
199
- - **不支持** RTM、交互组件(按钮/弹窗/slash command 回复)。
200
- - `slack_inbox` 为进程内存队列:重启即清空,且不持久化;最多保留 200 条,满则丢最旧。
201
- - `channel` 为必填参数,`defaultChannel` 目前只作为说明提示写入 `channel` 参数描述,不替代
202
- 必填的 `channel`。
203
- - 令牌缺失时插件仍会加载(懒加载),错误在工具被调用时才抛出;appToken 缺失则仅告警。
35
+ 需要 Bot Token。Socket Mode 收消息还需要 App Token 与相应权限;收件箱在内存中保存。
204
36
 
205
- 路线图:v0.3 计划引入交互组件(按钮/弹窗)与持久化收件箱。
37
+ 详细配置、工具参数与排错见[使用说明](docs/USAGE.md)。从源码独立开发时,Node 要求以 [package.json](package.json) 为准。
206
38
 
207
- ## 依赖
39
+ ## 文档
208
40
 
209
- - 运行时:`@slack/web-api`(官方 WebClient)、`@slack/socket-mode`(Socket Mode 客户端)
210
- - peer(由宿主提供,插件运行时不直接 import):`@deepseek-ai/cordis`、`@deepseek-ai/dsh-tools`
41
+ - [使用与排错](docs/USAGE.md)
42
+ - [更新记录](CHANGELOG.md)
43
+ - [验证范围与历史记录](docs/VALIDATION.md)
44
+ - [问题反馈与功能建议](https://github.com/STARDUSTLC666/dsh-slack/issues)
211
45
 
212
46
  ## License
213
47
 
214
- MIT
48
+ [MIT](LICENSE)
@@ -0,0 +1,21 @@
1
+ # Historical release notes
2
+
3
+ [Current changelog](../CHANGELOG.md) · [Overview](../README.en.md)
4
+
5
+ These English notes preserve the earlier translations. The main changelog contains the consolidated version history.
6
+
7
+ ## 0.3.4 (2026-10-05)
8
+
9
+ - Mark only displayed inbox messages as read, preserving unread entries and retry deduplication. Disable implicit send retries; missing receipts prompt channel inspection.
10
+
11
+ ## 0.3.0 (2026-08-26)
12
+
13
+ - new `slack_health` self-check (one-call token / Socket Mode config health); fixed a startup crash from optional chaining when only some config fields are set (e.g. token without appToken).
14
+
15
+ ## 0.2.3 (2026-08-15)
16
+
17
+ - `slack_channels` paginates automatically so large workspaces no longer lose channels after the first page.
18
+ - `slack_inbox` deduplicates Slack's at-least-once event deliveries and drains atomically on `markRead`.
19
+ - WebClient reuse avoids rebuilding clients on every tool call.
20
+ - Pagination has a page cap to prevent loops from a misbehaving `next_cursor`.
21
+ - Error mapping adds `not_authed` / `is_archived` / `msg_too_long` / `ratelimited`.