@openclaw/slack 2026.5.14-beta.1 → 2026.5.14-beta.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 (83) hide show
  1. package/dist/{action-runtime-gtC-RM3r.js → action-runtime-CyE2jfW-.js} +4 -4
  2. package/dist/action-runtime.runtime-DLhfKw4B.js +2 -0
  3. package/dist/{media-B-nNpS2G.js → actions-BibhOXpJ.js} +307 -2
  4. package/dist/{actions.runtime-DD6hfFCA.js → actions.runtime-B9XQG6X4.js} +1 -1
  5. package/dist/api.js +16 -16
  6. package/dist/{approval-handler.runtime-DeYBuIaU.js → approval-handler.runtime-BjzVRaXN.js} +3 -4
  7. package/dist/{blocks-render-BdLueE_v.js → blocks-render-BAVfd6r0.js} +1 -1
  8. package/dist/{channel-CC04F-xs.js → channel-Dh07mU_K.js} +23 -27
  9. package/dist/channel-config-api.js +1 -1
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/{channel.setup-jzYjY634.js → channel.setup-CmG37S2W.js} +3 -3
  12. package/dist/{client-8r7r7aZ3.js → client-C_IaJbi5.js} +20 -1
  13. package/dist/{config-schema-Bueih4yH.js → config-schema-CNRousxw.js} +1 -1
  14. package/dist/contract-api.js +4 -4
  15. package/dist/directory-contract-api.js +1 -1
  16. package/dist/{directory-live-CuaWaGnM.js → directory-live-CZPzpQZF.js} +1 -1
  17. package/dist/{doctor-contract-DCkS8eNN.js → doctor-contract-B8QIWMs1.js} +1 -1
  18. package/dist/doctor-contract-api.js +1 -1
  19. package/dist/http-routes-api.js +1 -1
  20. package/dist/inbound-contract-test-api.js +2 -2
  21. package/dist/interactive-replies-api.js +1 -1
  22. package/dist/{message-tool-api-B_bKUmP0.js → message-tool-api-C7gc7goF.js} +1 -1
  23. package/dist/message-tool-api.js +1 -1
  24. package/dist/{monitor-B3QB1ysK.js → monitor-DDE5AI2O.js} +3 -3
  25. package/dist/{outbound-adapter-DsAvCwpZ.js → outbound-adapter-BluPNDNi.js} +4 -5
  26. package/dist/outbound-payload-test-api.js +1 -1
  27. package/dist/{outbound-payload.test-harness-DM9ZdY2f.js → outbound-payload.test-harness-BNxnP6MC.js} +2 -2
  28. package/dist/{pipeline.runtime-D-YJZZaI.js → pipeline.runtime-Dft2-QU4.js} +11 -12
  29. package/dist/{plugin-routes-Dt_jh9W8.js → plugin-routes-CRnfsTTX.js} +1 -1
  30. package/dist/{prepare-CXI8nHbJ.js → prepare-D0tMg4dt.js} +8 -9
  31. package/dist/{prepare.test-helpers-BhFHtbz3.js → prepare.test-helpers-CU1qB54Q.js} +1 -1
  32. package/dist/{probe-D1wYA05H.js → probe-FL4sUJsH.js} +2 -2
  33. package/dist/{provider-Ut7IF0Mn.js → provider-C6WxaFFf.js} +21 -19
  34. package/dist/{replies-CzfjCaLG.js → replies-D0QXXSPP.js} +4 -4
  35. package/dist/reply-blocks-BFaJ_ejG.js +134 -0
  36. package/dist/{resolve-channels-BiVxSLVm.js → resolve-channels-B_eKaOkE.js} +2 -2
  37. package/dist/{resolve-users-CcpSlYw-.js → resolve-users-BzBAJwvq.js} +2 -2
  38. package/dist/{room-context-D0hGOp8m.js → room-context-Cd8jFpS-.js} +2 -2
  39. package/dist/{runtime-api-D8wiG9BS.js → runtime-api-B5HGOzX3.js} +2 -2
  40. package/dist/runtime-api.js +12 -12
  41. package/dist/runtime-setter-api.js +1 -1
  42. package/dist/{scopes-BTkB8PPE.js → scopes-Bvg_ZzqZ.js} +2 -2
  43. package/dist/secret-contract-api.js +1 -1
  44. package/dist/security-contract-api.js +1 -1
  45. package/dist/{send-ioky2Xpy.js → send-Dg9zcyYT.js} +4 -5
  46. package/dist/send.runtime-CjjQ9StM.js +2 -0
  47. package/dist/send.runtime-E47jGN-2.js +2 -0
  48. package/dist/setup-plugin-api.js +1 -1
  49. package/dist/{setup-surface-B6w9gtds.js → setup-surface-BLoTgna4.js} +4 -4
  50. package/dist/{shared-CSiHkaVO.js → shared-GoB-OuUq.js} +7 -7
  51. package/dist/{slash-dispatch.runtime-DNr1EDON.js → slash-dispatch.runtime-Bz_OkRcR.js} +1 -1
  52. package/dist/test-api.js +7 -7
  53. package/dist/thread-ts-As_dcNbD.js +52 -0
  54. package/package.json +5 -5
  55. package/dist/action-runtime.runtime-DbVd7_Na.js +0 -2
  56. package/dist/actions-Cqyj7oRr.js +0 -309
  57. package/dist/approval-auth-D3xf0sS6.js +0 -28
  58. package/dist/blocks-input-BJZ8vv03.js +0 -29
  59. package/dist/channel-api-BfBK89IN.js +0 -20
  60. package/dist/exec-approvals-BLn4Zx7V.js +0 -58
  61. package/dist/group-policy-utF2iWnE.js +0 -41
  62. package/dist/mrkdwn-18IzcEAY.js +0 -6
  63. package/dist/reply-blocks-DWoZrUll.js +0 -14
  64. package/dist/send.runtime-5Kl3Wzbf.js +0 -2
  65. package/dist/send.runtime-DoifekaA.js +0 -2
  66. package/dist/thread-ts-o-QBwB3k.js +0 -24
  67. /package/dist/{accounts.runtime-CkfFIisb.js → accounts.runtime-BhbEu1ZK.js} +0 -0
  68. /package/dist/{allow-list-T7ZDpUsF.js → allow-list-nwXs_eCP.js} +0 -0
  69. /package/dist/{config-api-B48Z4H47.js → config-api-CmgE_ORg.js} +0 -0
  70. /package/dist/{directory-config-BKKNBkCq.js → directory-config-CMvFiswf.js} +0 -0
  71. /package/dist/{errors-BrtayXHa.js → errors-C_sW0Zgl.js} +0 -0
  72. /package/dist/{interactive-replies-CawNPL-h.js → interactive-replies-BSg5hXhj.js} +0 -0
  73. /package/dist/{magic-string.es-BLAi6qQC.js → magic-string.es-9lw4MGoF.js} +0 -0
  74. /package/dist/{registry-BdfKYina.js → registry-D2cWOLZV.js} +0 -0
  75. /package/dist/{resolve-allowlist-common-rhfyDyWi.js → resolve-allowlist-common-DLub2I2i.js} +0 -0
  76. /package/dist/{runtime--VlVtTPu.js → runtime-DQxkf7k2.js} +0 -0
  77. /package/dist/{secret-contract-BurGIyhv.js → secret-contract-0TL3L5Kb.js} +0 -0
  78. /package/dist/{security-audit-DvOpSaZM.js → security-audit-BJzADAw3.js} +0 -0
  79. /package/dist/{setup-core-DgLJ7dQY.js → setup-core-WWQl-cE9.js} +0 -0
  80. /package/dist/{slash-commands.runtime-DRkNgIQ2.js → slash-commands.runtime-bcDwsGnu.js} +0 -0
  81. /package/dist/{slash-plugin-commands.runtime-Dj5h8hmv.js → slash-plugin-commands.runtime-DBHGUSj2.js} +0 -0
  82. /package/dist/{slash-skill-commands.runtime-B-_KAk0C.js → slash-skill-commands.runtime-rrY2hXvN.js} +0 -0
  83. /package/dist/{streaming-compat-C6rySwiD.js → streaming-compat-eu5Rj5gj.js} +0 -0
package/dist/test-api.js CHANGED
@@ -1,8 +1,8 @@
1
- import { a as createSlackActions, t as slackPlugin } from "./channel-CC04F-xs.js";
2
- import { n as setSlackRuntime } from "./runtime--VlVtTPu.js";
3
- import { t as sendMessageSlack } from "./send-ioky2Xpy.js";
4
- import { t as prepareSlackMessage } from "./prepare-CXI8nHbJ.js";
5
- import { t as createInboundSlackTestContext } from "./prepare.test-helpers-BhFHtbz3.js";
6
- import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-DM9ZdY2f.js";
7
- import { n as slackOutbound } from "./outbound-adapter-DsAvCwpZ.js";
1
+ import { a as createSlackActions, t as slackPlugin } from "./channel-Dh07mU_K.js";
2
+ import { n as setSlackRuntime } from "./runtime-DQxkf7k2.js";
3
+ import { t as sendMessageSlack } from "./send-Dg9zcyYT.js";
4
+ import { t as prepareSlackMessage } from "./prepare-D0tMg4dt.js";
5
+ import { t as createInboundSlackTestContext } from "./prepare.test-helpers-CU1qB54Q.js";
6
+ import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-BNxnP6MC.js";
7
+ import { n as slackOutbound } from "./outbound-adapter-BluPNDNi.js";
8
8
  export { createInboundSlackTestContext, createSlackActions, createSlackOutboundPayloadHarness, prepareSlackMessage, sendMessageSlack, setSlackRuntime, slackOutbound, slackPlugin };
@@ -0,0 +1,52 @@
1
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ //#region extensions/slack/src/truncate.ts
3
+ function truncateSlackText(value, max) {
4
+ const trimmed = value.trim();
5
+ if (trimmed.length <= max) return trimmed;
6
+ if (max <= 1) return trimmed.slice(0, max);
7
+ return `${trimmed.slice(0, max - 1)}…`;
8
+ }
9
+ //#endregion
10
+ //#region extensions/slack/src/limits.ts
11
+ const SLACK_TEXT_LIMIT = 8e3;
12
+ //#endregion
13
+ //#region extensions/slack/src/blocks-input.ts
14
+ const SLACK_MAX_BLOCKS = 50;
15
+ function parseBlocksJson(raw) {
16
+ try {
17
+ return JSON.parse(raw);
18
+ } catch {
19
+ throw new Error("blocks must be valid JSON");
20
+ }
21
+ }
22
+ function assertBlocksArray(raw) {
23
+ if (!Array.isArray(raw)) throw new Error("blocks must be an array");
24
+ if (raw.length === 0) throw new Error("blocks must contain at least one block");
25
+ if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
26
+ for (const block of raw) {
27
+ if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
28
+ const type = block.type;
29
+ if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
30
+ }
31
+ }
32
+ function validateSlackBlocksArray(raw) {
33
+ assertBlocksArray(raw);
34
+ return raw;
35
+ }
36
+ function parseSlackBlocksInput(raw) {
37
+ if (raw == null) return;
38
+ return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
39
+ }
40
+ //#endregion
41
+ //#region extensions/slack/src/thread-ts.ts
42
+ const SLACK_THREAD_TS_PATTERN = /^\d+\.\d+$/;
43
+ function normalizeSlackThreadTsCandidate(value) {
44
+ if (typeof value !== "string") return;
45
+ const normalized = normalizeOptionalString(value);
46
+ return normalized && SLACK_THREAD_TS_PATTERN.test(normalized) ? normalized : void 0;
47
+ }
48
+ function resolveSlackThreadTsValue(params) {
49
+ return normalizeSlackThreadTsCandidate(params.replyToId) ?? normalizeSlackThreadTsCandidate(params.threadId);
50
+ }
51
+ //#endregion
52
+ export { validateSlackBlocksArray as a, parseSlackBlocksInput as i, resolveSlackThreadTsValue as n, SLACK_TEXT_LIMIT as o, SLACK_MAX_BLOCKS as r, truncateSlackText as s, normalizeSlackThreadTsCandidate as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/slack",
3
- "version": "2026.5.14-beta.1",
3
+ "version": "2026.5.14-beta.2",
4
4
  "description": "OpenClaw Slack channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,7 +10,7 @@
10
10
  "dependencies": {
11
11
  "@slack/bolt": "4.7.2",
12
12
  "@slack/types": "2.21.1",
13
- "@slack/web-api": "7.15.2",
13
+ "@slack/web-api": "7.16.0",
14
14
  "https-proxy-agent": "9.0.0",
15
15
  "typebox": "1.1.38",
16
16
  "zod": "4.4.3"
@@ -20,7 +20,7 @@
20
20
  "openclaw": "workspace:*"
21
21
  },
22
22
  "peerDependencies": {
23
- "openclaw": ">=2026.5.14-beta.1"
23
+ "openclaw": ">=2026.5.14-beta.2"
24
24
  },
25
25
  "peerDependenciesMeta": {
26
26
  "openclaw": {
@@ -64,10 +64,10 @@
64
64
  "minHostVersion": ">=2026.5.12-beta.1"
65
65
  },
66
66
  "compat": {
67
- "pluginApi": ">=2026.5.14-beta.1"
67
+ "pluginApi": ">=2026.5.14-beta.2"
68
68
  },
69
69
  "build": {
70
- "openclawVersion": "2026.5.14-beta.1",
70
+ "openclawVersion": "2026.5.14-beta.2",
71
71
  "bundledDist": false
72
72
  },
73
73
  "release": {
@@ -1,2 +0,0 @@
1
- import { t as handleSlackAction } from "./action-runtime-gtC-RM3r.js";
2
- export { handleSlackAction };
@@ -1,309 +0,0 @@
1
- import { a as resolveSlackAccount, d as resolveSlackBotToken } from "./accounts-yk5K3wQU.js";
2
- import { i as truncateSlackText, r as SLACK_TEXT_LIMIT } from "./thread-ts-o-QBwB3k.js";
3
- import { a as getSlackWriteClient, r as createSlackWebClient } from "./client-8r7r7aZ3.js";
4
- import { r as validateSlackBlocksArray } from "./blocks-input-BJZ8vv03.js";
5
- import { c as buildSlackBlocksFallbackText, t as sendMessageSlack } from "./send-ioky2Xpy.js";
6
- import { n as resolveSlackMedia } from "./media-B-nNpS2G.js";
7
- import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
8
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
9
- import { z } from "zod";
10
- //#region extensions/slack/src/edit-text.ts
11
- function buildSlackEditTextPayload(content, blocks) {
12
- const trimmedContent = content.trim();
13
- if (trimmedContent) return trimmedContent;
14
- if (blocks?.length) return truncateSlackText(buildSlackBlocksFallbackText(blocks), SLACK_TEXT_LIMIT);
15
- return " ";
16
- }
17
- //#endregion
18
- //#region extensions/slack/src/actions.ts
19
- function resolveToken(explicit, accountId, cfg) {
20
- if (explicit?.trim()) {
21
- const token = resolveSlackBotToken(explicit);
22
- if (token) return token;
23
- }
24
- if (!cfg) throw new Error("Slack actions requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
25
- const account = resolveSlackAccount({
26
- cfg: requireRuntimeConfig(cfg, "Slack actions"),
27
- accountId
28
- });
29
- const token = resolveSlackBotToken(account.botToken ?? void 0);
30
- if (!token) {
31
- logVerbose(`slack actions: missing bot token for account=${account.accountId} explicit=${Boolean(explicit)} source=${account.botTokenSource ?? "unknown"}`);
32
- throw new Error("SLACK_BOT_TOKEN or channels.slack.botToken is required for Slack actions");
33
- }
34
- return token;
35
- }
36
- function normalizeEmoji(raw) {
37
- const trimmed = raw.trim();
38
- if (!trimmed) throw new Error("Emoji is required for Slack reactions");
39
- return trimmed.replace(/^:+|:+$/g, "");
40
- }
41
- const SLACK_TIMESTAMP_RE = /^\d+(?:\.\d+)?$/;
42
- const ISO_8601_TIMESTAMP_SCHEMA = z.iso.datetime({ offset: true });
43
- function formatEpochSeconds(milliseconds) {
44
- const seconds = milliseconds / 1e3;
45
- if (Number.isInteger(seconds)) return String(seconds);
46
- return seconds.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
47
- }
48
- function normalizeSlackReadTimestamp(raw, field) {
49
- const trimmed = raw?.trim();
50
- if (!trimmed) return;
51
- if (SLACK_TIMESTAMP_RE.test(trimmed)) return trimmed;
52
- if (!ISO_8601_TIMESTAMP_SCHEMA.safeParse(trimmed).success) throw new Error(`Invalid Slack read ${field} timestamp "${trimmed}": expected a Slack timestamp or ISO-8601 date string`);
53
- const parsed = Date.parse(trimmed);
54
- if (!Number.isFinite(parsed)) throw new Error(`Invalid Slack read ${field} timestamp "${trimmed}": expected a Slack timestamp or ISO-8601 date string`);
55
- return formatEpochSeconds(parsed);
56
- }
57
- function hasSlackPlatformError(err, code) {
58
- if (!err || typeof err !== "object") return false;
59
- const data = err.data;
60
- if (!data || typeof data !== "object") return false;
61
- return data.error === code;
62
- }
63
- async function getClient(opts = {}, mode = "read") {
64
- if (opts.client) return opts.client;
65
- const token = resolveToken(opts.token, opts.accountId, opts.cfg);
66
- return mode === "write" ? getSlackWriteClient(token) : createSlackWebClient(token);
67
- }
68
- async function resolveBotUserId(client) {
69
- const auth = await client.auth.test();
70
- if (!auth?.user_id) throw new Error("Failed to resolve Slack bot user id");
71
- return auth.user_id;
72
- }
73
- async function reactSlackMessage(channelId, messageId, emoji, opts = {}) {
74
- const client = await getClient(opts, "write");
75
- try {
76
- await client.reactions.add({
77
- channel: channelId,
78
- timestamp: messageId,
79
- name: normalizeEmoji(emoji)
80
- });
81
- } catch (err) {
82
- if (hasSlackPlatformError(err, "already_reacted")) return;
83
- throw err;
84
- }
85
- }
86
- async function removeSlackReaction(channelId, messageId, emoji, opts = {}) {
87
- const client = await getClient(opts, "write");
88
- try {
89
- await client.reactions.remove({
90
- channel: channelId,
91
- timestamp: messageId,
92
- name: normalizeEmoji(emoji)
93
- });
94
- } catch (err) {
95
- if (hasSlackPlatformError(err, "no_reaction")) return;
96
- throw err;
97
- }
98
- }
99
- async function removeOwnSlackReactions(channelId, messageId, opts = {}) {
100
- const client = await getClient(opts, "write");
101
- const userId = await resolveBotUserId(client);
102
- const reactions = await listSlackReactions(channelId, messageId, { client });
103
- const toRemove = /* @__PURE__ */ new Set();
104
- for (const reaction of reactions ?? []) {
105
- const name = reaction?.name;
106
- if (!name) continue;
107
- if ((reaction?.users ?? []).includes(userId)) toRemove.add(name);
108
- }
109
- if (toRemove.size === 0) return [];
110
- await Promise.all(Array.from(toRemove, (name) => removeSlackReaction(channelId, messageId, name, {
111
- ...opts,
112
- client
113
- })));
114
- return Array.from(toRemove);
115
- }
116
- async function listSlackReactions(channelId, messageId, opts = {}) {
117
- return (await (await getClient(opts)).reactions.get({
118
- channel: channelId,
119
- timestamp: messageId,
120
- full: true
121
- })).message?.reactions ?? [];
122
- }
123
- async function sendSlackMessage(to, content, opts) {
124
- return await sendMessageSlack(to, content, {
125
- accountId: opts.accountId,
126
- cfg: opts.cfg,
127
- token: opts.token,
128
- mediaUrl: opts.mediaUrl,
129
- mediaAccess: opts.mediaAccess,
130
- mediaLocalRoots: opts.mediaLocalRoots,
131
- mediaReadFile: opts.mediaReadFile,
132
- client: opts.client,
133
- threadTs: opts.threadTs,
134
- replyBroadcast: opts.replyBroadcast,
135
- ...opts.uploadFileName ? { uploadFileName: opts.uploadFileName } : {},
136
- ...opts.uploadTitle ? { uploadTitle: opts.uploadTitle } : {},
137
- blocks: opts.blocks
138
- });
139
- }
140
- async function editSlackMessage(channelId, messageId, content, opts = {}) {
141
- const client = await getClient(opts, "write");
142
- const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
143
- await client.chat.update({
144
- channel: channelId,
145
- ts: messageId,
146
- text: buildSlackEditTextPayload(content, blocks),
147
- ...blocks ? { blocks } : {}
148
- });
149
- }
150
- async function deleteSlackMessage(channelId, messageId, opts = {}) {
151
- await (await getClient(opts, "write")).chat.delete({
152
- channel: channelId,
153
- ts: messageId
154
- });
155
- }
156
- async function readSlackMessages(channelId, opts = {}) {
157
- const exactMessageId = opts.messageId?.trim();
158
- const readLimit = exactMessageId ? 1 : opts.limit;
159
- const exactBounds = exactMessageId ? {
160
- inclusive: true,
161
- latest: exactMessageId,
162
- oldest: void 0
163
- } : {
164
- latest: normalizeSlackReadTimestamp(opts.before, "before"),
165
- oldest: normalizeSlackReadTimestamp(opts.after, "after")
166
- };
167
- const client = await getClient(opts);
168
- if (opts.threadId) {
169
- const result = await client.conversations.replies({
170
- channel: channelId,
171
- ts: opts.threadId,
172
- limit: readLimit,
173
- ...exactBounds
174
- });
175
- return {
176
- messages: (result.messages ?? []).filter((message) => {
177
- if (exactMessageId) return message.ts === exactMessageId;
178
- return message.ts !== opts.threadId;
179
- }),
180
- hasMore: exactMessageId ? false : Boolean(result.has_more)
181
- };
182
- }
183
- const result = await client.conversations.history({
184
- channel: channelId,
185
- limit: readLimit,
186
- ...exactBounds
187
- });
188
- return {
189
- messages: (result.messages ?? []).filter((message) => !exactMessageId || message.ts === exactMessageId),
190
- hasMore: exactMessageId ? false : Boolean(result.has_more)
191
- };
192
- }
193
- async function getSlackMemberInfo(userId, opts = {}) {
194
- return await (await getClient(opts)).users.info({ user: userId });
195
- }
196
- async function listSlackEmojis(opts = {}) {
197
- return await (await getClient(opts)).emoji.list();
198
- }
199
- async function pinSlackMessage(channelId, messageId, opts = {}) {
200
- await (await getClient(opts, "write")).pins.add({
201
- channel: channelId,
202
- timestamp: messageId
203
- });
204
- }
205
- async function unpinSlackMessage(channelId, messageId, opts = {}) {
206
- await (await getClient(opts, "write")).pins.remove({
207
- channel: channelId,
208
- timestamp: messageId
209
- });
210
- }
211
- async function listSlackPins(channelId, opts = {}) {
212
- return (await (await getClient(opts)).pins.list({ channel: channelId })).items ?? [];
213
- }
214
- function normalizeSlackScopeValue(value) {
215
- const trimmed = value?.trim();
216
- return trimmed ? trimmed : void 0;
217
- }
218
- function collectSlackDirectShareChannelIds(file) {
219
- const ids = /* @__PURE__ */ new Set();
220
- for (const group of [
221
- file.channels,
222
- file.groups,
223
- file.ims
224
- ]) {
225
- if (!Array.isArray(group)) continue;
226
- for (const entry of group) {
227
- if (typeof entry !== "string") continue;
228
- const normalized = normalizeSlackScopeValue(entry);
229
- if (normalized) ids.add(normalized);
230
- }
231
- }
232
- return ids;
233
- }
234
- function collectSlackShareMaps(file) {
235
- if (!file.shares || typeof file.shares !== "object" || Array.isArray(file.shares)) return [];
236
- const shares = file.shares;
237
- return [shares.public, shares.private].filter((value) => Boolean(value) && typeof value === "object" && !Array.isArray(value));
238
- }
239
- function collectSlackSharedChannelIds(file) {
240
- const ids = /* @__PURE__ */ new Set();
241
- for (const shareMap of collectSlackShareMaps(file)) for (const channelId of Object.keys(shareMap)) {
242
- const normalized = normalizeSlackScopeValue(channelId);
243
- if (normalized) ids.add(normalized);
244
- }
245
- return ids;
246
- }
247
- function collectSlackThreadShares(file, channelId) {
248
- const matches = [];
249
- for (const shareMap of collectSlackShareMaps(file)) {
250
- const rawEntries = shareMap[channelId];
251
- if (!Array.isArray(rawEntries)) continue;
252
- for (const rawEntry of rawEntries) {
253
- if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) continue;
254
- const entry = rawEntry;
255
- const ts = typeof entry.ts === "string" ? normalizeSlackScopeValue(entry.ts) : void 0;
256
- const threadTs = typeof entry.thread_ts === "string" ? normalizeSlackScopeValue(entry.thread_ts) : void 0;
257
- matches.push({
258
- channelId,
259
- ts,
260
- threadTs
261
- });
262
- }
263
- }
264
- return matches;
265
- }
266
- function hasSlackScopeMismatch(params) {
267
- const channelId = normalizeSlackScopeValue(params.channelId);
268
- if (!channelId) return false;
269
- const threadId = normalizeSlackScopeValue(params.threadId);
270
- const directIds = collectSlackDirectShareChannelIds(params.file);
271
- const sharedIds = collectSlackSharedChannelIds(params.file);
272
- const hasChannelEvidence = directIds.size > 0 || sharedIds.size > 0;
273
- const inChannel = directIds.has(channelId) || sharedIds.has(channelId);
274
- if (hasChannelEvidence && !inChannel) return true;
275
- if (!threadId) return false;
276
- const threadShares = collectSlackThreadShares(params.file, channelId);
277
- if (threadShares.length === 0) return false;
278
- const threadEvidence = threadShares.filter((entry) => entry.threadTs || entry.ts);
279
- if (threadEvidence.length === 0) return false;
280
- return !threadEvidence.some((entry) => entry.threadTs === threadId || entry.ts === threadId);
281
- }
282
- /**
283
- * Downloads a Slack file by ID and saves it to the local media store.
284
- * Fetches a fresh download URL via files.info to avoid using stale private URLs.
285
- * Returns null when the file cannot be found or downloaded.
286
- */
287
- async function downloadSlackFile(fileId, opts) {
288
- const token = resolveToken(opts.token, opts.accountId, opts.cfg);
289
- const file = (await (await getClient(opts)).files.info({ file: fileId })).file;
290
- if (!file?.url_private_download && !file?.url_private) return null;
291
- if (hasSlackScopeMismatch({
292
- file,
293
- channelId: opts.channelId,
294
- threadId: opts.threadId
295
- })) return null;
296
- return (await resolveSlackMedia({
297
- files: [{
298
- id: file.id,
299
- name: file.name,
300
- mimetype: file.mimetype,
301
- url_private: file.url_private,
302
- url_private_download: file.url_private_download
303
- }],
304
- token,
305
- maxBytes: opts.maxBytes
306
- }))?.[0] ?? null;
307
- }
308
- //#endregion
309
- export { listSlackEmojis as a, pinSlackMessage as c, removeOwnSlackReactions as d, removeSlackReaction as f, buildSlackEditTextPayload as h, getSlackMemberInfo as i, reactSlackMessage as l, unpinSlackMessage as m, downloadSlackFile as n, listSlackPins as o, sendSlackMessage as p, editSlackMessage as r, listSlackReactions as s, deleteSlackMessage as t, readSlackMessages as u };
@@ -1,28 +0,0 @@
1
- import { a as resolveSlackAccount, o as resolveSlackAccountAllowFrom } from "./accounts-yk5K3wQU.js";
2
- import { i as normalizeSlackApproverId } from "./exec-approvals-BLn4Zx7V.js";
3
- import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
4
- //#region extensions/slack/src/approval-auth.ts
5
- function getSlackApprovalApprovers(params) {
6
- const account = resolveSlackAccount(params).config;
7
- return resolveApprovalApprovers({
8
- allowFrom: resolveSlackAccountAllowFrom(params),
9
- defaultTo: account.defaultTo,
10
- normalizeApprover: normalizeSlackApproverId,
11
- normalizeDefaultTo: normalizeSlackApproverId
12
- });
13
- }
14
- function isSlackApprovalAuthorizedSender(params) {
15
- const senderId = params.senderId ? normalizeSlackApproverId(params.senderId) : void 0;
16
- if (!senderId) return false;
17
- return getSlackApprovalApprovers(params).includes(senderId);
18
- }
19
- createResolvedApproverActionAuthAdapter({
20
- channelLabel: "Slack",
21
- resolveApprovers: ({ cfg, accountId }) => getSlackApprovalApprovers({
22
- cfg,
23
- accountId
24
- }),
25
- normalizeSenderId: (value) => normalizeSlackApproverId(value)
26
- });
27
- //#endregion
28
- export { isSlackApprovalAuthorizedSender as t };
@@ -1,29 +0,0 @@
1
- //#region extensions/slack/src/blocks-input.ts
2
- const SLACK_MAX_BLOCKS = 50;
3
- function parseBlocksJson(raw) {
4
- try {
5
- return JSON.parse(raw);
6
- } catch {
7
- throw new Error("blocks must be valid JSON");
8
- }
9
- }
10
- function assertBlocksArray(raw) {
11
- if (!Array.isArray(raw)) throw new Error("blocks must be an array");
12
- if (raw.length === 0) throw new Error("blocks must contain at least one block");
13
- if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
14
- for (const block of raw) {
15
- if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
16
- const type = block.type;
17
- if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
18
- }
19
- }
20
- function validateSlackBlocksArray(raw) {
21
- assertBlocksArray(raw);
22
- return raw;
23
- }
24
- function parseSlackBlocksInput(raw) {
25
- if (raw == null) return;
26
- return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
27
- }
28
- //#endregion
29
- export { parseSlackBlocksInput as n, validateSlackBlocksArray as r, SLACK_MAX_BLOCKS as t };
@@ -1,20 +0,0 @@
1
- import "./target-parsing-CQmv-iSm.js";
2
- import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
3
- import { PAIRING_APPROVED_MESSAGE, projectCredentialSnapshotFields, resolveConfiguredFromRequiredCredentialStatuses } from "openclaw/plugin-sdk/channel-status";
4
- //#region extensions/slack/src/channel-api.ts
5
- const SLACK_CHANNEL_META = {
6
- id: "slack",
7
- label: "Slack",
8
- selectionLabel: "Slack",
9
- docsPath: "/channels/slack",
10
- docsLabel: "slack",
11
- blurb: "supports bot + app tokens, channels, threads, and interactive replies.",
12
- systemImage: "number.square",
13
- markdownCapable: true
14
- };
15
- function getChatChannelMeta(id) {
16
- if (id !== SLACK_CHANNEL_META.id) throw new Error(`Unsupported Slack channel meta lookup: ${id}`);
17
- return SLACK_CHANNEL_META;
18
- }
19
- //#endregion
20
- export { resolveConfiguredFromRequiredCredentialStatuses as a, projectCredentialSnapshotFields as i, PAIRING_APPROVED_MESSAGE as n, getChatChannelMeta as r, DEFAULT_ACCOUNT_ID$1 as t };
@@ -1,58 +0,0 @@
1
- import { a as resolveSlackAccount } from "./accounts-yk5K3wQU.js";
2
- import { normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
- import { doesApprovalRequestMatchChannelAccount } from "openclaw/plugin-sdk/approval-native-runtime";
4
- import { resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
5
- import { createChannelExecApprovalProfile, isChannelExecApprovalTargetRecipient } from "openclaw/plugin-sdk/approval-client-runtime";
6
- //#region extensions/slack/src/exec-approvals.ts
7
- function normalizeSlackApproverId(value) {
8
- const trimmed = normalizeStringifiedOptionalString(value);
9
- if (!trimmed) return;
10
- const prefixed = trimmed.match(/^(?:slack|user):([A-Z0-9]+)$/i);
11
- if (prefixed?.[1]) return prefixed[1];
12
- const mention = trimmed.match(/^<@([A-Z0-9]+)>$/i);
13
- if (mention?.[1]) return mention[1];
14
- return /^[UW][A-Z0-9]+$/i.test(trimmed) ? trimmed : void 0;
15
- }
16
- function resolveSlackOwnerApprovers(cfg) {
17
- const ownerAllowFrom = cfg.commands?.ownerAllowFrom;
18
- if (!Array.isArray(ownerAllowFrom) || ownerAllowFrom.length === 0) return [];
19
- return resolveApprovalApprovers({
20
- explicit: ownerAllowFrom,
21
- normalizeApprover: normalizeSlackApproverId
22
- });
23
- }
24
- function getSlackExecApprovalApprovers(params) {
25
- const account = resolveSlackAccount(params).config;
26
- return resolveApprovalApprovers({
27
- explicit: account.execApprovals?.approvers ?? resolveSlackOwnerApprovers(params.cfg),
28
- normalizeApprover: normalizeSlackApproverId
29
- });
30
- }
31
- function isSlackExecApprovalTargetRecipient(params) {
32
- return isChannelExecApprovalTargetRecipient({
33
- ...params,
34
- channel: "slack",
35
- normalizeSenderId: normalizeSlackApproverId,
36
- matchTarget: ({ target, normalizedSenderId }) => normalizeSlackApproverId(target.to) === normalizedSenderId
37
- });
38
- }
39
- const slackExecApprovalProfile = createChannelExecApprovalProfile({
40
- resolveConfig: (params) => resolveSlackAccount(params).config.execApprovals,
41
- resolveApprovers: getSlackExecApprovalApprovers,
42
- normalizeSenderId: normalizeSlackApproverId,
43
- isTargetRecipient: isSlackExecApprovalTargetRecipient,
44
- matchesRequestAccount: (params) => doesApprovalRequestMatchChannelAccount({
45
- cfg: params.cfg,
46
- request: params.request,
47
- channel: "slack",
48
- accountId: params.accountId
49
- })
50
- });
51
- const isSlackExecApprovalClientEnabled = slackExecApprovalProfile.isClientEnabled;
52
- slackExecApprovalProfile.isApprover;
53
- const isSlackExecApprovalAuthorizedSender = slackExecApprovalProfile.isAuthorizedSender;
54
- const resolveSlackExecApprovalTarget = slackExecApprovalProfile.resolveTarget;
55
- const shouldHandleSlackExecApprovalRequest = slackExecApprovalProfile.shouldHandleRequest;
56
- const shouldSuppressLocalSlackExecApprovalPrompt = slackExecApprovalProfile.shouldSuppressLocalPrompt;
57
- //#endregion
58
- export { resolveSlackExecApprovalTarget as a, normalizeSlackApproverId as i, isSlackExecApprovalAuthorizedSender as n, shouldHandleSlackExecApprovalRequest as o, isSlackExecApprovalClientEnabled as r, shouldSuppressLocalSlackExecApprovalPrompt as s, getSlackExecApprovalApprovers as t };
@@ -1,41 +0,0 @@
1
- import { i as resolveDefaultSlackAccountId, r as mergeSlackAccountConfig } from "./accounts-yk5K3wQU.js";
2
- import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
3
- import { normalizeHyphenSlug } from "openclaw/plugin-sdk/string-normalization-runtime";
4
- import { resolveToolsBySender } from "openclaw/plugin-sdk/channel-policy";
5
- //#region extensions/slack/src/group-policy.ts
6
- function resolveSlackChannelPolicyEntry(params) {
7
- const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
8
- const channelMap = mergeSlackAccountConfig(params.cfg, accountId).channels ?? {};
9
- if (Object.keys(channelMap).length === 0) return;
10
- const channelId = params.groupId?.trim();
11
- const channelName = params.groupChannel?.replace(/^#/, "");
12
- const normalizedName = normalizeHyphenSlug(channelName);
13
- const candidates = [
14
- channelId ?? "",
15
- channelName ? `#${channelName}` : "",
16
- channelName ?? "",
17
- normalizedName
18
- ].filter(Boolean);
19
- for (const candidate of candidates) if (candidate && channelMap[candidate]) return channelMap[candidate];
20
- return channelMap["*"];
21
- }
22
- function resolveSenderToolsEntry(entry, params) {
23
- if (!entry) return;
24
- return resolveToolsBySender({
25
- toolsBySender: entry.toolsBySender,
26
- senderId: params.senderId,
27
- senderName: params.senderName,
28
- senderUsername: params.senderUsername,
29
- senderE164: params.senderE164
30
- }) ?? entry.tools;
31
- }
32
- function resolveSlackGroupRequireMention(params) {
33
- const resolved = resolveSlackChannelPolicyEntry(params);
34
- if (typeof resolved?.requireMention === "boolean") return resolved.requireMention;
35
- return true;
36
- }
37
- function resolveSlackGroupToolPolicy(params) {
38
- return resolveSenderToolsEntry(resolveSlackChannelPolicyEntry(params), params);
39
- }
40
- //#endregion
41
- export { resolveSlackGroupToolPolicy as n, resolveSlackGroupRequireMention as t };
@@ -1,6 +0,0 @@
1
- //#region extensions/slack/src/monitor/mrkdwn.ts
2
- function escapeSlackMrkdwn(value) {
3
- return value.replaceAll("\\", "\\\\").replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replace(/([*_`~])/g, "\\$1");
4
- }
5
- //#endregion
6
- export { escapeSlackMrkdwn as t };
@@ -1,14 +0,0 @@
1
- import { t as buildSlackInteractiveBlocks } from "./blocks-render-BdLueE_v.js";
2
- import { n as parseSlackBlocksInput } from "./blocks-input-BJZ8vv03.js";
3
- //#region extensions/slack/src/reply-blocks.ts
4
- function resolveSlackReplyBlocks(payload) {
5
- const slackData = payload.channelData?.slack;
6
- const interactiveBlocks = buildSlackInteractiveBlocks(payload.interactive);
7
- let channelBlocks = [];
8
- if (slackData && typeof slackData === "object" && !Array.isArray(slackData)) channelBlocks = parseSlackBlocksInput(slackData.blocks) ?? [];
9
- const blocks = [...channelBlocks, ...interactiveBlocks];
10
- if (blocks.length > 50) throw new Error(`Slack blocks cannot exceed 50 items after interactive render`);
11
- return blocks.length > 0 ? blocks : void 0;
12
- }
13
- //#endregion
14
- export { resolveSlackReplyBlocks as t };
@@ -1,2 +0,0 @@
1
- import { t as sendMessageSlack } from "./send-ioky2Xpy.js";
2
- export { sendMessageSlack };
@@ -1,2 +0,0 @@
1
- import "./send-ioky2Xpy.js";
2
- export {};
@@ -1,24 +0,0 @@
1
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
- //#region extensions/slack/src/truncate.ts
3
- function truncateSlackText(value, max) {
4
- const trimmed = value.trim();
5
- if (trimmed.length <= max) return trimmed;
6
- if (max <= 1) return trimmed.slice(0, max);
7
- return `${trimmed.slice(0, max - 1)}…`;
8
- }
9
- //#endregion
10
- //#region extensions/slack/src/limits.ts
11
- const SLACK_TEXT_LIMIT = 8e3;
12
- //#endregion
13
- //#region extensions/slack/src/thread-ts.ts
14
- const SLACK_THREAD_TS_PATTERN = /^\d+\.\d+$/;
15
- function normalizeSlackThreadTsCandidate(value) {
16
- if (typeof value !== "string") return;
17
- const normalized = normalizeOptionalString(value);
18
- return normalized && SLACK_THREAD_TS_PATTERN.test(normalized) ? normalized : void 0;
19
- }
20
- function resolveSlackThreadTsValue(params) {
21
- return normalizeSlackThreadTsCandidate(params.replyToId) ?? normalizeSlackThreadTsCandidate(params.threadId);
22
- }
23
- //#endregion
24
- export { truncateSlackText as i, resolveSlackThreadTsValue as n, SLACK_TEXT_LIMIT as r, normalizeSlackThreadTsCandidate as t };
File without changes