@zhin.js/adapter-slack 1.1.25 → 1.1.27

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 (48) hide show
  1. package/CHANGELOG.md +186 -0
  2. package/LICENSE +21 -0
  3. package/PERMITS.md +10 -17
  4. package/README.md +8 -4
  5. package/agents/slack/conversation.js +15 -0
  6. package/agents/slack/conversation.ts +17 -0
  7. package/agents/slack/messages.js +4 -0
  8. package/agents/slack/messages.ts +4 -0
  9. package/agents/slack/skills/slack-channels/tools/archive_channel/index.js +6 -7
  10. package/agents/slack/skills/slack-channels/tools/archive_channel/index.ts +7 -10
  11. package/agents/slack/skills/slack-channels/tools/invite_to_channel/index.js +5 -5
  12. package/agents/slack/skills/slack-channels/tools/invite_to_channel/index.ts +5 -6
  13. package/agents/slack/skills/slack-channels/tools/set_purpose/index.js +5 -5
  14. package/agents/slack/skills/slack-channels/tools/set_purpose/index.ts +5 -6
  15. package/agents/slack/skills/slack-channels/tools/set_topic/index.js +5 -5
  16. package/agents/slack/skills/slack-channels/tools/set_topic/index.ts +5 -6
  17. package/agents/slack/skills/slack-channels/tools/unarchive/index.js +2 -3
  18. package/agents/slack/skills/slack-channels/tools/unarchive/index.ts +2 -3
  19. package/agents/slack/skills/slack-messages/tools/add_reaction/index.js +5 -4
  20. package/agents/slack/skills/slack-messages/tools/add_reaction/index.ts +5 -5
  21. package/agents/slack/skills/slack-messages/tools/edit_message/index.js +6 -5
  22. package/agents/slack/skills/slack-messages/tools/edit_message/index.ts +6 -6
  23. package/agents/slack/skills/slack-messages/tools/pin_message/index.js +5 -5
  24. package/agents/slack/skills/slack-messages/tools/pin_message/index.ts +5 -6
  25. package/agents/slack/skills/slack-messages/tools/remove_reaction/index.js +5 -4
  26. package/agents/slack/skills/slack-messages/tools/remove_reaction/index.ts +5 -5
  27. package/agents/slack/skills/slack-messages/tools/unpin_message/index.js +5 -5
  28. package/agents/slack/skills/slack-messages/tools/unpin_message/index.ts +5 -6
  29. package/lib/console-spec.js +119 -11
  30. package/lib/index.d.ts +2 -2
  31. package/lib/index.js +2 -2
  32. package/lib/platform-permit.d.ts +4 -12
  33. package/lib/platform-permit.js +7 -41
  34. package/lib/protocol.d.ts +1 -5
  35. package/lib/protocol.js +1 -19
  36. package/lib/slack-message-ref.d.ts +0 -1
  37. package/lib/slack-message-ref.js +0 -3
  38. package/lib/webhook.d.ts +1 -2
  39. package/lib/webhook.js +12 -29
  40. package/package.json +24 -26
  41. package/plugin.js +0 -6
  42. package/schema.json +0 -56
  43. package/src/console-spec.ts +119 -11
  44. package/src/index.ts +1 -7
  45. package/src/platform-permit.ts +5 -54
  46. package/src/protocol.ts +2 -23
  47. package/src/slack-message-ref.ts +0 -4
  48. package/src/webhook.ts +12 -32
@@ -1,19 +1,18 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
2
  import { defineAgentTool } from '@zhin.js/tool';
3
3
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
4
 
6
5
  export default defineAgentTool<{
7
6
  channel_id: string;
8
7
  }>({
9
- description: '恢复已归档的 Slack 频道',
8
+ description: '恢复已归档的 Slack 频道(归档频道无法在其中对话,需指定频道 ID;仅全局层 zhin owner)',
10
9
  inputSchema: z.object({
11
10
  channel_id: z.string().describe('频道 ID'),
12
11
  }),
13
12
  adapter: 'slack',
14
13
  scopes: ["group"],
15
14
  tags: ['slack'],
16
- permissions: [platformPermission('slack', 'workspace_admin')],
15
+ permissions: ['owner@global'],
17
16
  async execute({ channel_id }, context) {
18
17
  const client = context.$client;
19
18
  await client.conversations.unarchive({ channel: channel_id });
@@ -1,18 +1,19 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentChannel } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
6
  import { normalizeSlackReactionName } from '@zhin.js/adapter-slack';
6
7
  export default defineAgentTool({
7
- description: '给 Slack 消息添加表情反应',
8
+ description: '给当前 Slack 频道(或私信)中的消息添加表情反应',
8
9
  inputSchema: z.object({
9
- channel: z.string().describe('频道 ID'),
10
- timestamp: z.string().describe('消息时间戳'),
10
+ timestamp: z.string().describe('当前频道中的消息时间戳'),
11
11
  emoji: z.string().describe('表情名称(不含冒号)'),
12
12
  }),
13
13
  adapter: 'slack',
14
14
  tags: ['slack'],
15
- async execute({ channel, timestamp, emoji }, context) {
15
+ async execute({ timestamp, emoji }, context) {
16
+ const channel = currentChannel(context, { allowDirect: true });
16
17
  const client = context.$client;
17
18
  const name = normalizeSlackReactionName(emoji);
18
19
  try {
@@ -1,22 +1,22 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentChannel } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { normalizeSlackReactionName } from '@zhin.js/adapter-slack';
5
6
 
6
7
  export default defineAgentTool<{
7
- channel: string;
8
8
  timestamp: string;
9
9
  emoji: string;
10
10
  }>({
11
- description: '给 Slack 消息添加表情反应',
11
+ description: '给当前 Slack 频道(或私信)中的消息添加表情反应',
12
12
  inputSchema: z.object({
13
- channel: z.string().describe('频道 ID'),
14
- timestamp: z.string().describe('消息时间戳'),
13
+ timestamp: z.string().describe('当前频道中的消息时间戳'),
15
14
  emoji: z.string().describe('表情名称(不含冒号)'),
16
15
  }),
17
16
  adapter: 'slack',
18
17
  tags: ['slack'],
19
- async execute({ channel, timestamp, emoji }, context) {
18
+ async execute({ timestamp, emoji }, context) {
19
+ const channel = currentChannel(context, { allowDirect: true });
20
20
  const client = context.$client;
21
21
  const name = normalizeSlackReactionName(emoji);
22
22
  try {
@@ -1,20 +1,21 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentChannel } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
6
  import { editSlackContent } from '@zhin.js/adapter-slack';
6
7
  export default defineAgentTool({
7
- description: '编辑 Slack 消息',
8
+ description: '编辑当前 Slack 频道(或私信)中你发出的消息',
8
9
  inputSchema: z.object({
9
- channel: z.string().describe('频道 ID'),
10
- message_ts: z.string().describe('消息时间戳'),
10
+ message_ts: z.string().describe('当前频道中的消息时间戳'),
11
11
  text: z.string().describe('新的消息文本'),
12
12
  }),
13
13
  adapter: 'slack',
14
14
  tags: ['slack'],
15
- async execute({ channel, message_ts, text }, context) {
15
+ async execute({ message_ts, text }, context) {
16
+ const channel = currentChannel(context, { allowDirect: true });
16
17
  const client = context.$client;
17
- await editSlackContent(client, { channel: channel, ts: message_ts, content: [
18
+ await editSlackContent(client, { channel, ts: message_ts, content: [
18
19
  { type: 'text', data: { text } },
19
20
  ] });
20
21
  return { success: true, message: t(context.locale, 'messageEdited') };
@@ -1,24 +1,24 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentChannel } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { editSlackContent } from '@zhin.js/adapter-slack';
5
6
 
6
7
  export default defineAgentTool<{
7
- channel: string;
8
8
  message_ts: string;
9
9
  text: string;
10
10
  }>({
11
- description: '编辑 Slack 消息',
11
+ description: '编辑当前 Slack 频道(或私信)中你发出的消息',
12
12
  inputSchema: z.object({
13
- channel: z.string().describe('频道 ID'),
14
- message_ts: z.string().describe('消息时间戳'),
13
+ message_ts: z.string().describe('当前频道中的消息时间戳'),
15
14
  text: z.string().describe('新的消息文本'),
16
15
  }),
17
16
  adapter: 'slack',
18
17
  tags: ['slack'],
19
- async execute({ channel, message_ts, text }, context) {
18
+ async execute({ message_ts, text }, context) {
19
+ const channel = currentChannel(context, { allowDirect: true });
20
20
  const client = context.$client;
21
- await editSlackContent(client, { channel: channel, ts: message_ts, content: [
21
+ await editSlackContent(client, { channel, ts: message_ts, content: [
22
22
  { type: 'text', data: { text } },
23
23
  ] });
24
24
  return { success: true, message: t(context.locale, 'messageEdited') };
@@ -1,18 +1,18 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentChannel } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
- import { platformPermission } from '@zhin.js/permission';
6
6
  export default defineAgentTool({
7
- description: '置顶 Slack 消息',
7
+ description: '置顶当前 Slack 会话中的消息',
8
8
  inputSchema: z.object({
9
- channel: z.string().describe('频道 ID'),
10
9
  timestamp: z.string().describe('消息时间戳'),
11
10
  }),
12
11
  adapter: 'slack',
13
12
  tags: ['slack'],
14
- permissions: [platformPermission('slack', 'channel_manager')],
15
- async execute({ channel, timestamp }, context) {
13
+ permissions: ['admin'],
14
+ async execute({ timestamp }, context) {
15
+ const channel = currentChannel(context, { allowDirect: true });
16
16
  const client = context.$client;
17
17
  await client.pins.add({ channel, timestamp });
18
18
  const success = true;
@@ -1,21 +1,20 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentChannel } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
5
 
6
6
  export default defineAgentTool<{
7
- channel: string;
8
7
  timestamp: string;
9
8
  }>({
10
- description: '置顶 Slack 消息',
9
+ description: '置顶当前 Slack 会话中的消息',
11
10
  inputSchema: z.object({
12
- channel: z.string().describe('频道 ID'),
13
11
  timestamp: z.string().describe('消息时间戳'),
14
12
  }),
15
13
  adapter: 'slack',
16
14
  tags: ['slack'],
17
- permissions: [platformPermission('slack', 'channel_manager')],
18
- async execute({ channel, timestamp }, context) {
15
+ permissions: ['admin'],
16
+ async execute({ timestamp }, context) {
17
+ const channel = currentChannel(context, { allowDirect: true });
19
18
  const client = context.$client;
20
19
  await client.pins.add({ channel, timestamp });
21
20
  const success = true;
@@ -1,18 +1,19 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentChannel } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
6
  import { normalizeSlackReactionName } from '@zhin.js/adapter-slack';
6
7
  export default defineAgentTool({
7
- description: '移除 Slack 消息上的表情反应',
8
+ description: '移除当前 Slack 频道(或私信)中消息上的表情反应',
8
9
  inputSchema: z.object({
9
- channel_id: z.string().describe('频道 ID'),
10
- timestamp: z.string().describe('消息时间戳'),
10
+ timestamp: z.string().describe('当前频道中的消息时间戳'),
11
11
  name: z.string().describe('表情名称(如 thumbsup、heart)'),
12
12
  }),
13
13
  adapter: 'slack',
14
14
  tags: ['slack'],
15
- async execute({ channel_id, timestamp, name }, context) {
15
+ async execute({ timestamp, name }, context) {
16
+ const channel_id = currentChannel(context, { allowDirect: true });
16
17
  const client = context.$client;
17
18
  try {
18
19
  await client.reactions.remove({
@@ -1,22 +1,22 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentChannel } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { normalizeSlackReactionName } from '@zhin.js/adapter-slack';
5
6
 
6
7
  export default defineAgentTool<{
7
- channel_id: string;
8
8
  timestamp: string;
9
9
  name: string;
10
10
  }>({
11
- description: '移除 Slack 消息上的表情反应',
11
+ description: '移除当前 Slack 频道(或私信)中消息上的表情反应',
12
12
  inputSchema: z.object({
13
- channel_id: z.string().describe('频道 ID'),
14
- timestamp: z.string().describe('消息时间戳'),
13
+ timestamp: z.string().describe('当前频道中的消息时间戳'),
15
14
  name: z.string().describe('表情名称(如 thumbsup、heart)'),
16
15
  }),
17
16
  adapter: 'slack',
18
17
  tags: ['slack'],
19
- async execute({ channel_id, timestamp, name }, context) {
18
+ async execute({ timestamp, name }, context) {
19
+ const channel_id = currentChannel(context, { allowDirect: true });
20
20
  const client = context.$client;
21
21
  try {
22
22
  await client.reactions.remove({
@@ -1,18 +1,18 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentChannel } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
- import { platformPermission } from '@zhin.js/permission';
6
6
  export default defineAgentTool({
7
- description: '取消 Slack 频道中消息的置顶',
7
+ description: '取消当前 Slack 会话中消息的置顶',
8
8
  inputSchema: z.object({
9
- channel_id: z.string().describe('频道 ID'),
10
9
  timestamp: z.string().describe('消息时间戳'),
11
10
  }),
12
11
  adapter: 'slack',
13
12
  tags: ['slack'],
14
- permissions: [platformPermission('slack', 'channel_manager')],
15
- async execute({ channel_id, timestamp }, context) {
13
+ permissions: ['admin'],
14
+ async execute({ timestamp }, context) {
15
+ const channel_id = currentChannel(context, { allowDirect: true });
16
16
  const client = context.$client;
17
17
  await client.pins.remove({ channel: channel_id, timestamp });
18
18
  const success = true;
@@ -1,21 +1,20 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentChannel } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
5
 
6
6
  export default defineAgentTool<{
7
- channel_id: string;
8
7
  timestamp: string;
9
8
  }>({
10
- description: '取消 Slack 频道中消息的置顶',
9
+ description: '取消当前 Slack 会话中消息的置顶',
11
10
  inputSchema: z.object({
12
- channel_id: z.string().describe('频道 ID'),
13
11
  timestamp: z.string().describe('消息时间戳'),
14
12
  }),
15
13
  adapter: 'slack',
16
14
  tags: ['slack'],
17
- permissions: [platformPermission('slack', 'channel_manager')],
18
- async execute({ channel_id, timestamp }, context) {
15
+ permissions: ['admin'],
16
+ async execute({ timestamp }, context) {
17
+ const channel_id = currentChannel(context, { allowDirect: true });
19
18
  const client = context.$client;
20
19
  await client.pins.remove({ channel: channel_id, timestamp });
21
20
  const success = true;
@@ -2,17 +2,125 @@ export const slackConsoleSpec = {
2
2
  adapterKey: 'slack',
3
3
  adapterDisplayName: 'Slack',
4
4
  fields: [
5
- { key: 'token', required: true, env: true, description: 'Bot User OAuth Token(xoxb-...)' },
6
- { key: 'signingSecret', env: true, description: '签名密钥(HTTP Events,socketMode: false 必填)', descriptionI18n: { en: 'Signing secret (required for HTTP Events)' } },
7
- { key: 'appToken', env: true, description: 'App-Level Token(xapp-...,Socket Mode)', descriptionI18n: { en: 'App-level token (xapp-..., Socket Mode)' } },
8
- { key: 'socketMode', type: 'boolean', description: 'Socket Mode; false selects HTTP Events' },
9
- { key: 'streaming', type: 'boolean', description: '生成时逐步显示回复', descriptionI18n: { en: 'Show replies progressively while generating' } },
10
- { key: 'streamingIntervalMs', type: 'number', description: '回复更新间隔(毫秒)', descriptionI18n: { en: 'Reply update interval in milliseconds' } },
11
- { key: 'webhookPath', description: 'HTTP Events route' },
12
- { key: 'clientPingTimeout', type: 'number', description: 'SDK client ping timeout in milliseconds' },
13
- { key: 'webApiProxy.port', type: 'number', description: 'Configured Web API loopback proxy port' },
14
- { key: 'streamProxy.port', type: 'number', description: 'Configured Socket Mode loopback proxy port' },
15
- { key: 'streamProxy.serverName', description: 'Expected Socket Mode TLS hostname' },
5
+ {
6
+ key: 'token',
7
+ required: true,
8
+ env: true,
9
+ label: 'Bot User OAuth Token',
10
+ labelI18n: { en: 'Bot User OAuth Token' },
11
+ group: '基础认证',
12
+ groupI18n: { en: 'Basic Auth' },
13
+ placeholder: 'xoxb-...',
14
+ description: 'Bot User OAuth Token(xoxb-...)',
15
+ descriptionI18n: { en: 'Bot User OAuth Token (xoxb-...)' },
16
+ },
17
+ {
18
+ key: 'appToken',
19
+ env: true,
20
+ label: 'App-Level Token (Socket Mode)',
21
+ labelI18n: { en: 'App-Level Token' },
22
+ group: '基础认证',
23
+ groupI18n: { en: 'Basic Auth' },
24
+ placeholder: 'xapp-...',
25
+ description: 'App-Level Token(xapp-...,Socket Mode)',
26
+ descriptionI18n: { en: 'App-level token (xapp-..., Socket Mode)' },
27
+ },
28
+ {
29
+ key: 'signingSecret',
30
+ env: true,
31
+ label: 'Signing Secret (签名密钥)',
32
+ labelI18n: { en: 'Signing Secret' },
33
+ group: '基础认证',
34
+ groupI18n: { en: 'Basic Auth' },
35
+ placeholder: '32 位十六进制签名密钥',
36
+ placeholderI18n: { en: 'Slack app signing secret' },
37
+ description: '签名密钥(HTTP Events,socketMode: false 必填)',
38
+ descriptionI18n: { en: 'Signing secret (required for HTTP Events)' },
39
+ },
40
+ {
41
+ key: 'socketMode',
42
+ type: 'boolean',
43
+ label: '启用 Socket Mode',
44
+ labelI18n: { en: 'Enable Socket Mode' },
45
+ group: '连接与回调',
46
+ groupI18n: { en: 'Connection & Webhook' },
47
+ description: '开启后使用 WebSocket 长连接;关闭则使用 HTTP Events 回调',
48
+ descriptionI18n: { en: 'Socket Mode; false selects HTTP Events' },
49
+ },
50
+ {
51
+ key: 'webhookPath',
52
+ label: 'HTTP Events 本地路由',
53
+ labelI18n: { en: 'HTTP Events Local Path' },
54
+ group: '连接与回调',
55
+ groupI18n: { en: 'Connection & Webhook' },
56
+ placeholder: '/slack/events',
57
+ description: 'HTTP Events 模式下监听的本地路由',
58
+ descriptionI18n: { en: 'HTTP Events route' },
59
+ },
60
+ {
61
+ key: 'clientPingTimeout',
62
+ type: 'number',
63
+ label: '心跳超时时间 (ms)',
64
+ labelI18n: { en: 'Client Ping Timeout (ms)' },
65
+ group: '连接与回调',
66
+ groupI18n: { en: 'Connection & Webhook' },
67
+ placeholder: '5000',
68
+ description: 'Socket Mode 客户端心跳超时毫秒数',
69
+ descriptionI18n: { en: 'SDK client ping timeout in milliseconds' },
70
+ },
71
+ {
72
+ key: 'streaming',
73
+ type: 'boolean',
74
+ label: '流式回复',
75
+ labelI18n: { en: 'Streaming Reply' },
76
+ group: '流式体验与代理',
77
+ groupI18n: { en: 'Streaming & Proxy' },
78
+ description: '生成时逐步显示回复',
79
+ descriptionI18n: { en: 'Show replies progressively while generating' },
80
+ },
81
+ {
82
+ key: 'streamingIntervalMs',
83
+ type: 'number',
84
+ label: '流式刷新间隔 (ms)',
85
+ labelI18n: { en: 'Streaming Interval (ms)' },
86
+ group: '流式体验与代理',
87
+ groupI18n: { en: 'Streaming & Proxy' },
88
+ placeholder: '500',
89
+ description: '回复更新间隔(毫秒)',
90
+ descriptionI18n: { en: 'Reply update interval in milliseconds' },
91
+ },
92
+ {
93
+ key: 'webApiProxy.port',
94
+ type: 'number',
95
+ label: 'Web API 代理端口',
96
+ labelI18n: { en: 'Web API Proxy Port' },
97
+ group: '流式体验与代理',
98
+ groupI18n: { en: 'Streaming & Proxy' },
99
+ placeholder: '例如 7890',
100
+ description: '本地回环 Web API 代理端口(可选)',
101
+ descriptionI18n: { en: 'Configured Web API loopback proxy port' },
102
+ },
103
+ {
104
+ key: 'streamProxy.port',
105
+ type: 'number',
106
+ label: 'Socket Mode 代理端口',
107
+ labelI18n: { en: 'Socket Mode Proxy Port' },
108
+ group: '流式体验与代理',
109
+ groupI18n: { en: 'Streaming & Proxy' },
110
+ placeholder: '例如 7890',
111
+ description: '本地回环 Socket Mode 代理端口(可选)',
112
+ descriptionI18n: { en: 'Configured Socket Mode loopback proxy port' },
113
+ },
114
+ {
115
+ key: 'streamProxy.serverName',
116
+ label: 'Socket Mode TLS 主机名',
117
+ labelI18n: { en: 'Socket Mode TLS Server Name' },
118
+ group: '流式体验与代理',
119
+ groupI18n: { en: 'Streaming & Proxy' },
120
+ placeholder: 'wss-primary.slack.com',
121
+ description: '代理校验的 Socket Mode TLS 主机名(可选)',
122
+ descriptionI18n: { en: 'Expected Socket Mode TLS hostname' },
123
+ },
16
124
  ],
17
125
  docsUrl: 'https://zhin.js.org/adapters/slack',
18
126
  readPermission: 'slack:read',
package/lib/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { formatInboundContent, formatInteractionContent, formatOutboundWire, formatSlashContent, headerValue, keyboardToBlockKitBlocks, normalizeWebhookPath, readTextBody, resolveSlackChannelType, resolveSlackConfig, slackInboundConversation, verifySlackSignature, type ResolvedSlackConfig, type SlackEndpointConfig, type SlackBlockAction, type SlackEvent, type SlackEventEnvelope, type SlackInteractionPayload, type SlackMessageEvent, type SlackSlashCommand, type SlackUrlVerification, type SlackWireSegment, } from './protocol.js';
1
+ export { formatInboundContent, formatInteractionContent, formatOutboundWire, formatSlashContent, headerValue, keyboardToBlockKitBlocks, normalizeWebhookPath, resolveSlackChannelType, resolveSlackConfig, slackInboundConversation, verifySlackSignature, type ResolvedSlackConfig, type SlackEndpointConfig, type SlackBlockAction, type SlackEvent, type SlackEventEnvelope, type SlackInteractionPayload, type SlackMessageEvent, type SlackSlashCommand, type SlackUrlVerification, type SlackWireSegment, } from './protocol.js';
2
2
  export { SlackEndpoint, type SlackEndpointOptions, type SlackSocketLike, type SlackWebClientLike, } from './endpoint.js';
3
3
  export { registerSlackWebhookRoutes, handleSlackWebhookRequest, type SlackWebhookHandler, } from './webhook.js';
4
4
  export { type SlackClientEventMap, type SlackUserInfo, } from './client.js';
5
- export { checkSlackPlatformPermit, normalizeSlackSenderForPermit, platformPermit, slackGroupPermitResolver, } from './platform-permit.js';
5
+ export { platformPermit } from './platform-permit.js';
6
6
  export { normalizeSlackReactionName } from './slack-reaction.js';
7
7
  export { markdownToMrkdwn, mrkdwnToPlainFallback, splitMrkdwnText } from './markdown-to-mrkdwn.js';
8
8
  export { mrkdwnToMarkdown } from './mrkdwn-to-markdown.js';
package/lib/index.js CHANGED
@@ -1,7 +1,7 @@
1
- export { formatInboundContent, formatInteractionContent, formatOutboundWire, formatSlashContent, headerValue, keyboardToBlockKitBlocks, normalizeWebhookPath, readTextBody, resolveSlackChannelType, resolveSlackConfig, slackInboundConversation, verifySlackSignature, } from './protocol.js';
1
+ export { formatInboundContent, formatInteractionContent, formatOutboundWire, formatSlashContent, headerValue, keyboardToBlockKitBlocks, normalizeWebhookPath, resolveSlackChannelType, resolveSlackConfig, slackInboundConversation, verifySlackSignature, } from './protocol.js';
2
2
  export { SlackEndpoint, } from './endpoint.js';
3
3
  export { registerSlackWebhookRoutes, handleSlackWebhookRequest, } from './webhook.js';
4
- export { checkSlackPlatformPermit, normalizeSlackSenderForPermit, platformPermit, slackGroupPermitResolver, } from './platform-permit.js';
4
+ export { platformPermit } from './platform-permit.js';
5
5
  export { normalizeSlackReactionName } from './slack-reaction.js';
6
6
  export { markdownToMrkdwn, mrkdwnToPlainFallback, splitMrkdwnText } from './markdown-to-mrkdwn.js';
7
7
  export { mrkdwnToMarkdown } from './mrkdwn-to-markdown.js';
@@ -1,15 +1,7 @@
1
1
  /**
2
- * Slack platform permit — workspace + channel 权限
2
+ * Slack platform permit helper(ADR 0056 §5)。
3
+ *
4
+ * 平台身份由适配器上报到 `sender.platform`,permit 由内置评估器(`@zhin.js/permission`)判断;
5
+ * 适配器不再导出自有的 permit 解析器或检查函数。
3
6
  */
4
- import type { PermissionSubject } from '@zhin.js/permission';
5
7
  export declare function platformPermit(perm: string): string;
6
- export declare function slackGroupPermitResolver(logicalPerm: string): string;
7
- export declare function normalizeSlackSenderForPermit(input: {
8
- isWorkspaceOwner?: boolean;
9
- isWorkspaceAdmin?: boolean;
10
- isChannelManager?: boolean;
11
- }): {
12
- role?: string;
13
- permissions?: string[];
14
- };
15
- export declare function checkSlackPlatformPermit(perm: string, subject: PermissionSubject): boolean;
@@ -1,43 +1,9 @@
1
- const ADAPTER = 'slack';
1
+ /**
2
+ * Slack platform permit helper(ADR 0056 §5)。
3
+ *
4
+ * 平台身份由适配器上报到 `sender.platform`,permit 由内置评估器(`@zhin.js/permission`)判断;
5
+ * 适配器不再导出自有的 permit 解析器或检查函数。
6
+ */
2
7
  export function platformPermit(perm) {
3
- return `platform(${ADAPTER},${perm})`;
4
- }
5
- const FACTORY_PERM_MAP = {
6
- scene_admin: 'channel_manager',
7
- scene_owner: 'workspace_owner',
8
- };
9
- export function slackGroupPermitResolver(logicalPerm) {
10
- return platformPermit(FACTORY_PERM_MAP[logicalPerm] ?? logicalPerm);
11
- }
12
- export function normalizeSlackSenderForPermit(input) {
13
- const permissions = [];
14
- if (input.isWorkspaceOwner) {
15
- permissions.push('workspace_owner', 'workspace_admin', 'channel_manager');
16
- return { role: 'owner', permissions };
17
- }
18
- if (input.isWorkspaceAdmin) {
19
- permissions.push('workspace_admin', 'channel_manager');
20
- return { role: 'admin', permissions };
21
- }
22
- if (input.isChannelManager) {
23
- permissions.push('channel_manager');
24
- return { role: 'channel_admin', permissions };
25
- }
26
- return { role: 'member', permissions };
27
- }
28
- export function checkSlackPlatformPermit(perm, subject) {
29
- const role = subject.sender?.role?.[0];
30
- const permissions = subject.sender?.permissions ?? [];
31
- const has = (t) => permissions.includes(t);
32
- switch (perm) {
33
- case 'workspace_owner':
34
- return role === 'owner' || has('workspace_owner');
35
- case 'workspace_admin':
36
- return role === 'owner' || role === 'admin' || has('workspace_admin') || has('workspace_owner');
37
- case 'channel_manager':
38
- return role === 'owner' || role === 'admin' || role === 'channel_admin'
39
- || has('channel_manager') || has('workspace_admin') || has('workspace_owner');
40
- default:
41
- return false;
42
- }
8
+ return `platform-permission:${perm}`;
43
9
  }
package/lib/protocol.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { EndpointProfileConfiguration } from 'zhin.js/adapter';
2
- import type { IncomingMessage } from 'node:http';
3
2
  import { type ConversationRef } from '@zhin.js/im-contract';
4
3
  /** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
5
4
  export interface SlackEndpointConfig extends EndpointProfileConfiguration {
@@ -156,7 +155,4 @@ export declare function formatOutboundWire(payload: unknown): {
156
155
  };
157
156
  export declare function keyboardToBlockKitBlocks(data: Record<string, unknown>): SlackBlock[];
158
157
  export declare function verifySlackSignature(signingSecret: string, rawBody: string, timestamp: string, signature: string): boolean;
159
- export declare function readTextBody(request: IncomingMessage, options?: {
160
- readonly limit?: number;
161
- }): Promise<string>;
162
- export declare function headerValue(headers: IncomingMessage['headers'], name: string): string;
158
+ export declare function headerValue(headers: Headers, name: string): string;
package/lib/protocol.js CHANGED
@@ -265,24 +265,6 @@ export function verifySlackSignature(signingSecret, rawBody, timestamp, signatur
265
265
  return false;
266
266
  return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
267
267
  }
268
- export async function readTextBody(request, options = {}) {
269
- const limit = options.limit ?? 1_048_576;
270
- const chunks = [];
271
- let size = 0;
272
- for await (const chunk of request) {
273
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
274
- size += buffer.length;
275
- if (size > limit) {
276
- request.destroy();
277
- throw new Error(`Request body exceeds ${limit} bytes`);
278
- }
279
- chunks.push(buffer);
280
- }
281
- return Buffer.concat(chunks).toString('utf8');
282
- }
283
268
  export function headerValue(headers, name) {
284
- const raw = headers[name.toLowerCase()];
285
- if (Array.isArray(raw))
286
- return raw[0] ?? '';
287
- return raw ?? '';
269
+ return headers.get(name) ?? '';
288
270
  }
@@ -4,4 +4,3 @@ export declare function parseSlackMessageRef(ref: string): {
4
4
  channel: string;
5
5
  ts: string;
6
6
  } | null;
7
- export declare function slackMessageTs(ref: string): string;
@@ -12,6 +12,3 @@ export function parseSlackMessageRef(ref) {
12
12
  return null;
13
13
  return { channel, ts };
14
14
  }
15
- export function slackMessageTs(ref) {
16
- return parseSlackMessageRef(ref)?.ts ?? ref;
17
- }
package/lib/webhook.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Slack webhook HTTP: signature → parse → admit.
3
3
  */
4
- import type { IncomingMessage, ServerResponse } from 'node:http';
5
4
  import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
6
5
  import { type ResolvedSlackConfig, type SlackInteractionPayload, type SlackSlashCommand } from './protocol.js';
7
6
  export interface SlackWebhookHandler {
@@ -11,4 +10,4 @@ export interface SlackWebhookHandler {
11
10
  admitSlashCommand(cmd: SlackSlashCommand): void;
12
11
  }
13
12
  export declare function registerSlackWebhookRoutes(http: HttpHost, handler: SlackWebhookHandler): HttpRouteRegistration[];
14
- export declare function handleSlackWebhookRequest(request: IncomingMessage, response: ServerResponse, handler: SlackWebhookHandler): Promise<void>;
13
+ export declare function handleSlackWebhookRequest(request: Request, handler: SlackWebhookHandler): Promise<Response>;