@zhin.js/adapter-slack 1.0.78 → 1.1.2

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 (108) hide show
  1. package/CHANGELOG.md +731 -2
  2. package/PERMITS.md +24 -0
  3. package/README.md +111 -158
  4. package/adapters/slack/index.js +40 -0
  5. package/adapters/slack/index.ts +45 -0
  6. package/agents/slack/agent.json +20 -0
  7. package/agents/slack/boundaries.md +3 -0
  8. package/agents/slack/conventions.md +3 -0
  9. package/agents/slack/skills/slack-channels/SKILL.md +24 -0
  10. package/agents/slack/skills/slack-channels/tools/archive_channel/index.js +19 -0
  11. package/agents/slack/skills/slack-channels/tools/archive_channel/index.ts +21 -0
  12. package/agents/slack/skills/slack-channels/tools/invite_to_channel/index.js +20 -0
  13. package/agents/slack/skills/slack-channels/tools/invite_to_channel/index.ts +23 -0
  14. package/agents/slack/skills/slack-channels/tools/set_purpose/index.js +20 -0
  15. package/agents/slack/skills/slack-channels/tools/set_purpose/index.ts +23 -0
  16. package/agents/slack/skills/slack-channels/tools/set_topic/index.js +20 -0
  17. package/agents/slack/skills/slack-channels/tools/set_topic/index.ts +23 -0
  18. package/agents/slack/skills/slack-channels/tools/unarchive/index.js +19 -0
  19. package/agents/slack/skills/slack-channels/tools/unarchive/index.ts +21 -0
  20. package/agents/slack/skills/slack-channels/tools/user_info/index.js +27 -0
  21. package/agents/slack/skills/slack-channels/tools/user_info/index.ts +29 -0
  22. package/agents/slack/skills/slack-messages/SKILL.md +22 -0
  23. package/agents/slack/skills/slack-messages/tools/add_reaction/index.js +27 -0
  24. package/agents/slack/skills/slack-messages/tools/add_reaction/index.ts +29 -0
  25. package/agents/slack/skills/slack-messages/tools/edit_message/index.js +21 -0
  26. package/agents/slack/skills/slack-messages/tools/edit_message/index.ts +25 -0
  27. package/agents/slack/skills/slack-messages/tools/pin_message/index.js +20 -0
  28. package/agents/slack/skills/slack-messages/tools/pin_message/index.ts +23 -0
  29. package/agents/slack/skills/slack-messages/tools/remove_reaction/index.js +30 -0
  30. package/agents/slack/skills/slack-messages/tools/remove_reaction/index.ts +32 -0
  31. package/agents/slack/skills/slack-messages/tools/unpin_message/index.js +20 -0
  32. package/agents/slack/skills/slack-messages/tools/unpin_message/index.ts +23 -0
  33. package/agents/slack/system.md +3 -0
  34. package/commands/slack/endpoint/add/[id]/index.js +3 -0
  35. package/commands/slack/endpoint/add/[id]/index.ts +3 -0
  36. package/commands/slack/endpoint/definition.js +19 -0
  37. package/commands/slack/endpoint/definition.ts +19 -0
  38. package/commands/slack/endpoint/list/index.js +3 -0
  39. package/commands/slack/endpoint/list/index.ts +3 -0
  40. package/commands/slack/endpoint/remove/[id]/index.js +3 -0
  41. package/commands/slack/endpoint/remove/[id]/index.ts +3 -0
  42. package/lib/client.d.ts +25 -0
  43. package/lib/client.js +2 -0
  44. package/lib/endpoint.d.ts +153 -0
  45. package/lib/endpoint.js +425 -0
  46. package/lib/index.d.ts +10 -10
  47. package/lib/index.js +10 -242
  48. package/lib/markdown-to-mrkdwn.d.ts +9 -0
  49. package/lib/markdown-to-mrkdwn.js +121 -0
  50. package/lib/mrkdwn-to-markdown.d.ts +4 -0
  51. package/lib/mrkdwn-to-markdown.js +30 -0
  52. package/lib/platform-permit.d.ts +15 -0
  53. package/lib/platform-permit.js +43 -0
  54. package/lib/protocol.d.ts +144 -0
  55. package/lib/protocol.js +258 -0
  56. package/lib/side-event-dispatch.d.ts +4 -0
  57. package/lib/side-event-dispatch.js +45 -0
  58. package/lib/slack-inbound-filter.d.ts +12 -0
  59. package/lib/slack-inbound-filter.js +46 -0
  60. package/lib/slack-message-ref.d.ts +7 -0
  61. package/lib/slack-message-ref.js +17 -0
  62. package/lib/slack-outbound.d.ts +24 -0
  63. package/lib/slack-outbound.js +111 -0
  64. package/lib/slack-reaction.d.ts +1 -0
  65. package/lib/slack-reaction.js +26 -0
  66. package/lib/slack-response-url.d.ts +5 -0
  67. package/lib/slack-response-url.js +16 -0
  68. package/lib/slack-runtime-state.d.ts +1 -0
  69. package/lib/slack-runtime-state.js +6 -0
  70. package/lib/webhook.d.ts +14 -0
  71. package/lib/webhook.js +72 -0
  72. package/package.json +80 -16
  73. package/plugin.js +19 -0
  74. package/schema.json +108 -0
  75. package/src/client.ts +30 -0
  76. package/src/endpoint.ts +526 -0
  77. package/src/index.ts +59 -265
  78. package/src/markdown-to-mrkdwn.ts +117 -0
  79. package/src/mrkdwn-to-markdown.ts +29 -0
  80. package/src/platform-permit.ts +59 -0
  81. package/src/protocol.ts +406 -0
  82. package/src/side-event-dispatch.ts +54 -0
  83. package/src/slack-inbound-filter.ts +60 -0
  84. package/src/slack-message-ref.ts +18 -0
  85. package/src/slack-outbound.ts +170 -0
  86. package/src/slack-reaction.ts +23 -0
  87. package/src/slack-response-url.ts +26 -0
  88. package/src/slack-runtime-state.ts +7 -0
  89. package/src/webhook.ts +106 -0
  90. package/lib/adapter.d.ts +0 -16
  91. package/lib/adapter.d.ts.map +0 -1
  92. package/lib/adapter.js +0 -43
  93. package/lib/adapter.js.map +0 -1
  94. package/lib/bot.d.ts +0 -106
  95. package/lib/bot.d.ts.map +0 -1
  96. package/lib/bot.js +0 -628
  97. package/lib/bot.js.map +0 -1
  98. package/lib/index.d.ts.map +0 -1
  99. package/lib/index.js.map +0 -1
  100. package/lib/types.d.ts +0 -17
  101. package/lib/types.d.ts.map +0 -1
  102. package/lib/types.js +0 -2
  103. package/lib/types.js.map +0 -1
  104. package/plugin.yml +0 -3
  105. package/skills/slack/SKILL.md +0 -91
  106. package/src/adapter.ts +0 -52
  107. package/src/bot.ts +0 -688
  108. package/src/types.ts +0 -18
package/PERMITS.md ADDED
@@ -0,0 +1,24 @@
1
+ # Slack Platform Permits
2
+
3
+ ## 入站字段
4
+
5
+ 频道消息异步 enrich(`users.info` + `conversations.info`,TTL 60s):
6
+
7
+ | 字段 | 来源 |
8
+ |------|------|
9
+ | `$sender.role` | `owner` · `admin` · `channel_admin` · `member` |
10
+ | `$sender.permissions` | `workspace_owner` · `workspace_admin` · `channel_manager` |
11
+
12
+ `channel_manager`:频道 `creator === user` 或 workspace 管理员。
13
+
14
+ ## Permit 词汇表
15
+
16
+ | `platform(slack,…)` | 含义 |
17
+ |---------------------|------|
18
+ | `workspace_owner` | Workspace 主 |
19
+ | `workspace_admin` | Workspace 管理员 |
20
+ | `channel_manager` | 频道管理者 |
21
+
22
+ ## 工厂映射
23
+
24
+ `scene_admin` → `channel_manager` · `scene_owner` → `workspace_owner`
package/README.md CHANGED
@@ -1,192 +1,145 @@
1
1
  # @zhin.js/adapter-slack
2
2
 
3
- Slack adapter for zhin.js framework.
3
+ Zhin.js Slack 适配器(Plugin Runtime),优先 Socket Mode,也可经 Runtime Host HTTP Events API 收发消息。
4
4
 
5
- ## Installation
5
+ ## 功能
6
+
7
+ - **Socket Mode**(默认):WebSocket 长连接,无需公网 URL
8
+ - **HTTP Events API**:`httpHostToken` POST(签名验证),**非** legacy host-router/Koa
9
+ - 入站经 `Endpoint.emit(...)`;出站 `send({ conversation, payload })` → `chat.postMessage` / Block Kit
10
+ - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
11
+ - Block Kit 按钮、斜杠命令、消息编辑、表情反应等(见 `tools/`)
12
+
13
+ ## 安装
6
14
 
7
15
  ```bash
8
16
  pnpm add @zhin.js/adapter-slack
9
17
  ```
10
18
 
11
- ## Configuration
19
+ ## Plugin Runtime
20
+
21
+ - `@zhin.js/adapter` — 约定式 `adapters/slack/index.ts`(`defineAdapter`)
22
+ - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
23
+ - `@zhin.js/host-http` — 仅 HTTP 模式需要 `httpHostToken` 注册 Events 路由
24
+ - `zhin.js` — `plugin.ts`(`definePlugin`)
25
+ - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
12
26
 
13
- 通过 **`socketMode`** 选择连接方式(默认 `true` 时为 Socket Mode)。
27
+ 入站:`gateway.receive({ conversation, message: { conversation, id }, content: text, sender, metadata })`(`conversation` 为 ConversationRef:`channel_type: im` → kind `private`,其余 → kind `group`;线程根 ts 进 `threadId`)
28
+ 出站:`send({ conversation, payload })` → Web API(`conversation.id` 为 channel,`conversation.threadId` 为 thread_ts)
14
29
 
15
- ### 模式对比
30
+ ### 平台权限(platform permit)
31
+
32
+ - `plugin.ts` 已注册 checker,Runtime Tool 权限统一经 Core `canAccessTool()`;当前 Slack 入站没有可靠 sender role 时,受限工具按 fail-closed 拒绝,不会静默放行。
33
+
34
+ ## 模式对比
16
35
 
17
36
  | 模式 | `socketMode` | 适用场景 | 额外字段 |
18
37
  |------|--------------|----------|----------|
19
- | **Socket Mode** | `true`(推荐本地/内网) | 无需公网 URL,WebSocket 长连接 | `appToken`(`xapp-...`) |
20
- | **HTTP Events** | `false` | 生产环境,有公网 HTTPS | `port`(Bolt 监听端口) |
21
-
22
- #### HTTP 模式前置条件
23
-
24
- - Slack App 中配置 **Event Subscriptions** 的 Request URL(须公网 HTTPS 可达)
25
- - 启用对应 Bot Events(`message.*`、`app_mention` 等)
26
- - 防火墙 / 反向代理放行 `port`
27
- - **不需要** `@zhin.js/host-router`(由 `@slack/bolt` 自行监听)
28
-
29
- ### Socket Mode (Recommended for Development)
30
-
31
- ```typescript
32
- import { defineConfig } from 'zhin.js'
33
-
34
- export default defineConfig({
35
- bots: [
36
- {
37
- name: 'my-slack-bot',
38
- context: 'slack',
39
- token: 'xoxb-your-bot-token',
40
- signingSecret: 'your-signing-secret',
41
- appToken: 'xapp-your-app-token',
42
- socketMode: true
43
- }
44
- ]
45
- })
38
+ | **Socket Mode**(默认) | `true` | 本地/内网,无需公网 URL | `appToken`(`xapp-...`) |
39
+ | **HTTP Events** | `false` | 生产环境有公网 HTTPS | `signingSecret` + Runtime Host |
40
+
41
+ ## 前置条件
42
+
43
+ 1. 创建 Slack App,安装到 Workspace,并授予收发消息所需 OAuth scopes。
44
+ 2. Socket Mode 创建 `connections:write` App-Level Token;HTTP 模式配置 Signing Secret 与 Events URL。
45
+ 3. 订阅需要的 bot events,并把应用加入目标频道。
46
+
47
+ ## 最小配置(Socket Mode)
48
+
49
+ ```yaml
50
+ # zhin.config.yml(Plugin Runtime)
51
+ plugins:
52
+ slack:
53
+ socketMode: true # 默认 true,可省略
54
+ endpoints:
55
+ - id: my-slack-bot
56
+ token: ${SLACK_BOT_TOKEN}
57
+ appToken: ${SLACK_APP_TOKEN}
46
58
  ```
47
59
 
48
- ### HTTP Mode (For Production with Public URL)
49
-
50
- ```typescript
51
- import { defineConfig } from 'zhin.js'
52
-
53
- export default defineConfig({
54
- bots: [
55
- {
56
- name: 'my-slack-bot',
57
- context: 'slack',
58
- token: 'xoxb-your-bot-token',
59
- signingSecret: 'your-signing-secret',
60
- socketMode: false,
61
- port: 3000
62
- }
63
- ]
64
- })
60
+ 多 workspace:一个插件实例挂多个 endpoint(`endpoints` 数组逐项覆盖顶层字段,`id` 必填):
61
+
62
+ ```yaml
63
+ plugins:
64
+ slack:
65
+ endpoints:
66
+ - id: team-a
67
+ token: ${SLACK_BOT_TOKEN_A}
68
+ appToken: ${SLACK_APP_TOKEN_A}
69
+ - id: team-b
70
+ token: ${SLACK_BOT_TOKEN_B}
71
+ appToken: ${SLACK_APP_TOKEN_B}
65
72
  ```
66
73
 
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 Bot 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 Bot 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
114
-
115
- ```typescript
116
- import { usePlugin, MessageCommand } from 'zhin.js'
117
-
118
- const { addCommand } = usePlugin()
119
-
120
- addCommand(new MessageCommand('hello')
121
- .action(async (message) => {
122
- return 'Hello from Slack!'
123
- })
124
- )
74
+ ## HTTP Events 配置
75
+
76
+ ```yaml
77
+ plugins:
78
+ slack:
79
+ socketMode: false
80
+ webhookPath: /slack/events # 可选,默认 /slack/events
81
+ endpoints:
82
+ - id: my-slack-bot
83
+ token: ${SLACK_BOT_TOKEN}
84
+ signingSecret: ${SLACK_SIGNING_SECRET}
125
85
  ```
126
86
 
127
- ### Send Rich Messages
128
-
129
- ```typescript
130
- addCommand(new MessageCommand('info')
131
- .action(async (message) => {
132
- return [
133
- { type: 'text', data: { text: '*Bold* and _italic_ text\n' } },
134
- { type: 'link', data: { url: 'https://slack.com', text: 'Visit Slack' } }
135
- ]
136
- })
137
- )
138
- ```
87
+ 根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-slack`(`instanceKey: slack`)。
88
+ HTTP 模式下 Runtime Host(`http`)须已 listen;Slack App 的 Event Subscriptions / Interactivity / Slash Commands Request URL 指向 `https://your-domain/slack/events`。
139
89
 
140
- ### Mention Users
141
-
142
- ```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
- ]
149
- })
150
- )
151
- ```
90
+ ## 环境变量
152
91
 
153
- ### Reply in Thread
92
+ | 变量 | 说明 |
93
+ |------|------|
94
+ | `SLACK_BOT_TOKEN` | 示例中由 YAML `${SLACK_BOT_TOKEN}` 引用的 Bot User OAuth Token;变量名可自行定义 |
95
+ | `SLACK_APP_TOKEN` | 示例中由 YAML `${SLACK_APP_TOKEN}` 引用的 App-Level Token;变量名可自行定义 |
96
+ | `SLACK_SIGNING_SECRET` | 示例中由 YAML `${SLACK_SIGNING_SECRET}` 引用的 Signing Secret;变量名可自行定义 |
154
97
 
155
- ```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
- )
162
- ```
98
+ ## 消息格式
99
+
100
+ ### 出站(Markdown → mrkdwn)
163
101
 
164
- ## Slack-Specific Features
102
+ 通用 Markdown(如 `**粗体**`)会转换为 Slack mrkdwn,并通过 Block Kit `section` 发送。
165
103
 
166
- ### Slack Formatting
104
+ ### 入站(mrkdwn → Markdown)
167
105
 
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
106
+ | Slack mrkdwn | 通用 Markdown |
107
+ |--------------|---------------|
108
+ | `*bold*` | `**bold**` |
109
+ | `_italic_` | `*italic*` |
110
+ | `~strike~` | `~~strike~~` |
111
+ | `<url\|text>` | `[text](url)` |
174
112
 
175
- ### User and Channel Mentions
113
+ ## AI 工具
176
114
 
177
- The adapter automatically converts:
178
- - `<@U12345678>` to user mentions
179
- - `<#C12345678>` to channel mentions
115
+ | 类别 | 路径 |
116
+ |------|------|
117
+ | Permit 词汇 | `PERMITS.md` |
118
+ | 平台工具 | `tools/`(邀请、话题、反应、置顶、编辑等) |
119
+ | 技能说明 | `agents/slack/skills/slack-channels/SKILL.md`、`agents/slack/skills/slack-messages/SKILL.md` |
180
120
 
181
- ### File Uploads
121
+ ## 限制
182
122
 
183
- Upload files using the `file` segment type with a local file path.
123
+ - 入站 mrkdwn → Markdown 为启发式转换
124
+ - Modals / Select menus — 暂不支持
125
+ - OAuth 安装流程 — 暂不支持
126
+ - 旧 `usePlugin` / `extends Adapter` / host-router 生产入口已删除
184
127
 
185
- ## Limitations
128
+ ## 故障排查
186
129
 
187
- - Message recall requires channel information (not available from message ID alone)
188
- - Some Slack features like interactive components require additional setup
130
+ | 现象 | 排查 |
131
+ | --- | --- |
132
+ | Socket Mode 无法连接 | 检查 `xapp-` Token、Socket Mode 与 `connections:write` scope |
133
+ | HTTP Events 返回 401 | 检查 Signing Secret、原始请求体、服务器时钟与反向代理 |
134
+ | 频道消息未触发 | 确认事件订阅、OAuth scopes,并邀请 App 进入频道 |
135
+ | 线程回复跑到主频道 | 检查入站 `thread_ts` 是否保留为 Conversation `threadId` |
189
136
 
190
- ## License
137
+ ## 许可证
191
138
 
192
139
  MIT
140
+
141
+ ## 发送失败与回执
142
+
143
+ 成功发送返回平台 `ts` 组成的消息引用,不以本地时间替代缺失回执。
144
+ 文件上传失败会让本次发送失败;分段消息中某段缺少有效回执时,停止后续分段。
145
+ 前面已成功的文件或分段不会自动回滚;发送失败可能表示部分已送达,请先核对目标会话再重试。
@@ -0,0 +1,40 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ /**
3
+ * Convention entry: discover `adapters/slack/index.ts` → defineAdapter.
4
+ */
5
+ import { defineAdapter } from 'zhin.js/adapter';
6
+ import { httpHostToken } from '@zhin.js/host-http';
7
+ import { SlackEndpoint } from "../../lib/endpoint.js";
8
+ import { resolveSlackConfig, } from "../../lib/protocol.js";
9
+ import { slackRuntimeStateToken } from "../../lib/slack-runtime-state.js";
10
+ export { SlackEndpoint } from "../../lib/endpoint.js";
11
+ export default defineAdapter({
12
+ capabilities: ['inbound', 'outbound'],
13
+ operations: ['recall', 'edit', 'reaction'],
14
+ // 媒体段(canonical MediaRef):kind=url 直发(image 走 attachment image_url,
15
+ // 其余拉取后上传);kind=base64 解码后经 files.uploadV2 上传;kind=path 读盘上传;
16
+ // kind=file 无 Slack 对应物,丢弃留痕。Block Kit 原生按钮承载交互段。
17
+ segments: {
18
+ outboundMedia: ['url', 'upload', 'path'],
19
+ interactive: 'native',
20
+ },
21
+ create(context) {
22
+ const config = resolveSlackConfig(context.config);
23
+ // 注册到插件运行时状态(slack endpoint list 的"运行中"数据源)
24
+ context.use(slackRuntimeStateToken).endpoints.set(config.id, {
25
+ id: config.id,
26
+ mode: config.mode,
27
+ });
28
+ if (config.mode === 'http') {
29
+ return new SlackEndpoint({
30
+ id: context.id,
31
+ http: context.use(httpHostToken),
32
+ config,
33
+ });
34
+ }
35
+ return new SlackEndpoint({
36
+ id: context.id,
37
+ config,
38
+ });
39
+ },
40
+ });
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Convention entry: discover `adapters/slack/index.ts` → defineAdapter.
3
+ */
4
+ import { defineAdapter } from 'zhin.js/adapter';
5
+ import { httpHostToken } from '@zhin.js/host-http';
6
+ import { SlackEndpoint } from '../../src/endpoint.js';
7
+ import {
8
+ resolveSlackConfig,
9
+ type SlackEndpointConfig,
10
+ } from '../../src/protocol.js';
11
+ import { slackRuntimeStateToken } from '../../src/slack-runtime-state.js';
12
+
13
+ export { SlackEndpoint } from '../../src/endpoint.js';
14
+ export type { SlackEndpointOptions, SlackSocketLike, SlackWebClientLike } from '../../src/endpoint.js';
15
+
16
+ export default defineAdapter<SlackEndpointConfig>({
17
+ capabilities: ['inbound', 'outbound'],
18
+ operations: ['recall', 'edit', 'reaction'],
19
+ // 媒体段(canonical MediaRef):kind=url 直发(image 走 attachment image_url,
20
+ // 其余拉取后上传);kind=base64 解码后经 files.uploadV2 上传;kind=path 读盘上传;
21
+ // kind=file 无 Slack 对应物,丢弃留痕。Block Kit 原生按钮承载交互段。
22
+ segments: {
23
+ outboundMedia: ['url', 'upload', 'path'],
24
+ interactive: 'native',
25
+ },
26
+ create(context) {
27
+ const config = resolveSlackConfig(context.config);
28
+ // 注册到插件运行时状态(slack endpoint list 的"运行中"数据源)
29
+ context.use(slackRuntimeStateToken).endpoints.set(config.id, {
30
+ id: config.id,
31
+ mode: config.mode,
32
+ });
33
+ if (config.mode === 'http') {
34
+ return new SlackEndpoint({
35
+ id: context.id,
36
+ http: context.use(httpHostToken),
37
+ config,
38
+ });
39
+ }
40
+ return new SlackEndpoint({
41
+ id: context.id,
42
+ config,
43
+ });
44
+ },
45
+ });
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "SLACK Platform Agent",
3
+ "version": "1.0.0",
4
+ "description": "Handles slack platform-specific operations and progressively loads only the required platform Skill.",
5
+ "trigger_rules": {
6
+ "file_patterns": [],
7
+ "keywords": [
8
+ "slack",
9
+ "adapter:slack"
10
+ ]
11
+ },
12
+ "entry_points": [
13
+ "system.md",
14
+ "boundaries.md",
15
+ "conventions.md"
16
+ ],
17
+ "platforms": [
18
+ "slack"
19
+ ]
20
+ }
@@ -0,0 +1,3 @@
1
+ # Boundaries
2
+
3
+ Operate only on the active slack endpoint and authenticated conversation context. Respect every Tool permission and approval policy. Do not infer identifiers, roles, or authorization from display names.
@@ -0,0 +1,3 @@
1
+ # Conventions
2
+
3
+ Use stable platform identifiers from the current turn or directory queries. Load one task-specific Skill at a time, and use the unified reply and outbound message path.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: slack-channels
3
+ platforms:
4
+ - slack
5
+ description: Slack 用户查询、频道邀请、主题、用途和归档管理能力。
6
+ keywords:
7
+ - "slack"
8
+ - "channel"
9
+ - "invite"
10
+ - "topic"
11
+ - "archive"
12
+ - "user"
13
+ tools:
14
+ - "invite_to_channel"
15
+ - "set_topic"
16
+ - "set_purpose"
17
+ - "archive_channel"
18
+ - "unarchive"
19
+ - "user_info"
20
+ ---
21
+
22
+ # slack-channels
23
+
24
+ 先查询用户 ID,再邀请或修改频道。归档和恢复属于频道状态变更,遵守 Tool 审批。
@@ -0,0 +1,19 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { platformPermission } from '@zhin.js/permission';
5
+ export default defineAgentTool({
6
+ description: '归档 Slack 频道',
7
+ inputSchema: z.object({
8
+ channel: z.string().describe('频道 ID'),
9
+ }),
10
+ adapter: 'slack',
11
+ tags: ['slack'],
12
+ permissions: [platformPermission('slack', 'workspace_admin')],
13
+ async execute({ channel }, context) {
14
+ const client = context.$client;
15
+ await client.conversations.archive({ channel });
16
+ const success = true;
17
+ return { success, message: success ? '已归档频道' : '操作失败' };
18
+ },
19
+ });
@@ -0,0 +1,21 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { platformPermission } from '@zhin.js/permission';
4
+
5
+ export default defineAgentTool<{
6
+ channel: string;
7
+ }>({
8
+ description: '归档 Slack 频道',
9
+ inputSchema: z.object({
10
+ channel: z.string().describe('频道 ID'),
11
+ }),
12
+ adapter: 'slack',
13
+ tags: ['slack'],
14
+ permissions: [platformPermission('slack', 'workspace_admin')],
15
+ async execute({ channel }, context) {
16
+ const client = context.$client;
17
+ await client.conversations.archive({ channel });
18
+ const success = true;
19
+ return { success, message: success ? '已归档频道' : '操作失败' };
20
+ },
21
+ });
@@ -0,0 +1,20 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { platformPermission } from '@zhin.js/permission';
5
+ export default defineAgentTool({
6
+ description: '邀请用户加入 Slack 频道',
7
+ inputSchema: z.object({
8
+ channel: z.string().describe('频道 ID'),
9
+ users: z.string().describe('用户 ID 列表(逗号分隔)'),
10
+ }),
11
+ adapter: 'slack',
12
+ tags: ['slack'],
13
+ permissions: [platformPermission('slack', 'channel_manager')],
14
+ async execute({ channel, users }, context) {
15
+ const client = context.$client;
16
+ await client.conversations.invite({ channel, users });
17
+ const success = true;
18
+ return { success, message: success ? '已邀请用户加入频道' : '操作失败' };
19
+ },
20
+ });
@@ -0,0 +1,23 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { platformPermission } from '@zhin.js/permission';
4
+
5
+ export default defineAgentTool<{
6
+ channel: string;
7
+ users: string;
8
+ }>({
9
+ description: '邀请用户加入 Slack 频道',
10
+ inputSchema: z.object({
11
+ channel: z.string().describe('频道 ID'),
12
+ users: z.string().describe('用户 ID 列表(逗号分隔)'),
13
+ }),
14
+ adapter: 'slack',
15
+ tags: ['slack'],
16
+ permissions: [platformPermission('slack', 'channel_manager')],
17
+ async execute({ channel, users }, context) {
18
+ const client = context.$client;
19
+ await client.conversations.invite({ channel, users });
20
+ const success = true;
21
+ return { success, message: success ? '已邀请用户加入频道' : '操作失败' };
22
+ },
23
+ });
@@ -0,0 +1,20 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { platformPermission } from '@zhin.js/permission';
5
+ export default defineAgentTool({
6
+ description: '设置 Slack 频道的用途/目的',
7
+ inputSchema: z.object({
8
+ channel_id: z.string().describe('频道 ID'),
9
+ purpose: z.string().describe('频道用途描述'),
10
+ }),
11
+ adapter: 'slack',
12
+ tags: ['slack'],
13
+ permissions: [platformPermission('slack', 'channel_manager')],
14
+ async execute({ channel_id, purpose }, context) {
15
+ const client = context.$client;
16
+ await client.conversations.setPurpose({ channel: channel_id, purpose });
17
+ const success = true;
18
+ return { success, message: success ? '频道用途已更新' : '操作失败' };
19
+ },
20
+ });
@@ -0,0 +1,23 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { platformPermission } from '@zhin.js/permission';
4
+
5
+ export default defineAgentTool<{
6
+ channel_id: string;
7
+ purpose: string;
8
+ }>({
9
+ description: '设置 Slack 频道的用途/目的',
10
+ inputSchema: z.object({
11
+ channel_id: z.string().describe('频道 ID'),
12
+ purpose: z.string().describe('频道用途描述'),
13
+ }),
14
+ adapter: 'slack',
15
+ tags: ['slack'],
16
+ permissions: [platformPermission('slack', 'channel_manager')],
17
+ async execute({ channel_id, purpose }, context) {
18
+ const client = context.$client;
19
+ await client.conversations.setPurpose({ channel: channel_id, purpose });
20
+ const success = true;
21
+ return { success, message: success ? '频道用途已更新' : '操作失败' };
22
+ },
23
+ });
@@ -0,0 +1,20 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { platformPermission } from '@zhin.js/permission';
5
+ export default defineAgentTool({
6
+ description: '设置 Slack 频道话题',
7
+ inputSchema: z.object({
8
+ channel: z.string().describe('频道 ID'),
9
+ topic: z.string().describe('新话题'),
10
+ }),
11
+ adapter: 'slack',
12
+ tags: ['slack'],
13
+ permissions: [platformPermission('slack', 'channel_manager')],
14
+ async execute({ channel, topic }, context) {
15
+ const client = context.$client;
16
+ await client.conversations.setTopic({ channel, topic });
17
+ const success = true;
18
+ return { success, message: success ? '已设置频道话题' : '操作失败' };
19
+ },
20
+ });
@@ -0,0 +1,23 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { platformPermission } from '@zhin.js/permission';
4
+
5
+ export default defineAgentTool<{
6
+ channel: string;
7
+ topic: string;
8
+ }>({
9
+ description: '设置 Slack 频道话题',
10
+ inputSchema: z.object({
11
+ channel: z.string().describe('频道 ID'),
12
+ topic: z.string().describe('新话题'),
13
+ }),
14
+ adapter: 'slack',
15
+ tags: ['slack'],
16
+ permissions: [platformPermission('slack', 'channel_manager')],
17
+ async execute({ channel, topic }, context) {
18
+ const client = context.$client;
19
+ await client.conversations.setTopic({ channel, topic });
20
+ const success = true;
21
+ return { success, message: success ? '已设置频道话题' : '操作失败' };
22
+ },
23
+ });