@openclaw/slack 2026.7.1 → 2026.7.2-beta.1

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 (69) hide show
  1. package/dist/accounts.runtime-KvftRRek.js +2 -0
  2. package/dist/{action-runtime-DoQGk_8D.js → action-runtime-p6M2ULpv.js} +205 -29
  3. package/dist/action-runtime.runtime-DQstDkHG.js +2 -0
  4. package/dist/{actions-DMpDmKEA.js → actions-DkTcWmpT.js} +87 -138
  5. package/dist/{actions.runtime-C103_BPW.js → actions.runtime-BSxpwgUc.js} +1 -1
  6. package/dist/api.js +14 -13
  7. package/dist/{approval-handler.runtime-CIUbOt5T.js → approval-handler.runtime-UGbnz9OC.js} +3 -3
  8. package/dist/{channel-BjlsaGHn.js → channel-B0_j6C6z.js} +116 -140
  9. package/dist/channel-config-api.js +1 -1
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/channel-type-BpeTezY4.js +109 -0
  12. package/dist/{channel.setup-Dq6syTNU.js → channel.setup-BQFut21T.js} +2 -2
  13. package/dist/{client-DGxwSL7f.js → client-D2F6m8CP.js} +38 -2
  14. package/dist/config-api-Df9a1B8C.js +3 -0
  15. package/dist/{config-schema-BzqzFW__.js → config-schema-DYI01PV2.js} +20 -37
  16. package/dist/cursor-pages-DSmTg0su.js +13 -0
  17. package/dist/{directory-config-BZuS8141.js → directory-config-DRkFujwG.js} +2 -2
  18. package/dist/directory-contract-api.js +1 -1
  19. package/dist/{directory-live-BNsxCgqP.js → directory-live-DX7yFsM-.js} +2 -2
  20. package/dist/{doctor-contract-XL6HeNCb.js → doctor-contract-DddfkMlF.js} +25 -38
  21. package/dist/doctor-contract-api.js +1 -1
  22. package/dist/group-policy-C-b2ZnSl.js +2332 -0
  23. package/dist/{interactive-replies-CXpT-vA_.js → interactive-replies-BilWUdcI.js} +5 -1
  24. package/dist/interactive-replies-api.js +1 -1
  25. package/dist/{message-tool-api-BgWKyu2r.js → message-tool-api-CA9jZrCY.js} +1 -1
  26. package/dist/message-tool-api.js +1 -1
  27. package/dist/{monitor-Ux-wzUWI.js → monitor-BN_uuvrQ.js} +3 -3
  28. package/dist/outbound-adapter-ECl0go7d.js +228 -0
  29. package/dist/{pipeline.runtime-rpVpay59.js → pipeline.runtime-f0eJJoJL.js} +492 -178
  30. package/dist/{policy-Dj-puVPb.js → policy-f8b0edSi.js} +1 -1
  31. package/dist/preflight-audio.runtime-D5Bgags0.js +3 -0
  32. package/dist/{probe-CuwRDE5j.js → probe-CfALk0l4.js} +2 -2
  33. package/dist/{provider-C1-DFSpw.js → provider-Ds-y-imP.js} +658 -192
  34. package/dist/{relay-source-D2jv1iGg.js → relay-source-B-6LFUdz.js} +6 -17
  35. package/dist/replies-BMvf3ihj.js +420 -0
  36. package/dist/{resolve-channels-CstkChBE.js → resolve-channels-DOMgNCWb.js} +17 -6
  37. package/dist/{resolve-users-C3NP2c-Q.js → resolve-users-aL6-Ssee.js} +11 -6
  38. package/dist/{runtime-BOk7xkOl.js → runtime-CauEvswP.js} +1 -1
  39. package/dist/{runtime-api-CEmqYxR-.js → runtime-api-CVb6CQjX.js} +3 -3
  40. package/dist/runtime-api.js +11 -11
  41. package/dist/runtime-setter-api.js +1 -1
  42. package/dist/{scopes-DCWVD5-8.js → scopes-Dw8wbU0j.js} +2 -2
  43. package/dist/{secret-contract-C3ChHo5A.js → secret-contract-CMohXFWS.js} +18 -113
  44. package/dist/secret-contract-api.js +1 -1
  45. package/dist/{send-DKDXoeoV.js → send-NEfJ0GvM.js} +662 -325
  46. package/dist/{send.runtime-GPRa63l1.js → send.runtime-BkKpitPu.js} +1 -1
  47. package/dist/setup-plugin-api.js +1 -1
  48. package/dist/{setup-surface-Dv2fIJNB.js → setup-surface-BN2WeG5c.js} +3 -3
  49. package/dist/{shared-CosfcFri.js → shared-BLnB9R1T.js} +7 -5
  50. package/dist/{slash-dispatch.runtime-CcMbbT3_.js → slash-dispatch.runtime-C0Otuf_T.js} +1 -1
  51. package/dist/{streaming-compat-DjlgH-Be.js → streaming-compat-3_X-21wW.js} +1 -0
  52. package/dist/{target-parsing-3jYH8LfB.js → target-parsing-N6lHogYZ.js} +16 -3
  53. package/dist/{targets-Dll4NJgs.js → targets-KmjP2E8s.js} +1 -1
  54. package/node_modules/p-map/index.d.ts +155 -0
  55. package/node_modules/p-map/index.js +284 -0
  56. package/node_modules/p-map/license +9 -0
  57. package/node_modules/p-map/package.json +57 -0
  58. package/node_modules/p-map/readme.md +190 -0
  59. package/npm-shrinkwrap.json +16 -3
  60. package/openclaw.plugin.json +16 -0
  61. package/package.json +6 -4
  62. package/dist/accounts.runtime-DWvaCb-X.js +0 -2
  63. package/dist/action-runtime.runtime-BABj3aM-.js +0 -2
  64. package/dist/config-api-DnT9ohtE.js +0 -2
  65. package/dist/format-YCNoNkM2.js +0 -107
  66. package/dist/outbound-adapter-DVoBfBW5.js +0 -272
  67. package/dist/replies-DpF38e1y.js +0 -287
  68. package/dist/reply-blocks-BGQ6zSqM.js +0 -877
  69. package/dist/resolve-allowlist-common-CP8SH0Zf.js +0 -43
@@ -0,0 +1,2 @@
1
+ import { a as resolveSlackAccount, o as resolveSlackAccountAllowFrom } from "./accounts-BOJJiHSr.js";
2
+ export { resolveSlackAccount, resolveSlackAccountAllowFrom };
@@ -1,8 +1,10 @@
1
- import { i as resolveSlackChannelId } from "./target-parsing-3jYH8LfB.js";
2
- import { t as slackContextTargetsMatch } from "./targets-Dll4NJgs.js";
3
- import { r as parseSlackBlocksInput } from "./reply-blocks-BGQ6zSqM.js";
4
- import { a as readPositiveIntegerParam, c as withNormalizedTimestamp, n as imageResultFromFile, o as readReactionParams, r as jsonResult, s as readStringParam, t as createActionGate } from "./runtime-api-CEmqYxR-.js";
5
- import { n as resolveSlackChannelConfig, t as isSlackChannelAllowedByPolicy } from "./policy-Dj-puVPb.js";
1
+ import { a as resolveSlackChannelId, i as parseSlackTarget } from "./target-parsing-N6lHogYZ.js";
2
+ import { t as slackContextTargetsMatch } from "./targets-KmjP2E8s.js";
3
+ import { C as hasSlackNativeDataBlock, X as parseSlackBlocksInput } from "./group-policy-C-b2ZnSl.js";
4
+ import { a as readPositiveIntegerParam, c as withNormalizedTimestamp, n as imageResultFromFile, o as readReactionParams, r as jsonResult, s as readStringParam, t as createActionGate } from "./runtime-api-CVb6CQjX.js";
5
+ import { n as resolveSlackChannelConfig, t as isSlackChannelAllowedByPolicy } from "./policy-f8b0edSi.js";
6
+ import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
7
+ import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
8
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
7
9
  import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
8
10
  import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
@@ -22,8 +24,9 @@ const pinActions = /* @__PURE__ */ new Set([
22
24
  "unpinMessage",
23
25
  "listPins"
24
26
  ]);
25
- const loadSlackActionsRuntime = createLazyRuntimeModule(() => import("./actions.runtime-C103_BPW.js"));
26
- const loadSlackAccountsRuntime = createLazyRuntimeModule(() => import("./accounts.runtime-DWvaCb-X.js"));
27
+ const loadSlackActionsRuntime = createLazyRuntimeModule(() => import("./actions.runtime-BSxpwgUc.js"));
28
+ const loadSlackAccountsRuntime = createLazyRuntimeModule(() => import("./accounts.runtime-KvftRRek.js"));
29
+ const loadSlackChannelTypeRuntime = createLazyRuntimeModule(() => import("./channel-type-BpeTezY4.js").then((n) => n.t));
27
30
  function createLazySlackAction(key) {
28
31
  return (async (...args) => {
29
32
  const action = (await loadSlackActionsRuntime())[key];
@@ -45,6 +48,8 @@ const slackActionRuntime = {
45
48
  removeOwnSlackReactions: createLazySlackAction("removeOwnSlackReactions"),
46
49
  removeSlackReaction: createLazySlackAction("removeSlackReaction"),
47
50
  resolveSlackConversationName: createLazySlackAction("resolveSlackConversationName"),
51
+ resolveSlackConversationInfo: async (params) => (await loadSlackChannelTypeRuntime()).resolveSlackConversationInfo(params),
52
+ resolveSlackChannelType: async (params) => (await loadSlackChannelTypeRuntime()).resolveSlackChannelType(params),
48
53
  sendSlackMessage: createLazySlackAction("sendSlackMessage"),
49
54
  unpinSlackMessage: createLazySlackAction("unpinSlackMessage")
50
55
  };
@@ -75,7 +80,51 @@ function readSlackBlocksParam(params) {
75
80
  function isImageContentType(value) {
76
81
  return value?.trim().toLowerCase().startsWith("image/") === true;
77
82
  }
78
- function resolveSlackReadTargetDecision(params) {
83
+ function hasPotentialSlackNamedPolicy(params) {
84
+ if (params.allowNameMatching !== true) return false;
85
+ return Object.entries(params.channels ?? {}).some(([key, entry]) => {
86
+ if (entry == null || key === "*") return false;
87
+ const named = !/^(?:channel:)?[CDG][A-Z0-9]+$/i.test(key);
88
+ const entryAllows = entry.enabled !== false;
89
+ return named && (params.decision === "allow" ? entryAllows : !entryAllows);
90
+ });
91
+ }
92
+ function resolveSlackDmReadAllowed(account) {
93
+ const dmPolicy = account.config.dmPolicy ?? account.config.dm?.policy ?? "pairing";
94
+ return account.config.dm?.enabled !== false && dmPolicy !== "disabled";
95
+ }
96
+ function normalizeConfiguredSlackDmUserId(value) {
97
+ const target = parseSlackTarget(String(value), { defaultKind: "user" });
98
+ if (target?.kind !== "user") return;
99
+ const userId = target.id.trim().toLowerCase();
100
+ return /^[uw][a-z0-9]+$/i.test(userId) ? userId : void 0;
101
+ }
102
+ async function isSlackDmTargetConfigured(params) {
103
+ const defaultTo = params.account.config.defaultTo?.trim();
104
+ if (defaultTo && slackContextTargetsMatch(params.channelId, { currentChannelId: defaultTo })) return true;
105
+ const userId = normalizeConfiguredSlackDmUserId(params.userId);
106
+ if (!userId) return false;
107
+ const { resolveSlackAccountAllowFrom } = await loadSlackAccountsRuntime();
108
+ return [
109
+ ...resolveSlackAccountAllowFrom({
110
+ cfg: params.cfg,
111
+ accountId: params.account.accountId
112
+ }) ?? [],
113
+ ...Object.keys(params.account.config.dms ?? {}),
114
+ ...defaultTo ? [defaultTo] : []
115
+ ].some((entry) => normalizeConfiguredSlackDmUserId(entry) === userId);
116
+ }
117
+ function isCurrentSlackReadTarget(params) {
118
+ const requesterAccountId = params.context?.requesterAccountId?.trim();
119
+ return Boolean(normalizeOptionalLowercaseString(params.context?.currentChannelProvider) === "slack" && requesterAccountId && normalizeAccountId(requesterAccountId) === normalizeAccountId(params.account.accountId) && params.context && slackContextTargetsMatch(params.channelId, params.context));
120
+ }
121
+ function assertSlackMemberInfoAllowed(params) {
122
+ if (params.context?.conversationReadOrigin === "direct-operator") return;
123
+ const requesterAccountId = params.context?.requesterAccountId?.trim();
124
+ const requesterSenderId = normalizeOptionalLowercaseString(params.context?.requesterSenderId);
125
+ if (normalizeOptionalLowercaseString(params.context?.currentChannelProvider) !== "slack" || !requesterAccountId || normalizeAccountId(requesterAccountId) !== normalizeAccountId(params.account.accountId) || !requesterSenderId || requesterSenderId !== normalizeOptionalLowercaseString(params.userId)) throw new Error("Delegated Slack member info is limited to the current requester.");
126
+ }
127
+ function resolveSlackChannelReadPolicy(params) {
79
128
  const channels = params.account.config.channels;
80
129
  const channelKeys = Object.keys(channels ?? {});
81
130
  const channelConfig = resolveSlackChannelConfig({
@@ -87,29 +136,103 @@ function resolveSlackReadTargetDecision(params) {
87
136
  defaultRequireMention: params.account.config.requireMention
88
137
  });
89
138
  const channelAllowed = channelConfig?.allowed !== false;
139
+ const channelExplicitlyDisabled = !channelAllowed && channelConfig?.matchSource === "direct";
140
+ const channelWildcardDisabled = !channelAllowed && channelConfig?.matchSource === "wildcard";
90
141
  const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
91
142
  providerConfigPresent: params.cfg.channels?.slack !== void 0,
92
143
  groupPolicy: params.account.config.groupPolicy,
93
144
  defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy
94
145
  });
95
- if (isSlackChannelAllowedByPolicy({
146
+ const delegatedChannelAllowed = isSlackChannelAllowedByPolicy({
96
147
  groupPolicy,
97
148
  channelAllowlistConfigured: channelKeys.length > 0,
98
149
  channelAllowed
99
- })) return !channelAllowed && (groupPolicy !== "open" || channelConfig?.matchSource) ? "deny" : "allow";
100
- return groupPolicy === "allowlist" && channelKeys.length > 0 && params.account.config.dangerouslyAllowNameMatching === true && !params.channelName && (channelConfig?.matchSource === void 0 || channelConfig.matchSource === "wildcard") ? "resolve-name" : "deny";
150
+ }) && !(!channelAllowed && (groupPolicy !== "open" || channelConfig?.matchSource));
151
+ const directChannelAllowed = groupPolicy !== "disabled" && !channelExplicitlyDisabled && !channelWildcardDisabled;
152
+ const baseChannelAllowed = params.conversationReadOrigin === "direct-operator" || params.currentConversation ? directChannelAllowed : delegatedChannelAllowed;
153
+ const allowNameMatching = params.account.config.dangerouslyAllowNameMatching;
154
+ const shouldResolveName = !params.metadataResolved && !params.channelName && (baseChannelAllowed && channelConfig?.matchSource !== "direct" && hasPotentialSlackNamedPolicy({
155
+ channels,
156
+ allowNameMatching,
157
+ decision: "deny"
158
+ }) || !baseChannelAllowed && groupPolicy !== "disabled" && !channelExplicitlyDisabled && hasPotentialSlackNamedPolicy({
159
+ channels,
160
+ allowNameMatching,
161
+ decision: "allow"
162
+ }));
163
+ return {
164
+ channelAllowed: baseChannelAllowed,
165
+ channelExplicitlyDisabled,
166
+ groupDmAllowed: params.account.config.dm?.enabled !== false && params.account.config.dm?.groupEnabled === true && (params.currentConversation || isSlackGroupDmTargetConfigured(params.account, params.channelId)),
167
+ shouldResolveName
168
+ };
101
169
  }
102
170
  async function assertSlackReadTargetAllowed(params) {
103
- const direct = resolveSlackReadTargetDecision(params);
104
- if (direct === "allow") return;
105
- if (direct === "resolve-name") {
106
- const channelName = await params.resolveChannelName();
107
- if (channelName && resolveSlackReadTargetDecision({
171
+ const deny = () => {
172
+ throw new Error("Slack read target channel is not allowed.");
173
+ };
174
+ const currentConversation = isCurrentSlackReadTarget({
175
+ account: params.account,
176
+ channelId: params.channelId,
177
+ context: params.context
178
+ });
179
+ const directOperator = params.conversationReadOrigin === "direct-operator";
180
+ if (/^D/i.test(params.channelId)) {
181
+ if (!resolveSlackDmReadAllowed(params.account)) deny();
182
+ if (directOperator || currentConversation) return;
183
+ const info = await slackActionRuntime.resolveSlackConversationInfo({
184
+ cfg: params.cfg,
185
+ accountId: params.account.accountId,
186
+ channelId: params.channelId,
187
+ operation: "read"
188
+ });
189
+ if (info.type !== "dm" || !await isSlackDmTargetConfigured({
190
+ ...params,
191
+ userId: info.user
192
+ })) deny();
193
+ return;
194
+ }
195
+ const preliminary = resolveSlackChannelReadPolicy({
196
+ ...params,
197
+ currentConversation
198
+ });
199
+ if (preliminary.channelExplicitlyDisabled) deny();
200
+ if (!(preliminary.shouldResolveName || preliminary.channelAllowed !== preliminary.groupDmAllowed)) {
201
+ if (!preliminary.channelAllowed) deny();
202
+ return;
203
+ }
204
+ const info = await slackActionRuntime.resolveSlackConversationInfo({
205
+ cfg: params.cfg,
206
+ accountId: params.account.accountId,
207
+ channelId: params.channelId,
208
+ operation: "read",
209
+ ...preliminary.shouldResolveName ? { requireFreshName: true } : {}
210
+ });
211
+ if (preliminary.shouldResolveName && (info.type === "channel" || info.type === "unknown") && !info.name) deny();
212
+ const resolved = resolveSlackChannelReadPolicy({
213
+ ...params,
214
+ channelName: info.name,
215
+ metadataResolved: true,
216
+ currentConversation
217
+ });
218
+ if (resolved.channelExplicitlyDisabled) deny();
219
+ if (info.type === "dm") {
220
+ if (!resolveSlackDmReadAllowed(params.account) || !directOperator && !currentConversation && !await isSlackDmTargetConfigured({
108
221
  ...params,
109
- channelName
110
- }) === "allow") return;
222
+ userId: info.user
223
+ })) deny();
224
+ return;
111
225
  }
112
- throw new Error("Slack read target channel is not allowed.");
226
+ if (!(info.type === "channel" ? resolved.channelAllowed : info.type === "group" ? resolved.groupDmAllowed : resolved.channelAllowed && resolved.groupDmAllowed)) deny();
227
+ }
228
+ function isSlackGroupDmTargetConfigured(account, channelId) {
229
+ const entries = account.config.dm?.groupChannels ?? [];
230
+ if (entries.length === 0) return true;
231
+ const target = channelId.trim().toLowerCase();
232
+ return entries.some((entry) => {
233
+ const candidate = String(entry).trim().toLowerCase();
234
+ return candidate === "*" || candidate === target || candidate === `slack:${target}` || candidate === `channel:${target}` || candidate === `group:${target}` || candidate === `mpim:${target}`;
235
+ });
113
236
  }
114
237
  async function handleSlackAction(params, cfg, context) {
115
238
  const resolveChannelId = () => resolveSlackChannelId(readStringParam(params, "channelId", { required: true }));
@@ -120,6 +243,7 @@ async function handleSlackAction(params, cfg, context) {
120
243
  cfg,
121
244
  accountId
122
245
  });
246
+ if (account.config.enterpriseOrgInstall === true) throw new Error("Slack action tools are unavailable for Enterprise Grid org installs.");
123
247
  const isActionEnabled = createActionGate(account.actions ?? cfg.channels?.slack?.actions);
124
248
  const userToken = account.userToken;
125
249
  const botToken = account.botToken?.trim();
@@ -144,7 +268,8 @@ async function handleSlackAction(params, cfg, context) {
144
268
  account,
145
269
  cfg,
146
270
  channelId,
147
- resolveChannelName: async () => await slackActionRuntime.resolveSlackConversationName(channelId, readOpts)
271
+ conversationReadOrigin: context?.conversationReadOrigin,
272
+ context
148
273
  });
149
274
  if (reactionsActions.has(action)) {
150
275
  if (!isActionEnabled("reactions")) throw new Error("Slack reactions are disabled.");
@@ -152,6 +277,7 @@ async function handleSlackAction(params, cfg, context) {
152
277
  const messageId = readStringParam(params, "messageId", { required: true });
153
278
  if (action === "react") {
154
279
  const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Slack reaction." });
280
+ await assertReadTargetAllowed(channelId);
155
281
  if (remove) {
156
282
  if (writeOpts) await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji, writeOpts);
157
283
  else await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji);
@@ -186,25 +312,66 @@ async function handleSlackAction(params, cfg, context) {
186
312
  const mediaUrl = readStringParam(params, "mediaUrl");
187
313
  const blocks = readSlackBlocksParam(params);
188
314
  const replyBroadcast = readBooleanParam(params, "replyBroadcast");
189
- if (!content && !mediaUrl && !blocks) throw new Error("Slack sendMessage requires content, blocks, or mediaUrl.");
315
+ const textIsSlackMrkdwn = readBooleanParam(params, "textIsSlackMrkdwn");
316
+ const textIsSlackPlainText = readBooleanParam(params, "textIsSlackPlainText");
317
+ const preparedMessages = context?.preparedMessages;
318
+ const authoredTextPlacement = readStringParam(params, "authoredTextPlacement");
319
+ if (authoredTextPlacement && authoredTextPlacement !== "none" && authoredTextPlacement !== "blocks" && authoredTextPlacement !== "outside-blocks") throw new Error("Slack authoredTextPlacement is invalid.");
320
+ const nativeDataFallbackBaseText = readStringParam(params, "nativeDataFallbackBaseText", { allowEmpty: true });
321
+ if (!content && !mediaUrl && !blocks && !preparedMessages?.length) throw new Error("Slack sendMessage requires content, blocks, or mediaUrl.");
190
322
  if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
191
323
  const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), to, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
192
- const sendOpts = {
324
+ const baseSendOpts = {
193
325
  ...writeOpts,
194
326
  mediaLocalRoots: context?.mediaLocalRoots,
195
327
  mediaReadFile: context?.mediaReadFile,
196
- threadTs: threadTs ?? void 0,
197
- ...replyBroadcast ? { replyBroadcast } : {}
328
+ threadTs: threadTs ?? void 0
329
+ };
330
+ const sendOpts = {
331
+ ...baseSendOpts,
332
+ ...replyBroadcast ? { replyBroadcast } : {},
333
+ ...textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
334
+ ...textIsSlackPlainText ? { textIsSlackPlainText: true } : {},
335
+ ...authoredTextPlacement ? { authoredTextPlacement } : {},
336
+ ...nativeDataFallbackBaseText !== void 0 ? { nativeDataFallbackBaseText } : {}
198
337
  };
199
- const result = mediaUrl && blocks ? await (async () => {
200
- await slackActionRuntime.sendSlackMessage(to, "", {
338
+ const sendContentAndBlocks = async () => {
339
+ const shouldSplitLongContent = content && content.length > 8e3 && !hasSlackNativeDataBlock(blocks);
340
+ if (content && shouldSplitLongContent) {
341
+ const { replyBroadcast: _replyBroadcast, ...blockSendOpts } = sendOpts;
342
+ await slackActionRuntime.sendSlackMessage(to, "", {
343
+ ...blockSendOpts,
344
+ blocks
345
+ });
346
+ return await slackActionRuntime.sendSlackMessage(to, content, sendOpts);
347
+ }
348
+ return await slackActionRuntime.sendSlackMessage(to, content ?? "", {
201
349
  ...sendOpts,
350
+ blocks
351
+ });
352
+ };
353
+ const result = preparedMessages?.length ? await (async () => {
354
+ let lastResult;
355
+ if (mediaUrl) lastResult = await slackActionRuntime.sendSlackMessage(to, "", {
356
+ ...baseSendOpts,
202
357
  mediaUrl
203
358
  });
204
- return await slackActionRuntime.sendSlackMessage(to, content ?? "", {
359
+ for (const [index, message] of preparedMessages.entries()) lastResult = await slackActionRuntime.sendSlackMessage(to, message.text, {
360
+ ...baseSendOpts,
361
+ ...index === 0 && replyBroadcast ? { replyBroadcast: true } : {},
362
+ ...message.blocks ? { blocks: message.blocks } : {},
363
+ ...message.authoredTextPlacement ? { authoredTextPlacement: message.authoredTextPlacement } : {},
364
+ ...Object.hasOwn(message, "nativeDataFallbackBaseText") ? { nativeDataFallbackBaseText: message.nativeDataFallbackBaseText } : {},
365
+ ...message.textIsSlackPlainText ? { textIsSlackPlainText: true } : {}
366
+ });
367
+ if (!lastResult) throw new Error("Slack prepared message plan produced no delivery.");
368
+ return lastResult;
369
+ })() : blocks ? await (async () => {
370
+ if (mediaUrl) await slackActionRuntime.sendSlackMessage(to, "", {
205
371
  ...sendOpts,
206
- blocks
372
+ mediaUrl
207
373
  });
374
+ return await sendContentAndBlocks();
208
375
  })() : await slackActionRuntime.sendSlackMessage(to, content ?? "", {
209
376
  ...sendOpts,
210
377
  mediaUrl: mediaUrl ?? void 0,
@@ -248,6 +415,7 @@ async function handleSlackAction(params, cfg, context) {
248
415
  const content = readStringParam(params, "content", { allowEmpty: true });
249
416
  const blocks = readSlackBlocksParam(params);
250
417
  if (!content && !blocks) throw new Error("Slack editMessage requires content or blocks.");
418
+ await assertReadTargetAllowed(channelId);
251
419
  if (writeOpts) await slackActionRuntime.editSlackMessage(channelId, messageId, content ?? "", {
252
420
  ...writeOpts,
253
421
  blocks
@@ -258,6 +426,7 @@ async function handleSlackAction(params, cfg, context) {
258
426
  case "deleteMessage": {
259
427
  const channelId = resolveChannelId();
260
428
  const messageId = readStringParam(params, "messageId", { required: true });
429
+ await assertReadTargetAllowed(channelId);
261
430
  if (writeOpts) await slackActionRuntime.deleteSlackMessage(channelId, messageId, writeOpts);
262
431
  else await slackActionRuntime.deleteSlackMessage(channelId, messageId);
263
432
  return jsonResult({ ok: true });
@@ -336,12 +505,14 @@ async function handleSlackAction(params, cfg, context) {
336
505
  const channelId = resolveChannelId();
337
506
  if (action === "pinMessage") {
338
507
  const messageId = readStringParam(params, "messageId", { required: true });
508
+ await assertReadTargetAllowed(channelId);
339
509
  if (writeOpts) await slackActionRuntime.pinSlackMessage(channelId, messageId, writeOpts);
340
510
  else await slackActionRuntime.pinSlackMessage(channelId, messageId);
341
511
  return jsonResult({ ok: true });
342
512
  }
343
513
  if (action === "unpinMessage") {
344
514
  const messageId = readStringParam(params, "messageId", { required: true });
515
+ await assertReadTargetAllowed(channelId);
345
516
  if (writeOpts) await slackActionRuntime.unpinSlackMessage(channelId, messageId, writeOpts);
346
517
  else await slackActionRuntime.unpinSlackMessage(channelId, messageId);
347
518
  return jsonResult({ ok: true });
@@ -358,9 +529,14 @@ async function handleSlackAction(params, cfg, context) {
358
529
  if (action === "memberInfo") {
359
530
  if (!isActionEnabled("memberInfo")) throw new Error("Slack member info is disabled.");
360
531
  const userId = readStringParam(params, "userId", { required: true });
532
+ assertSlackMemberInfoAllowed({
533
+ account,
534
+ context,
535
+ userId
536
+ });
361
537
  return jsonResult({
362
538
  ok: true,
363
- info: writeOpts ? await slackActionRuntime.getSlackMemberInfo(userId, readOpts) : await slackActionRuntime.getSlackMemberInfo(userId)
539
+ info: readOpts ? await slackActionRuntime.getSlackMemberInfo(userId, readOpts) : await slackActionRuntime.getSlackMemberInfo(userId)
364
540
  });
365
541
  }
366
542
  if (action === "emojiList") {
@@ -0,0 +1,2 @@
1
+ import { t as handleSlackAction } from "./action-runtime-p6M2ULpv.js";
2
+ export { handleSlackAction };