@zhin.js/adapter-slack 4.0.1 → 4.1.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +207 -98
  3. package/{skills/slack/SKILL.md → agent/skills/slack.md} +2 -0
  4. package/agent/tools/add_reaction.ts +26 -0
  5. package/agent/tools/archive_channel.ts +24 -0
  6. package/agent/tools/edit_message.ts +27 -0
  7. package/agent/tools/invite_to_channel.ts +26 -0
  8. package/agent/tools/pin_message.ts +26 -0
  9. package/agent/tools/remove_reaction.ts +26 -0
  10. package/agent/tools/set_purpose.ts +26 -0
  11. package/agent/tools/set_topic.ts +26 -0
  12. package/agent/tools/unarchive.ts +24 -0
  13. package/agent/tools/unpin_message.ts +26 -0
  14. package/agent/tools/user_info.ts +31 -0
  15. package/lib/agent/tools/add_reaction.js +21 -0
  16. package/lib/agent/tools/add_reaction.js.map +1 -0
  17. package/lib/agent/tools/archive_channel.js +21 -0
  18. package/lib/agent/tools/archive_channel.js.map +1 -0
  19. package/lib/agent/tools/edit_message.js +22 -0
  20. package/lib/agent/tools/edit_message.js.map +1 -0
  21. package/lib/agent/tools/invite_to_channel.js +22 -0
  22. package/lib/agent/tools/invite_to_channel.js.map +1 -0
  23. package/lib/agent/tools/pin_message.js +22 -0
  24. package/lib/agent/tools/pin_message.js.map +1 -0
  25. package/lib/agent/tools/remove_reaction.js +21 -0
  26. package/lib/agent/tools/remove_reaction.js.map +1 -0
  27. package/lib/agent/tools/set_purpose.js +22 -0
  28. package/lib/agent/tools/set_purpose.js.map +1 -0
  29. package/lib/agent/tools/set_topic.js +22 -0
  30. package/lib/agent/tools/set_topic.js.map +1 -0
  31. package/lib/agent/tools/unarchive.js +21 -0
  32. package/lib/agent/tools/unarchive.js.map +1 -0
  33. package/lib/agent/tools/unpin_message.js +22 -0
  34. package/lib/agent/tools/unpin_message.js.map +1 -0
  35. package/lib/agent/tools/user_info.js +28 -0
  36. package/lib/agent/tools/user_info.js.map +1 -0
  37. package/lib/{adapter.js → src/adapter.js} +19 -3
  38. package/lib/src/adapter.js.map +1 -0
  39. package/lib/src/endpoint.js +312 -0
  40. package/lib/src/endpoint.js.map +1 -0
  41. package/lib/src/event-dispatcher.js +233 -0
  42. package/lib/src/event-dispatcher.js.map +1 -0
  43. package/lib/src/index.js +51 -0
  44. package/lib/src/index.js.map +1 -0
  45. package/lib/src/markdown-to-mrkdwn.js +61 -0
  46. package/lib/src/markdown-to-mrkdwn.js.map +1 -0
  47. package/lib/src/mrkdwn-to-markdown.js +31 -0
  48. package/lib/src/mrkdwn-to-markdown.js.map +1 -0
  49. package/lib/{platform-permit.js → src/platform-permit.js} +3 -0
  50. package/lib/src/platform-permit.js.map +1 -0
  51. package/lib/src/segment-mapper.js.map +1 -0
  52. package/lib/src/signing.js +21 -0
  53. package/lib/src/signing.js.map +1 -0
  54. package/lib/src/slack-agent-deps.js +10 -0
  55. package/lib/src/slack-agent-deps.js.map +1 -0
  56. package/lib/src/slack-inbound-filter.js +47 -0
  57. package/lib/src/slack-inbound-filter.js.map +1 -0
  58. package/lib/src/slack-inbound.js +127 -0
  59. package/lib/src/slack-inbound.js.map +1 -0
  60. package/lib/src/slack-message-ref.js +18 -0
  61. package/lib/src/slack-message-ref.js.map +1 -0
  62. package/lib/src/slack-outbound.js +223 -0
  63. package/lib/src/slack-outbound.js.map +1 -0
  64. package/lib/src/slack-reaction.js +27 -0
  65. package/lib/src/slack-reaction.js.map +1 -0
  66. package/lib/src/slack-response-url.js +17 -0
  67. package/lib/src/slack-response-url.js.map +1 -0
  68. package/lib/src/slack-side-events.js +64 -0
  69. package/lib/src/slack-side-events.js.map +1 -0
  70. package/lib/src/transport-http.js +83 -0
  71. package/lib/src/transport-http.js.map +1 -0
  72. package/lib/src/transport-socket.js +68 -0
  73. package/lib/src/transport-socket.js.map +1 -0
  74. package/lib/src/types.js +5 -0
  75. package/lib/src/types.js.map +1 -0
  76. package/package.json +24 -6
  77. package/src/adapter.ts +28 -7
  78. package/src/endpoint.ts +206 -604
  79. package/src/event-dispatcher.ts +255 -0
  80. package/src/index.ts +31 -239
  81. package/src/markdown-to-mrkdwn.ts +58 -0
  82. package/src/mrkdwn-to-markdown.ts +29 -0
  83. package/src/platform-permit.ts +1 -2
  84. package/src/signing.ts +28 -0
  85. package/src/slack-agent-deps.ts +22 -0
  86. package/src/slack-inbound-filter.ts +60 -0
  87. package/src/slack-inbound.ts +140 -0
  88. package/src/slack-message-ref.ts +18 -0
  89. package/src/slack-outbound.ts +269 -0
  90. package/src/slack-reaction.ts +23 -0
  91. package/src/slack-response-url.ts +26 -0
  92. package/src/slack-side-events.ts +74 -0
  93. package/src/transport-http.ts +95 -0
  94. package/src/transport-socket.ts +77 -0
  95. package/src/types.ts +99 -4
  96. package/lib/adapter.d.ts +0 -19
  97. package/lib/adapter.d.ts.map +0 -1
  98. package/lib/adapter.js.map +0 -1
  99. package/lib/endpoint.d.ts +0 -108
  100. package/lib/endpoint.d.ts.map +0 -1
  101. package/lib/endpoint.js +0 -677
  102. package/lib/endpoint.js.map +0 -1
  103. package/lib/index.d.ts +0 -10
  104. package/lib/index.d.ts.map +0 -1
  105. package/lib/index.js +0 -252
  106. package/lib/index.js.map +0 -1
  107. package/lib/platform-permit.d.ts +0 -17
  108. package/lib/platform-permit.d.ts.map +0 -1
  109. package/lib/platform-permit.js.map +0 -1
  110. package/lib/segment-mapper.d.ts +0 -2
  111. package/lib/segment-mapper.d.ts.map +0 -1
  112. package/lib/segment-mapper.js.map +0 -1
  113. package/lib/types.d.ts +0 -17
  114. package/lib/types.d.ts.map +0 -1
  115. package/lib/types.js +0 -2
  116. package/lib/types.js.map +0 -1
  117. /package/{skills/slack → agent}/PERMITS.md +0 -0
  118. /package/lib/{segment-mapper.js → src/segment-mapper.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 872c583: Slack 适配器 Phase 1/2:mrkdwn 出站、长消息切分、斜杠/按钮 ephemeral 反馈、入站 mrkdwn→Markdown、editMessage 对齐 core。
8
+
9
+ Logger 表格日志与 string-width 列宽;Agent AI Handler 框线表格与 introspection/MCP 导出;Core side-event 归一化;Schedule 时区规划;多适配器 side-event 与 API surface 更新。
10
+
11
+ ### Patch Changes
12
+
13
+ - 872c583: fix: 代码格式优化
14
+ - Updated dependencies [872c583]
15
+ - Updated dependencies [872c583]
16
+ - @zhin.js/agent@1.0.3
17
+ - @zhin.js/host-router@2.0.3
18
+ - @zhin.js/logger@1.0.74
19
+ - zhin.js@4.1.2
20
+
3
21
  ## 4.0.1
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -1,32 +1,27 @@
1
1
  # @zhin.js/adapter-slack
2
2
 
3
- Slack adapter for zhin.js framework.
3
+ Zhin.js 的 Slack 适配器,支持消息收发、Block Kit 交互与 Assistant API。
4
4
 
5
- ## Installation
5
+ ## 安装
6
6
 
7
7
  ```bash
8
8
  pnpm add @zhin.js/adapter-slack
9
9
  ```
10
10
 
11
- ## Configuration
11
+ ## 配置
12
12
 
13
- 通过 **`socketMode`** 选择连接方式(默认 `true` 时为 Socket Mode)。
13
+ 通过 **`socketMode`** 选择连接方式。
14
14
 
15
15
  ### 模式对比
16
16
 
17
17
  | 模式 | `socketMode` | 适用场景 | 额外字段 |
18
18
  |------|--------------|----------|----------|
19
19
  | **Socket Mode** | `true`(推荐本地/内网) | 无需公网 URL,WebSocket 长连接 | `appToken`(`xapp-...`) |
20
- | **HTTP Events** | `false` | 生产环境,有公网 HTTPS | `port`(Bolt 监听端口) |
20
+ | **HTTP Events** | `false` | 生产环境,有公网 HTTPS | 共享 zhin router 端口 8086 |
21
21
 
22
- #### HTTP 模式前置条件
22
+ ### Socket Mode(推荐开发环境)
23
23
 
24
- - Slack App 中配置 **Event Subscriptions** Request URL(须公网 HTTPS 可达)
25
- - 启用对应 Endpoint Events(`message.*`、`app_mention` 等)
26
- - 防火墙 / 反向代理放行 `port`
27
- - **不需要** `@zhin.js/host-router`(由 `@slack/bolt` 自行监听)
28
-
29
- ### Socket Mode (Recommended for Development)
24
+ 可选 `clientPingTimeout`(毫秒,默认 `15000`)用于调整 Socket Mode 客户端心跳超时,减少误报 pong 警告。
30
25
 
31
26
  ```typescript
32
27
  import { defineConfig } from 'zhin.js'
@@ -45,7 +40,9 @@ export default defineConfig({
45
40
  })
46
41
  ```
47
42
 
48
- ### HTTP Mode (For Production with Public URL)
43
+ ### HTTP 模式(生产环境,使用 zhin Router)
44
+
45
+ HTTP 模式共享 zhin.js 内置的 Koa Router(默认端口 8086),无需额外监听端口。
49
46
 
50
47
  ```typescript
51
48
  import { defineConfig } from 'zhin.js'
@@ -57,60 +54,128 @@ export default defineConfig({
57
54
  context: 'slack',
58
55
  token: 'xoxb-your-bot-token',
59
56
  signingSecret: 'your-signing-secret',
60
- socketMode: false,
61
- port: 3000
57
+ socketMode: false
62
58
  }
63
59
  ]
64
60
  })
65
61
  ```
66
62
 
67
- ## Features
68
-
69
- - Send and receive text messages
70
- - Support for rich media (images, files)
71
- - Message formatting (Slack mrkdwn)
72
- - Reply to messages and threads
73
- - ✅ Mentions (@user, #channel)
74
- - ✅ Links and attachments
75
- - ✅ Socket Mode and HTTP mode
76
- - ✅ Private messages and channels
77
-
78
- ## Setting Up Your Slack App
79
-
80
- 1. Go to [Slack API](https://api.slack.com/apps)
81
- 2. Create a new app
82
- 3. Add Endpoint Token Scopes:
83
- - `chat:write` - Send messages
84
- - `chat:write.public` - Send messages to public channels
85
- - `channels:read` - View basic channel info
86
- - `channels:history` - View messages in channels
87
- - `groups:read` - View basic private channel info
88
- - `groups:history` - View messages in private channels
89
- - `im:read` - View basic direct message info
90
- - `im:history` - View messages in direct messages
91
- - `mpim:read` - View basic group direct message info
92
- - `mpim:history` - View messages in group direct messages
93
- - `users:read` - View user info
94
- - `files:read` - View files
95
- - `files:write` - Upload files
96
- 4. Enable Socket Mode (if using Socket Mode):
97
- - Go to Socket Mode settings
98
- - Enable Socket Mode
99
- - Generate an app-level token with `connections:write` scope
100
- 5. Subscribe to events:
101
- - `message.channels` - Messages in public channels
102
- - `message.groups` - Messages in private channels
103
- - `message.im` - Direct messages
104
- - `message.mpim` - Group direct messages
105
- - `app_mention` - When the bot is mentioned
106
- 6. Install the app to your workspace
107
- 7. Copy the Endpoint User OAuth Token (`xoxb-...`)
108
- 8. Copy the Signing Secret
109
- 9. Copy the App-Level Token (`xapp-...`) if using Socket Mode
110
-
111
- ## Usage Examples
112
-
113
- ### Basic Message Handling
63
+ **HTTP 模式前置条件:**
64
+
65
+ - Slack App 中配置 **Event Subscriptions** 的 Request URL 为 `https://your-domain:8086/slack/events`
66
+ - 配置 **Interactivity & Shortcuts** Request URL 为同一地址
67
+ - 配置 **Slash Commands** Request URL 为同一地址
68
+ - 防火墙 / 反向代理放行端口
69
+
70
+ ## 功能特性
71
+
72
+ - 收发文本消息
73
+ - 富媒体(图片、文件),经 `files.uploadV2` 上传
74
+ - 消息格式化(Slack mrkdwn + Block Kit)
75
+ - 回复消息与线程(`thread_ts`)
76
+ - 提及(@用户、#频道)
77
+ - 链接与附件
78
+ - Socket Mode HTTP 模式(共享 zhin router)
79
+ - 私信与频道消息
80
+ - Block Kit 交互按钮(`keyboard` 片段 原生 Slack 按钮)
81
+ - 斜杠命令 zhin Command 映射
82
+ - 消息编辑(`$editMessage` / `chat.update`)
83
+ - Notice 事件映射(`member_joined`、`reaction_added`、`pin_added` 等)
84
+ - Assistant API 支持(`assistant_thread_started` 事件)
85
+ - 出站 Markdown Slack mrkdwn 自动转换(`**粗体**` → `*粗体*`)
86
+ - 长消息自动分段(超 2900 字符切 section;超 48 blocks 分多条发送)
87
+ - 斜杠命令即时 ephemeral 反馈(「处理中…」);最终回复仍 `chat.postMessage`
88
+ - 按钮点击即时 ephemeral 反馈(「已收到」)
89
+ - 入站 Slack mrkdwn 通用 Markdown(粗体/斜体/删除线/代码/链接)
90
+
91
+ ## 消息格式
92
+
93
+ ### 出站(Markdown mrkdwn)
94
+
95
+ AI 或命令输出的通用 Markdown(如 `**粗体**`、`*斜体*`)会自动转换为 Slack mrkdwn,并通过 Block Kit `section` 块发送,确保在 Slack 客户端正确渲染。
96
+
97
+ ### 长消息
98
+
99
+ - 单条 `section` 文本超过约 2900 字符时自动切分为多个 section
100
+ - 单条消息 blocks 超过 48 个时自动拆分为多条 `chat.postMessage`
101
+
102
+ ### 入站(mrkdwn Markdown)
103
+
104
+ 用户发送的 Slack mrkdwn 在解析为 `text` 段前会转换为通用 Markdown:
105
+
106
+ | Slack mrkdwn | 通用 Markdown |
107
+ |--------------|---------------|
108
+ | `*bold*` | `**bold**` |
109
+ | `_italic_` | `*italic*` |
110
+ | `~strike~` | `~~strike~~` |
111
+ | `` `code` `` | 保持 |
112
+ | `<url\|text>` | `[text](url)` |
113
+
114
+ `<@U>` / `<#C>` 等特殊段仍由专用解析器处理,不在此转换。该转换为启发式,复杂嵌套格式不保证完美往返。
115
+
116
+ ## 交互反馈
117
+
118
+ ### 斜杠命令
119
+
120
+ 收到斜杠命令后,适配器会立即向触发者发送 ephemeral「处理中…」(仅触发者可见)。命令处理完成后的最终回复仍通过 `chat.postMessage` 发送到频道,与现有 `$reply` 行为一致。
121
+
122
+ ### Block Kit 按钮
123
+
124
+ 用户点击 `block_actions` 按钮后,适配器会向点击者发送 ephemeral「已收到」。如需在线程中回复,仍通过 `sendMessage`(`thread_ts`)发送。
125
+
126
+ ## 创建 Slack App
127
+
128
+ 1. 前往 [Slack API](https://api.slack.com/apps)
129
+ 2. 创建新应用
130
+ 3. 添加 Bot Token Scopes:
131
+ - `chat:write` — 发送消息
132
+ - `chat:write.public` — 向公开频道发送消息
133
+ - `channels:read` — 查看频道基本信息
134
+ - `channels:history` — 查看频道消息历史
135
+ - `channels:manage` — 管理频道
136
+ - `groups:read` — 查看私有频道基本信息
137
+ - `groups:history` — 查看私有频道消息历史
138
+ - `im:read` — 查看私信基本信息
139
+ - `im:history` — 查看私信消息历史
140
+ - `mpim:read` — 查看群组私信基本信息
141
+ - `mpim:history` — 查看群组私信消息历史
142
+ - `users:read` — 查看用户信息
143
+ - `files:read` — 查看文件
144
+ - `files:write` — 上传文件
145
+ - `reactions:read` — 查看表情回应
146
+ - `reactions:write` — 添加/移除表情回应
147
+ - `pins:read` — 查看置顶项
148
+ - `pins:write` — 置顶/取消置顶消息
149
+ - `commands` — 添加斜杠命令
150
+ - `assistant:write` — Assistant API(若使用 AI 功能)
151
+ 4. 启用 Socket Mode(若使用 Socket Mode):
152
+ - 进入 Socket Mode 设置
153
+ - 启用 Socket Mode
154
+ - 生成带 `connections:write` scope 的应用级 Token
155
+ 5. 订阅 Bot 事件:
156
+ - `message.channels` — 公开频道消息
157
+ - `message.groups` — 私有频道消息
158
+ - `message.im` — 私信
159
+ - `message.mpim` — 群组私信
160
+ - `app_mention` — Bot 被 @ 提及时
161
+ - `member_joined_channel` — 用户加入频道
162
+ - `member_left_channel` — 用户离开频道
163
+ - `reaction_added` — 添加表情回应
164
+ - `reaction_removed` — 移除表情回应
165
+ - `channel_archive` / `channel_unarchive`
166
+ - `channel_rename` / `channel_created` / `channel_deleted`
167
+ - `pin_added` / `pin_removed`
168
+ - `team_join` — 新用户加入工作区
169
+ - `assistant_thread_started`(若使用 Assistant API)
170
+ - `assistant_thread_context_changed`(若使用 Assistant API)
171
+ 6. 将应用安装到工作区
172
+ 7. 复制 Bot User OAuth Token(`xoxb-...`)
173
+ 8. 复制 Signing Secret
174
+ 9. 若使用 Socket Mode,复制 App-Level Token(`xapp-...`)
175
+
176
+ ## 使用示例
177
+
178
+ ### 基础消息处理
114
179
 
115
180
  ```typescript
116
181
  import { usePlugin, MessageCommand } from 'zhin.js'
@@ -124,69 +189,113 @@ addCommand(new MessageCommand('hello')
124
189
  )
125
190
  ```
126
191
 
127
- ### Send Rich Messages
192
+ ### 发送带 Block Kit 按钮的富消息
128
193
 
129
194
  ```typescript
130
- addCommand(new MessageCommand('info')
195
+ addCommand(new MessageCommand('vote')
131
196
  .action(async (message) => {
132
197
  return [
133
- { type: 'text', data: { text: '*Bold* and _italic_ text\n' } },
134
- { type: 'link', data: { url: 'https://slack.com', text: 'Visit Slack' } }
198
+ { type: 'text', data: { text: 'What do you think?' } },
199
+ {
200
+ type: 'keyboard',
201
+ data: {
202
+ rows: [[
203
+ { label: 'Approve', id: 'vote_yes', style: 'primary' },
204
+ { label: 'Reject', id: 'vote_no', style: 'danger' },
205
+ ]]
206
+ }
207
+ }
135
208
  ]
136
209
  })
137
210
  )
138
211
  ```
139
212
 
140
- ### Mention Users
213
+ ### 在线程中回复
141
214
 
142
215
  ```typescript
143
- addCommand(new MessageCommand('mention <userId:text>')
144
- .action(async (message, result) => {
145
- return [
146
- { type: 'at', data: { id: result.params.userId } },
147
- { type: 'text', data: { text: ' Hello!' } }
148
- ]
216
+ addCommand(new MessageCommand('thread')
217
+ .action(async (message) => {
218
+ await message.$reply('This is a threaded reply!', true)
149
219
  })
150
220
  )
151
221
  ```
152
222
 
153
- ### Reply in Thread
223
+ ### 编辑消息
224
+
225
+ 适配器支持 core `EditMessageOptions` 契约。`messageId` 优先使用 `channel:ts` 格式;若仅为 `ts`,则使用 `options.id` 作为 channel。
154
226
 
155
227
  ```typescript
156
- addCommand(new MessageCommand('thread')
157
- .action(async (message) => {
158
- // Reply in a thread by passing the message timestamp
159
- await message.$reply('This is a threaded reply!', true)
160
- })
161
- )
228
+ const adapter = inject('slack')
229
+
230
+ // API(薄封装,仍可用)
231
+ await adapter.editMessage('my-slack-bot', 'C001', '1700000000.000000', [
232
+ { type: 'text', data: { text: 'Updated message content' } }
233
+ ])
234
+
235
+ // core 契约(推荐)
236
+ await adapter.editMessage({
237
+ messageId: 'C001:1700000000.000000',
238
+ context: 'slack',
239
+ endpoint: 'my-slack-bot',
240
+ id: 'C001',
241
+ type: 'group',
242
+ content: [{ type: 'text', data: { text: 'Updated message content' } }],
243
+ })
162
244
  ```
163
245
 
164
- ## Slack-Specific Features
246
+ ## Slack MCP Server 集成
247
+
248
+ 如果你的 zhin 实例使用了 `@zhin.js/agent`(AI 功能),可以将 Slack MCP Server 配置为 AI 的工具来源:
249
+
250
+ ```typescript
251
+ export default defineConfig({
252
+ ai: {
253
+ mcpServers: {
254
+ slack: {
255
+ command: 'npx',
256
+ args: ['-y', '@anthropic/slack-mcp-server'],
257
+ env: {
258
+ SLACK_BOT_TOKEN: 'xoxb-your-bot-token',
259
+ SLACK_TEAM_ID: 'T0123456789'
260
+ }
261
+ }
262
+ }
263
+ }
264
+ })
265
+ ```
165
266
 
166
- ### Slack Formatting
267
+ 这将使 AI Agent 获得搜索 Slack 消息、管理频道等额外能力。
167
268
 
168
- Slack uses mrkdwn format:
169
- - `*bold*` for **bold**
170
- - `_italic_` for *italic*
171
- - `~strike~` for ~~strikethrough~~
172
- - `` `code` `` for `code`
173
- - `> quote` for blockquotes
269
+ ## Notice 事件映射
174
270
 
175
- ### User and Channel Mentions
271
+ | Slack 事件 | zhin Notice 类型 |
272
+ |---|---|
273
+ | `member_joined_channel` | `notice.group.member_increase` |
274
+ | `member_left_channel` | `notice.group.member_decrease` |
275
+ | `reaction_added` / `reaction_removed` | `notice.group.emoji_reaction` |
276
+ | `message_deleted` | `notice.group.recall` |
277
+ | `team_join` | `notice.friend.increase` |
278
+ | `channel_archive` | `notice.slack.channel_archive` |
279
+ | `pin_added` / `pin_removed` | `notice.slack.pin_added` / `notice.slack.pin_removed` |
176
280
 
177
- The adapter automatically converts:
178
- - `<@U12345678>` to user mentions
179
- - `<#C12345678>` to channel mentions
281
+ ## AI 工具
180
282
 
181
- ### File Uploads
283
+ | 类别 | 路径 |
284
+ |------|------|
285
+ | Permit 词汇 | `agent/PERMITS.md` |
286
+ | 平台工具(11 个) | `agent/tools/`(`slack_*`:邀请、话题、反应、置顶等) |
287
+ | 技能说明 | `agent/skills/slack.md` |
288
+ | 群管标准工具 | `createSceneManagementTools()` |
182
289
 
183
- Upload files using the `file` segment type with a local file path.
184
290
 
185
- ## Limitations
291
+ ## 限制
186
292
 
187
- - Message recall requires channel information (not available from message ID alone)
188
- - Some Slack features like interactive components require additional setup
293
+ - 入站 mrkdwn Markdown 为启发式转换,复杂嵌套格式不保证完美往返
294
+ - Modals / `view_submission` / `view_closed` 暂不支持
295
+ - Select menus / options load — 暂不支持
296
+ - File 事件全系列(`file_created` / `file_shared` 等)— 暂不支持
297
+ - OAuth 安装流程 — 暂不支持
189
298
 
190
- ## License
299
+ ## 许可证
191
300
 
192
301
  MIT
@@ -34,6 +34,7 @@ tools:
34
34
  - slack_user_info
35
35
  - slack_set_purpose
36
36
  - slack_unarchive
37
+ - slack_edit_message
37
38
  - slack_kick_member
38
39
  - slack_set_group_name
39
40
  - slack_list_members
@@ -83,6 +84,7 @@ Slack 频道有两个元信息字段:
83
84
  | `slack_unpin_message` | 取消置顶 | — |
84
85
  | `slack_add_reaction` | 添加表情反应 | — |
85
86
  | `slack_remove_reaction` | 移除表情反应 | — |
87
+ | `slack_edit_message` | 编辑消息 | 通过 chat.update 修改已发消息 |
86
88
 
87
89
  ## 易错点
88
90
 
@@ -0,0 +1,26 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
4
+
5
+ export default defineTool<{
6
+ endpoint_id: string;
7
+ channel: string;
8
+ timestamp: string;
9
+ emoji: string;
10
+ }>({
11
+ description: '给 Slack 消息添加表情反应',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel: z.string().describe('频道 ID'),
15
+ timestamp: z.string().describe('消息时间戳'),
16
+ emoji: z.string().describe('表情名称(不含冒号)'),
17
+ }),
18
+ platforms: ['slack'],
19
+ tags: ['slack'],
20
+ async execute({ endpoint_id, channel, timestamp, emoji }) {
21
+ const { getEndpoint } = getSlackAgentDeps();
22
+ const endpoint = getEndpoint(endpoint_id);
23
+ const success = await endpoint.addReaction(channel, timestamp, emoji);
24
+ return { success, message: success ? `已添加反应 :${emoji}:` : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,24 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
5
+
6
+ export default defineTool<{
7
+ endpoint_id: string;
8
+ channel: string;
9
+ }>({
10
+ description: '归档 Slack 频道',
11
+ inputSchema: z.object({
12
+ endpoint_id: z.string().describe('Endpoint 名称'),
13
+ channel: z.string().describe('频道 ID'),
14
+ }),
15
+ platforms: ['slack'],
16
+ tags: ['slack'],
17
+ permissions: [platformPermit('workspace_admin')],
18
+ async execute({ endpoint_id, channel }) {
19
+ const { getEndpoint } = getSlackAgentDeps();
20
+ const endpoint = getEndpoint(endpoint_id);
21
+ const success = await endpoint.archiveChannel(channel);
22
+ return { success, message: success ? '已归档频道' : '操作失败' };
23
+ },
24
+ });
@@ -0,0 +1,27 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
4
+
5
+ export default defineTool<{
6
+ endpoint_id: string;
7
+ channel: string;
8
+ message_ts: string;
9
+ text: string;
10
+ }>({
11
+ description: '编辑 Slack 消息',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel: z.string().describe('频道 ID'),
15
+ message_ts: z.string().describe('消息时间戳'),
16
+ text: z.string().describe('新的消息文本'),
17
+ }),
18
+ platforms: ['slack'],
19
+ tags: ['slack'],
20
+ async execute({ endpoint_id, channel, message_ts, text }) {
21
+ const { getAdapter } = getSlackAgentDeps();
22
+ await getAdapter().editMessage(endpoint_id, channel, message_ts, [
23
+ { type: 'text', data: { text } },
24
+ ]);
25
+ return { success: true, message: '消息已编辑' };
26
+ },
27
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
5
+
6
+ export default defineTool<{
7
+ endpoint_id: string;
8
+ channel: string;
9
+ users: string;
10
+ }>({
11
+ description: '邀请用户加入 Slack 频道',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel: z.string().describe('频道 ID'),
15
+ users: z.string().describe('用户 ID 列表(逗号分隔)'),
16
+ }),
17
+ platforms: ['slack'],
18
+ tags: ['slack'],
19
+ permissions: [platformPermit('channel_manager')],
20
+ async execute({ endpoint_id, channel, users }) {
21
+ const { getEndpoint } = getSlackAgentDeps();
22
+ const endpoint = getEndpoint(endpoint_id);
23
+ const success = await endpoint.inviteToChannel(channel, users.split(','));
24
+ return { success, message: success ? '已邀请用户加入频道' : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
5
+
6
+ export default defineTool<{
7
+ endpoint_id: string;
8
+ channel: string;
9
+ timestamp: string;
10
+ }>({
11
+ description: '置顶 Slack 消息',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel: z.string().describe('频道 ID'),
15
+ timestamp: z.string().describe('消息时间戳'),
16
+ }),
17
+ platforms: ['slack'],
18
+ tags: ['slack'],
19
+ permissions: [platformPermit('channel_manager')],
20
+ async execute({ endpoint_id, channel, timestamp }) {
21
+ const { getEndpoint } = getSlackAgentDeps();
22
+ const endpoint = getEndpoint(endpoint_id);
23
+ const success = await endpoint.pinMessage(channel, timestamp);
24
+ return { success, message: success ? '已置顶消息' : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
4
+
5
+ export default defineTool<{
6
+ endpoint_id: string;
7
+ channel_id: string;
8
+ timestamp: string;
9
+ name: string;
10
+ }>({
11
+ description: '移除 Slack 消息上的表情反应',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel_id: z.string().describe('频道 ID'),
15
+ timestamp: z.string().describe('消息时间戳'),
16
+ name: z.string().describe('表情名称(如 thumbsup、heart)'),
17
+ }),
18
+ platforms: ['slack'],
19
+ tags: ['slack'],
20
+ async execute({ endpoint_id, channel_id, timestamp, name }) {
21
+ const { getEndpoint } = getSlackAgentDeps();
22
+ const endpoint = getEndpoint(endpoint_id);
23
+ const success = await endpoint.removeReaction(channel_id, timestamp, name);
24
+ return { success, message: success ? `已移除反应 :${name}:` : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
5
+
6
+ export default defineTool<{
7
+ endpoint_id: string;
8
+ channel_id: string;
9
+ purpose: string;
10
+ }>({
11
+ description: '设置 Slack 频道的用途/目的',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel_id: z.string().describe('频道 ID'),
15
+ purpose: z.string().describe('频道用途描述'),
16
+ }),
17
+ platforms: ['slack'],
18
+ tags: ['slack'],
19
+ permissions: [platformPermit('channel_manager')],
20
+ async execute({ endpoint_id, channel_id, purpose }) {
21
+ const { getEndpoint } = getSlackAgentDeps();
22
+ const endpoint = getEndpoint(endpoint_id);
23
+ const success = await endpoint.setChannelPurpose(channel_id, purpose);
24
+ return { success, message: success ? '频道用途已更新' : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,26 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
5
+
6
+ export default defineTool<{
7
+ endpoint_id: string;
8
+ channel: string;
9
+ topic: string;
10
+ }>({
11
+ description: '设置 Slack 频道话题',
12
+ inputSchema: z.object({
13
+ endpoint_id: z.string().describe('Endpoint 名称'),
14
+ channel: z.string().describe('频道 ID'),
15
+ topic: z.string().describe('新话题'),
16
+ }),
17
+ platforms: ['slack'],
18
+ tags: ['slack'],
19
+ permissions: [platformPermit('channel_manager')],
20
+ async execute({ endpoint_id, channel, topic }) {
21
+ const { getEndpoint } = getSlackAgentDeps();
22
+ const endpoint = getEndpoint(endpoint_id);
23
+ const success = await endpoint.setChannelTopic(channel, topic);
24
+ return { success, message: success ? '已设置频道话题' : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,24 @@
1
+ import { defineTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+ import { getSlackAgentDeps } from '../../src/slack-agent-deps.js';
5
+
6
+ export default defineTool<{
7
+ endpoint_id: string;
8
+ channel_id: string;
9
+ }>({
10
+ description: '恢复已归档的 Slack 频道',
11
+ inputSchema: z.object({
12
+ endpoint_id: z.string().describe('Endpoint 名称'),
13
+ channel_id: z.string().describe('频道 ID'),
14
+ }),
15
+ platforms: ['slack'],
16
+ tags: ['slack'],
17
+ permissions: [platformPermit('workspace_admin')],
18
+ async execute({ endpoint_id, channel_id }) {
19
+ const { getEndpoint } = getSlackAgentDeps();
20
+ const endpoint = getEndpoint(endpoint_id);
21
+ const success = await endpoint.unarchiveChannel(channel_id);
22
+ return { success, message: success ? '频道已恢复' : '操作失败' };
23
+ },
24
+ });