@openclaw/slack 2026.7.2-beta.7 → 2026.8.1-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 (78) hide show
  1. package/dist/{account-inspect-DEKpg9Ip.js → account-inspect-Drw2gAiN.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-CHAeNZOX.js → accounts-CK4AVI2_.js} +2 -2
  4. package/dist/{accounts.runtime-BHD4Ma2R.js → accounts.runtime-Cb7QwWBz.js} +1 -1
  5. package/dist/{action-runtime-DfuYoMjG.js → action-runtime-BkGe7ny_.js} +148 -76
  6. package/dist/action-runtime.runtime-D9I6uc0Q.js +2 -0
  7. package/dist/{actions-D3NuJvva.js → actions-BTDXwwE3.js} +85 -44
  8. package/dist/actions.runtime-DLFyUkvg.js +2 -0
  9. package/dist/api.js +15 -15
  10. package/dist/{approval-handler.runtime-BA05P0QT.js → approval-handler.runtime-CJaNzAq2.js} +51 -14
  11. package/dist/{block-text-DkHaoGem.js → block-text-YtiNkqmx.js} +1 -1
  12. package/dist/{channel-B9fVdW3s.js → channel-D_tovcUL.js} +151 -91
  13. package/dist/channel-config-api.js +1 -1
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/{channel-type-DXyos1d2.js → channel-type-B9MSdoGN.js} +9 -8
  16. package/dist/{config-adapter-CxBQH8fq.js → channel.setup-Bch9dYmA.js} +83 -25
  17. package/dist/{config-schema-SgZT6nXV.js → config-schema-xto5jFIx.js} +5 -11
  18. package/dist/{directory-config-CnCIAktf.js → directory-config-CNBz8lJa.js} +3 -3
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-DKunWh3A.js → directory-live-CFKUtW9E.js} +13 -22
  21. package/dist/{doctor-contract-CsGH1Dfc.js → doctor-contract-BAy7-EUQ.js} +30 -3
  22. package/dist/doctor-contract-api.js +1 -1
  23. package/dist/{group-policy-NQZti9t-.js → group-policy-c4RP9bjc.js} +248 -163
  24. package/dist/index.js +4 -1
  25. package/dist/{message-tool-api-DkhFpMoy.js → message-tool-api-BykQB4AU.js} +14 -3
  26. package/dist/message-tool-api.js +1 -1
  27. package/dist/{monitor-CmKz0wtI.js → monitor-1nF1NtqT.js} +3 -3
  28. package/dist/{outbound-adapter-BkuMp2Vs.js → outbound-adapter-S81tsswN.js} +19 -17
  29. package/dist/{pipeline.runtime-DgtmuYCP.js → pipeline.runtime-BvYsM5JO.js} +1087 -682
  30. package/dist/{policy-PRysPn23.js → policy-TapwbeaT.js} +18 -14
  31. package/dist/{probe-CgDsSops.js → probe-HoEg_WxB.js} +38 -18
  32. package/dist/{provider-DmRizMZt.js → provider-CDNvBXUi.js} +3422 -2590
  33. package/dist/{relay-source-Blxj8xb4.js → relay-source-C9leF11u.js} +11 -21
  34. package/dist/{replies-4s_Vq_z9.js → replies-CeOfv82I.js} +52 -6
  35. package/dist/{resolve-channels-yEqmM-3I.js → resolve-channels-CNPrxaXY.js} +39 -12
  36. package/dist/{resolve-users-BOrt5K-5.js → resolve-users-Dzomuwnr.js} +28 -5
  37. package/dist/{runtime-api-QMb-Q5Ko.js → runtime-api-Cj9nxBNv.js} +3 -3
  38. package/dist/runtime-api.js +11 -11
  39. package/dist/{scopes-BJSrkAp6.js → scopes-cYXKkrRD.js} +1 -1
  40. package/dist/{send-DsLeZpST.js → send-Nor0iBwY.js} +211 -105
  41. package/dist/{send.runtime-gUdK6V3h.js → send.runtime-BmgNe6S9.js} +1 -1
  42. package/dist/setup-entry.js +1 -4
  43. package/dist/setup-plugin-api.js +1 -1
  44. package/dist/{setup-surface-BeNzrMrJ.js → setup-surface-CbX1-Knh.js} +6 -6
  45. package/dist/{shared-DgIN3Dcr.js → shared-zdT5AMp-.js} +36 -42
  46. package/dist/{slash-dispatch.runtime-zPkyl7dB.js → slash-dispatch.runtime-Bnr9GR1S.js} +1 -1
  47. package/dist/{streaming-compat-3_X-21wW.js → streaming-compat-B-e0mqM0.js} +3 -8
  48. package/dist/{target-parsing-N6lHogYZ.js → target-parsing-BnMD2ZqZ.js} +40 -2
  49. package/dist/{targets-KmjP2E8s.js → targets-Cx5W_n3W.js} +1 -1
  50. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  51. package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +1 -1
  52. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  53. package/node_modules/@slack/socket-mode/node_modules/@types/node/README.md +1 -1
  54. package/node_modules/@slack/socket-mode/node_modules/@types/node/crypto.d.ts +1 -1
  55. package/node_modules/@slack/socket-mode/node_modules/@types/node/package.json +2 -2
  56. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  57. package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +1 -1
  58. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  59. package/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
  60. package/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
  61. package/node_modules/undici/lib/core/request.js +12 -1
  62. package/node_modules/undici/lib/dispatcher/client-h1.js +11 -2
  63. package/node_modules/undici/lib/handler/cache-handler.js +246 -64
  64. package/node_modules/undici/lib/handler/cache-revalidation-handler.js +3 -3
  65. package/node_modules/undici/lib/handler/retry-handler.js +24 -0
  66. package/node_modules/undici/lib/interceptor/cache.js +159 -52
  67. package/node_modules/undici/lib/util/cache.js +324 -62
  68. package/node_modules/undici/lib/util/date.js +23 -6
  69. package/node_modules/undici/lib/web/cookies/util.js +79 -9
  70. package/node_modules/undici/package.json +1 -1
  71. package/openclaw.plugin.json +239 -34
  72. package/package.json +9 -9
  73. package/skills/slack/SKILL.md +10 -68
  74. package/dist/action-runtime.runtime-DQErZYpz.js +0 -2
  75. package/dist/actions.runtime-BIRU_G4M.js +0 -2
  76. package/dist/channel.setup-CLP5oTvh.js +0 -56
  77. package/dist/preflight-audio.runtime-D5Bgags0.js +0 -3
  78. package/dist/slash-plugin-commands.runtime-Dosfcx3X.js +0 -2
@@ -1,4 +1,4 @@
1
- import { i as resolveDefaultSlackAccountId, r as mergeSlackAccountConfig } from "./accounts-CHAeNZOX.js";
1
+ import { i as resolveDefaultSlackAccountId, r as mergeSlackAccountConfig } from "./accounts-CK4AVI2_.js";
2
2
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
3
3
  import { hasConfiguredSecretInput, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -1,4 +1,4 @@
1
- import { t as inspectSlackAccount } from "./account-inspect-DEKpg9Ip.js";
1
+ import { t as inspectSlackAccount } from "./account-inspect-Drw2gAiN.js";
2
2
  //#region extensions/slack/account-inspect-api.ts
3
3
  function inspectSlackReadOnlyAccount(cfg, accountId) {
4
4
  return inspectSlackAccount({
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, hasConfiguredAccountValue, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
2
2
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
3
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { mapAllowFromEntries, normalizeChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
5
5
  import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
6
6
  //#region extensions/slack/src/token.ts
@@ -60,7 +60,7 @@ function resolveSlackAccountConfig(cfg, accountId) {
60
60
  return resolveAccountEntry(cfg.channels?.slack?.accounts, accountId);
61
61
  }
62
62
  function asStreamingConfigObject(value) {
63
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
63
+ return asOptionalRecord(value);
64
64
  }
65
65
  function asLegacyStreamingScalar(value) {
66
66
  return typeof value === "boolean" || typeof value === "string" ? value : void 0;
@@ -1,2 +1,2 @@
1
- import { a as resolveSlackAccount, l as resolveSlackOperationToken, o as resolveSlackAccountAllowFrom } from "./accounts-CHAeNZOX.js";
1
+ import { a as resolveSlackAccount, l as resolveSlackOperationToken, o as resolveSlackAccountAllowFrom } from "./accounts-CK4AVI2_.js";
2
2
  export { resolveSlackAccount, resolveSlackAccountAllowFrom, resolveSlackOperationToken };
@@ -1,8 +1,8 @@
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, rt as parseSlackBlocksInput } from "./group-policy-NQZti9t-.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-QMb-Q5Ko.js";
5
- import { n as resolveSlackChannelConfig, t as isSlackChannelAllowedByPolicy } from "./policy-PRysPn23.js";
1
+ import { a as parseSlackTarget, n as formatSlackTarget, o as resolveSlackChannelId } from "./target-parsing-BnMD2ZqZ.js";
2
+ import { t as slackContextTargetsMatch } from "./targets-Cx5W_n3W.js";
3
+ import { St as getSlackInstallationKind, T as hasSlackNativeDataBlock, lt as parseSlackBlocksInput, p as assertSlackDetachedTargetAllowed, t as buildSlackChannelIdCandidates } from "./group-policy-c4RP9bjc.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-Cj9nxBNv.js";
5
+ import { n as resolveSlackChannelConfig, t as isSlackChannelAllowedByPolicy } from "./policy-TapwbeaT.js";
6
6
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
7
7
  import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
@@ -24,9 +24,10 @@ const pinActions = /* @__PURE__ */ new Set([
24
24
  "unpinMessage",
25
25
  "listPins"
26
26
  ]);
27
- const loadSlackActionsRuntime = createLazyRuntimeModule(() => import("./actions.runtime-BIRU_G4M.js"));
28
- const loadSlackAccountsRuntime = createLazyRuntimeModule(() => import("./accounts.runtime-BHD4Ma2R.js"));
29
- const loadSlackChannelTypeRuntime = createLazyRuntimeModule(() => import("./channel-type-DXyos1d2.js").then((n) => n.t));
27
+ const SLACK_REACTION_USER_LIMIT = 100;
28
+ const loadSlackActionsRuntime = createLazyRuntimeModule(() => import("./actions.runtime-DLFyUkvg.js"));
29
+ const loadSlackAccountsRuntime = createLazyRuntimeModule(() => import("./accounts.runtime-Cb7QwWBz.js"));
30
+ const loadSlackChannelTypeRuntime = createLazyRuntimeModule(() => import("./channel-type-B9MSdoGN.js").then((n) => n.t));
30
31
  function createLazySlackAction(key) {
31
32
  return (async (...args) => {
32
33
  const action = (await loadSlackActionsRuntime())[key];
@@ -116,7 +117,7 @@ async function isSlackDmTargetConfigured(params) {
116
117
  }
117
118
  function isCurrentSlackReadTarget(params) {
118
119
  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
+ return Boolean(normalizeOptionalLowercaseString(params.context?.currentChannelProvider) === "slack" && requesterAccountId && normalizeAccountId(requesterAccountId) === normalizeAccountId(params.account.accountId) && params.context && slackContextTargetsMatch(params.target, params.context));
120
121
  }
121
122
  function assertSlackMemberInfoAllowed(params) {
122
123
  if (params.context?.conversationReadOrigin === "direct-operator") return;
@@ -128,6 +129,8 @@ function resolveSlackChannelReadPolicy(params) {
128
129
  const channels = params.account.config.channels;
129
130
  const channelKeys = Object.keys(channels ?? {});
130
131
  const channelConfig = resolveSlackChannelConfig({
132
+ teamId: params.teamId,
133
+ allowUnscoped: getSlackInstallationKind(params.account.accountId) !== "enterprise",
131
134
  channelId: params.channelId,
132
135
  channelName: params.channelName,
133
136
  channels,
@@ -163,7 +166,7 @@ function resolveSlackChannelReadPolicy(params) {
163
166
  return {
164
167
  channelAllowed: baseChannelAllowed,
165
168
  channelExplicitlyDisabled,
166
- groupDmAllowed: params.account.config.dm?.enabled !== false && params.account.config.dm?.groupEnabled === true && (params.currentConversation || isSlackGroupDmTargetConfigured(params.account, params.channelId)),
169
+ groupDmAllowed: params.account.config.dm?.enabled !== false && params.account.config.dm?.groupEnabled === true && (params.currentConversation || isSlackGroupDmTargetConfigured(params.account, params.channelId, params.teamId)),
167
170
  shouldResolveName
168
171
  };
169
172
  }
@@ -173,7 +176,11 @@ async function assertSlackReadTargetAllowed(params) {
173
176
  };
174
177
  const currentConversation = isCurrentSlackReadTarget({
175
178
  account: params.account,
176
- channelId: params.channelId,
179
+ target: formatSlackTarget({
180
+ teamId: params.teamId,
181
+ kind: "channel",
182
+ id: params.channelId
183
+ }),
177
184
  context: params.context
178
185
  });
179
186
  const directOperator = params.conversationReadOrigin === "direct-operator";
@@ -184,6 +191,7 @@ async function assertSlackReadTargetAllowed(params) {
184
191
  cfg: params.cfg,
185
192
  accountId: params.account.accountId,
186
193
  channelId: params.channelId,
194
+ teamId: params.teamId,
187
195
  operation: "read"
188
196
  });
189
197
  if (info.type !== "dm" || !await isSlackDmTargetConfigured({
@@ -205,6 +213,7 @@ async function assertSlackReadTargetAllowed(params) {
205
213
  cfg: params.cfg,
206
214
  accountId: params.account.accountId,
207
215
  channelId: params.channelId,
216
+ teamId: params.teamId,
208
217
  operation: "read",
209
218
  ...preliminary.shouldResolveName ? { requireFreshName: true } : {}
210
219
  });
@@ -225,17 +234,53 @@ async function assertSlackReadTargetAllowed(params) {
225
234
  }
226
235
  if (!(info.type === "channel" ? resolved.channelAllowed : info.type === "group" ? resolved.groupDmAllowed : resolved.channelAllowed && resolved.groupDmAllowed)) deny();
227
236
  }
228
- function isSlackGroupDmTargetConfigured(account, channelId) {
237
+ function isSlackGroupDmTargetConfigured(account, channelId, teamId) {
229
238
  const entries = account.config.dm?.groupChannels ?? [];
230
239
  if (entries.length === 0) return true;
240
+ const candidates = new Set(buildSlackChannelIdCandidates(channelId, teamId, { allowUnscoped: getSlackInstallationKind(account.accountId) !== "enterprise" }).map((candidate) => candidate.toLowerCase()));
231
241
  const target = channelId.trim().toLowerCase();
232
242
  return entries.some((entry) => {
233
243
  const candidate = String(entry).trim().toLowerCase();
234
- return candidate === "*" || candidate === target || candidate === `slack:${target}` || candidate === `channel:${target}` || candidate === `group:${target}` || candidate === `mpim:${target}`;
244
+ return candidate === "*" || candidates.has(candidate) || candidate === target || candidate === `slack:${target}` || candidate === `channel:${target}` || candidate === `group:${target}` || candidate === `mpim:${target}`;
245
+ });
246
+ }
247
+ function resolveTrustedCurrentSlackTeamId(params) {
248
+ const requesterAccountId = params.context?.requesterAccountId?.trim();
249
+ if (normalizeOptionalLowercaseString(params.context?.currentChannelProvider) !== "slack" || !requesterAccountId || normalizeAccountId(requesterAccountId) !== normalizeAccountId(params.account.accountId)) return;
250
+ const matchingTeams = /* @__PURE__ */ new Map();
251
+ for (const raw of [params.context?.currentChannelId, params.context?.currentMessagingTarget]) {
252
+ if (!raw) continue;
253
+ const current = parseSlackTarget(raw);
254
+ if (current?.teamId && (!params.target || current.kind === params.target.kind && current.id.toLowerCase() === params.target.id.toLowerCase())) matchingTeams.set(current.teamId.toLowerCase(), current.teamId);
255
+ }
256
+ return matchingTeams.size === 1 ? matchingTeams.values().next().value : void 0;
257
+ }
258
+ function resolveSlackActionTarget(account, raw, context) {
259
+ const parsed = parseSlackTarget(raw, { defaultKind: "channel" });
260
+ if (!parsed) throw new Error("Slack target is required.");
261
+ const teamId = parsed.teamId ?? resolveTrustedCurrentSlackTeamId({
262
+ account,
263
+ target: parsed,
264
+ context
235
265
  });
266
+ assertSlackDetachedTargetAllowed(account.accountId, teamId);
267
+ return {
268
+ routingTarget: teamId ? formatSlackTarget({
269
+ teamId,
270
+ kind: parsed.kind,
271
+ id: parsed.id
272
+ }) : raw,
273
+ teamId
274
+ };
275
+ }
276
+ function resolveSlackActionChannelTarget(account, raw, context) {
277
+ const resolved = resolveSlackActionTarget(account, raw, context);
278
+ return {
279
+ channelId: resolveSlackChannelId(raw),
280
+ teamId: resolved.teamId
281
+ };
236
282
  }
237
283
  async function handleSlackAction(params, cfg, context) {
238
- const resolveChannelId = () => resolveSlackChannelId(readStringParam(params, "channelId", { required: true }));
239
284
  const action = readStringParam(params, "action", { required: true });
240
285
  const accountId = readStringParam(params, "accountId");
241
286
  const { resolveSlackAccount, resolveSlackOperationToken } = await loadSlackAccountsRuntime();
@@ -243,38 +288,42 @@ async function handleSlackAction(params, cfg, context) {
243
288
  cfg,
244
289
  accountId
245
290
  });
246
- if (account.config.enterpriseOrgInstall === true) throw new Error("Slack action tools are unavailable for Enterprise Grid org installs.");
291
+ const resolveChannelTarget = () => resolveSlackActionChannelTarget(account, readStringParam(params, "channelId", { required: true }), context);
247
292
  const isActionEnabled = createActionGate(account.actions ?? cfg.channels?.slack?.actions);
248
293
  const botToken = account.botToken?.trim();
249
- const buildActionOpts = (operation) => {
294
+ const buildActionOpts = (operation, teamId) => {
250
295
  const token = resolveSlackOperationToken(account, operation);
251
296
  if (!token && account.identity === "user") throw new Error(`Slack operation token missing for account "${account.accountId}".`);
252
297
  const tokenOverride = token && token !== botToken ? token : void 0;
253
298
  return {
254
299
  cfg,
255
300
  ...accountId ? { accountId } : {},
256
- ...tokenOverride ? { token: tokenOverride } : {}
301
+ ...tokenOverride ? { token: tokenOverride } : {},
302
+ teamId
257
303
  };
258
304
  };
259
- const readOpts = buildActionOpts("read");
260
- const writeOpts = buildActionOpts("write");
261
- const assertReadTargetAllowed = async (channelId) => await assertSlackReadTargetAllowed({
262
- account,
263
- cfg,
264
- channelId,
265
- conversationReadOrigin: context?.conversationReadOrigin,
266
- context
267
- });
305
+ const assertReadTargetAllowed = async (target) => {
306
+ await assertSlackReadTargetAllowed({
307
+ account,
308
+ cfg,
309
+ channelId: target.channelId,
310
+ teamId: target.teamId,
311
+ conversationReadOrigin: context?.conversationReadOrigin,
312
+ context
313
+ });
314
+ };
268
315
  if (reactionsActions.has(action)) {
269
316
  if (!isActionEnabled("reactions")) throw new Error("Slack reactions are disabled.");
270
- const channelId = resolveChannelId();
317
+ const target = resolveChannelTarget();
318
+ const { channelId } = target;
319
+ const readOpts = buildActionOpts("read", target.teamId);
320
+ const writeOpts = buildActionOpts("write", target.teamId);
271
321
  const messageId = readStringParam(params, "messageId", { required: true });
272
322
  if (action === "react") {
273
323
  const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Slack reaction." });
274
- await assertReadTargetAllowed(channelId);
324
+ await assertReadTargetAllowed(target);
275
325
  if (remove) {
276
- if (writeOpts) await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji, writeOpts);
277
- else await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji);
326
+ await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji, writeOpts);
278
327
  return jsonResult({
279
328
  ok: true,
280
329
  removed: emoji
@@ -282,44 +331,47 @@ async function handleSlackAction(params, cfg, context) {
282
331
  }
283
332
  if (isEmpty) return jsonResult({
284
333
  ok: true,
285
- removed: writeOpts ? await slackActionRuntime.removeOwnSlackReactions(channelId, messageId, writeOpts) : await slackActionRuntime.removeOwnSlackReactions(channelId, messageId)
334
+ removed: await slackActionRuntime.removeOwnSlackReactions(channelId, messageId, writeOpts)
286
335
  });
287
- if (writeOpts) await slackActionRuntime.reactSlackMessage(channelId, messageId, emoji, writeOpts);
288
- else await slackActionRuntime.reactSlackMessage(channelId, messageId, emoji);
336
+ await slackActionRuntime.reactSlackMessage(channelId, messageId, emoji, writeOpts);
289
337
  return jsonResult({
290
338
  ok: true,
291
339
  added: emoji
292
340
  });
293
341
  }
294
- await assertReadTargetAllowed(channelId);
342
+ await assertReadTargetAllowed(target);
343
+ const limit = Math.min(readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." }) ?? SLACK_REACTION_USER_LIMIT, SLACK_REACTION_USER_LIMIT);
295
344
  return jsonResult({
296
345
  ok: true,
297
- reactions: readOpts ? await slackActionRuntime.listSlackReactions(channelId, messageId, readOpts) : await slackActionRuntime.listSlackReactions(channelId, messageId)
346
+ reactions: (await slackActionRuntime.listSlackReactions(channelId, messageId, readOpts))?.map((reaction) => reaction.users ? Object.assign({}, reaction, { users: reaction.users.slice(0, limit) }) : reaction)
298
347
  });
299
348
  }
300
349
  if (messagingActions.has(action)) {
301
350
  if (!isActionEnabled("messages")) throw new Error("Slack messages are disabled.");
302
351
  switch (action) {
303
352
  case "sendMessage": {
304
- const to = readStringParam(params, "to", { required: true });
353
+ const destination = resolveSlackActionTarget(account, readStringParam(params, "to", { required: true }), context).routingTarget;
305
354
  const content = readStringParam(params, "content", { allowEmpty: true });
306
355
  const mediaUrl = readStringParam(params, "mediaUrl");
307
356
  const blocks = readSlackBlocksParam(params);
308
357
  const replyBroadcast = readBooleanParam(params, "replyBroadcast");
309
358
  const textIsSlackMrkdwn = readBooleanParam(params, "textIsSlackMrkdwn");
310
359
  const textIsSlackPlainText = readBooleanParam(params, "textIsSlackPlainText");
360
+ const forceDocument = readBooleanParam(params, "forceDocument") === true;
311
361
  const preparedMessages = context?.preparedMessages;
312
362
  const authoredTextPlacement = readStringParam(params, "authoredTextPlacement");
313
363
  if (authoredTextPlacement && authoredTextPlacement !== "none" && authoredTextPlacement !== "blocks" && authoredTextPlacement !== "outside-blocks") throw new Error("Slack authoredTextPlacement is invalid.");
314
364
  const nativeDataFallbackBaseText = readStringParam(params, "nativeDataFallbackBaseText", { allowEmpty: true });
315
365
  if (!content && !mediaUrl && !blocks && !preparedMessages?.length) throw new Error("Slack sendMessage requires content, blocks, or mediaUrl.");
316
366
  if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
317
- const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), to, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
367
+ const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), destination, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
318
368
  const baseSendOpts = {
319
- ...writeOpts,
369
+ ...buildActionOpts("write"),
370
+ mediaAccess: context?.mediaAccess,
320
371
  mediaLocalRoots: context?.mediaLocalRoots,
321
372
  mediaReadFile: context?.mediaReadFile,
322
- threadTs: threadTs ?? void 0
373
+ threadTs: threadTs ?? void 0,
374
+ ...forceDocument ? { forceDocument: true } : {}
323
375
  };
324
376
  const sendOpts = {
325
377
  ...baseSendOpts,
@@ -333,24 +385,24 @@ async function handleSlackAction(params, cfg, context) {
333
385
  const shouldSplitLongContent = content && content.length > 8e3 && !hasSlackNativeDataBlock(blocks);
334
386
  if (content && shouldSplitLongContent) {
335
387
  const { replyBroadcast: _replyBroadcast, ...blockSendOpts } = sendOpts;
336
- await slackActionRuntime.sendSlackMessage(to, "", {
388
+ await slackActionRuntime.sendSlackMessage(destination, "", {
337
389
  ...blockSendOpts,
338
390
  blocks
339
391
  });
340
- return await slackActionRuntime.sendSlackMessage(to, content, sendOpts);
392
+ return await slackActionRuntime.sendSlackMessage(destination, content, sendOpts);
341
393
  }
342
- return await slackActionRuntime.sendSlackMessage(to, content ?? "", {
394
+ return await slackActionRuntime.sendSlackMessage(destination, content ?? "", {
343
395
  ...sendOpts,
344
396
  blocks
345
397
  });
346
398
  };
347
399
  const result = preparedMessages?.length ? await (async () => {
348
400
  let lastResult;
349
- if (mediaUrl) lastResult = await slackActionRuntime.sendSlackMessage(to, "", {
401
+ if (mediaUrl) lastResult = await slackActionRuntime.sendSlackMessage(destination, "", {
350
402
  ...baseSendOpts,
351
403
  mediaUrl
352
404
  });
353
- for (const [index, message] of preparedMessages.entries()) lastResult = await slackActionRuntime.sendSlackMessage(to, message.text, {
405
+ for (const [index, message] of preparedMessages.entries()) lastResult = await slackActionRuntime.sendSlackMessage(destination, message.text, {
354
406
  ...baseSendOpts,
355
407
  ...index === 0 && replyBroadcast ? { replyBroadcast: true } : {},
356
408
  ...message.blocks ? { blocks: message.blocks } : {},
@@ -361,24 +413,24 @@ async function handleSlackAction(params, cfg, context) {
361
413
  if (!lastResult) throw new Error("Slack prepared message plan produced no delivery.");
362
414
  return lastResult;
363
415
  })() : blocks ? await (async () => {
364
- if (mediaUrl) await slackActionRuntime.sendSlackMessage(to, "", {
416
+ if (mediaUrl) await slackActionRuntime.sendSlackMessage(destination, "", {
365
417
  ...sendOpts,
366
418
  mediaUrl
367
419
  });
368
420
  return await sendContentAndBlocks();
369
- })() : await slackActionRuntime.sendSlackMessage(to, content ?? "", {
421
+ })() : await slackActionRuntime.sendSlackMessage(destination, content ?? "", {
370
422
  ...sendOpts,
371
423
  mediaUrl: mediaUrl ?? void 0,
372
424
  blocks
373
425
  });
374
- if (context?.hasRepliedRef && slackContextTargetsMatch(to, context)) context.hasRepliedRef.value = true;
426
+ if (context?.hasRepliedRef && slackContextTargetsMatch(destination, context)) context.hasRepliedRef.value = true;
375
427
  return jsonResult({
376
428
  ok: true,
377
429
  result
378
430
  });
379
431
  }
380
432
  case "uploadFile": {
381
- const to = readStringParam(params, "to", { required: true });
433
+ const destination = resolveSlackActionTarget(account, readStringParam(params, "to", { required: true }), context).routingTarget;
382
434
  const filePath = readStringParam(params, "filePath", {
383
435
  required: true,
384
436
  trim: false
@@ -386,48 +438,55 @@ async function handleSlackAction(params, cfg, context) {
386
438
  const initialComment = readStringParam(params, "initialComment", { allowEmpty: true });
387
439
  const filename = readStringParam(params, "filename");
388
440
  const title = readStringParam(params, "title");
441
+ const forceDocument = readBooleanParam(params, "forceDocument") === true;
389
442
  if (readBooleanParam(params, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
390
- const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), to, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
391
- const result = await slackActionRuntime.sendSlackMessage(to, initialComment ?? "", {
392
- ...writeOpts,
443
+ const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), destination, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
444
+ const result = await slackActionRuntime.sendSlackMessage(destination, initialComment ?? "", {
445
+ ...buildActionOpts("write"),
393
446
  mediaUrl: filePath,
447
+ mediaAccess: context?.mediaAccess,
394
448
  mediaLocalRoots: context?.mediaLocalRoots,
395
449
  mediaReadFile: context?.mediaReadFile,
396
450
  threadTs: threadTs ?? void 0,
451
+ ...forceDocument ? { forceDocument: true } : {},
397
452
  ...filename ? { uploadFileName: filename } : {},
398
453
  ...title ? { uploadTitle: title } : {}
399
454
  });
400
- if (context?.hasRepliedRef && slackContextTargetsMatch(to, context)) context.hasRepliedRef.value = true;
455
+ if (context?.hasRepliedRef && slackContextTargetsMatch(destination, context)) context.hasRepliedRef.value = true;
401
456
  return jsonResult({
402
457
  ok: true,
403
458
  result
404
459
  });
405
460
  }
406
461
  case "editMessage": {
407
- const channelId = resolveChannelId();
462
+ const target = resolveChannelTarget();
463
+ const { channelId } = target;
408
464
  const messageId = readStringParam(params, "messageId", { required: true });
409
465
  const content = readStringParam(params, "content", { allowEmpty: true });
410
466
  const blocks = readSlackBlocksParam(params);
411
467
  if (!content && !blocks) throw new Error("Slack editMessage requires content or blocks.");
412
- await assertReadTargetAllowed(channelId);
413
- if (writeOpts) await slackActionRuntime.editSlackMessage(channelId, messageId, content ?? "", {
468
+ await assertReadTargetAllowed(target);
469
+ const writeOpts = buildActionOpts("write", target.teamId);
470
+ await slackActionRuntime.editSlackMessage(channelId, messageId, content ?? "", {
414
471
  ...writeOpts,
415
472
  blocks
416
473
  });
417
- else await slackActionRuntime.editSlackMessage(channelId, messageId, content ?? "", { blocks });
418
474
  return jsonResult({ ok: true });
419
475
  }
420
476
  case "deleteMessage": {
421
- const channelId = resolveChannelId();
477
+ const target = resolveChannelTarget();
478
+ const { channelId } = target;
422
479
  const messageId = readStringParam(params, "messageId", { required: true });
423
- await assertReadTargetAllowed(channelId);
424
- if (writeOpts) await slackActionRuntime.deleteSlackMessage(channelId, messageId, writeOpts);
425
- else await slackActionRuntime.deleteSlackMessage(channelId, messageId);
480
+ await assertReadTargetAllowed(target);
481
+ const writeOpts = buildActionOpts("write", target.teamId);
482
+ await slackActionRuntime.deleteSlackMessage(channelId, messageId, writeOpts);
426
483
  return jsonResult({ ok: true });
427
484
  }
428
485
  case "readMessages": {
429
- const channelId = resolveChannelId();
430
- await assertReadTargetAllowed(channelId);
486
+ const target = resolveChannelTarget();
487
+ const { channelId } = target;
488
+ await assertReadTargetAllowed(target);
489
+ const readOpts = buildActionOpts("read", target.teamId);
431
490
  const limit = readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." });
432
491
  const before = readStringParam(params, "before");
433
492
  const after = readStringParam(params, "after");
@@ -454,14 +513,16 @@ async function handleSlackAction(params, cfg, context) {
454
513
  const fileId = readStringParam(params, "fileId", { required: true });
455
514
  const channelTarget = readStringParam(params, "channelId") ?? readStringParam(params, "to") ?? context?.currentChannelId;
456
515
  if (!channelTarget) throw new Error("Slack file download requires channelId or to so the read target can be authorized.");
457
- const channelId = resolveSlackChannelId(channelTarget);
458
- await assertReadTargetAllowed(channelId);
516
+ const target = resolveSlackActionChannelTarget(account, channelTarget, context);
517
+ const { channelId } = target;
518
+ await assertReadTargetAllowed(target);
459
519
  const threadId = readStringParam(params, "threadId") ?? readStringParam(params, "replyTo");
460
520
  const maxBytes = account.config?.mediaMaxMb ? account.config.mediaMaxMb * 1024 * 1024 : 20 * 1024 * 1024;
461
521
  const readToken = resolveSlackOperationToken(account, "read");
522
+ const readOpts = buildActionOpts("read", target.teamId);
462
523
  const downloaded = await slackActionRuntime.downloadSlackFile(fileId, {
463
524
  ...readOpts,
464
- ...readToken && !readOpts?.token ? { token: readToken } : {},
525
+ ...readToken && !readOpts.token ? { token: readToken } : {},
465
526
  maxBytes,
466
527
  channelId,
467
528
  threadId: threadId ?? void 0
@@ -499,25 +560,26 @@ async function handleSlackAction(params, cfg, context) {
499
560
  }
500
561
  if (pinActions.has(action)) {
501
562
  if (!isActionEnabled("pins")) throw new Error("Slack pins are disabled.");
502
- const channelId = resolveChannelId();
563
+ const target = resolveChannelTarget();
564
+ const { channelId } = target;
565
+ const readOpts = buildActionOpts("read", target.teamId);
566
+ const writeOpts = buildActionOpts("write", target.teamId);
503
567
  if (action === "pinMessage") {
504
568
  const messageId = readStringParam(params, "messageId", { required: true });
505
- await assertReadTargetAllowed(channelId);
506
- if (writeOpts) await slackActionRuntime.pinSlackMessage(channelId, messageId, writeOpts);
507
- else await slackActionRuntime.pinSlackMessage(channelId, messageId);
569
+ await assertReadTargetAllowed(target);
570
+ await slackActionRuntime.pinSlackMessage(channelId, messageId, writeOpts);
508
571
  return jsonResult({ ok: true });
509
572
  }
510
573
  if (action === "unpinMessage") {
511
574
  const messageId = readStringParam(params, "messageId", { required: true });
512
- await assertReadTargetAllowed(channelId);
513
- if (writeOpts) await slackActionRuntime.unpinSlackMessage(channelId, messageId, writeOpts);
514
- else await slackActionRuntime.unpinSlackMessage(channelId, messageId);
575
+ await assertReadTargetAllowed(target);
576
+ await slackActionRuntime.unpinSlackMessage(channelId, messageId, writeOpts);
515
577
  return jsonResult({ ok: true });
516
578
  }
517
- await assertReadTargetAllowed(channelId);
579
+ await assertReadTargetAllowed(target);
518
580
  return jsonResult({
519
581
  ok: true,
520
- pins: (writeOpts ? await slackActionRuntime.listSlackPins(channelId, readOpts) : await slackActionRuntime.listSlackPins(channelId)).map((pin) => {
582
+ pins: (await slackActionRuntime.listSlackPins(channelId, readOpts)).map((pin) => {
521
583
  const message = pin.message ? withNormalizedTimestamp(pin.message, pin.message.ts) : pin.message;
522
584
  return message ? Object.assign({}, pin, { message }) : pin;
523
585
  })
@@ -531,15 +593,25 @@ async function handleSlackAction(params, cfg, context) {
531
593
  context,
532
594
  userId
533
595
  });
596
+ const teamId = resolveTrustedCurrentSlackTeamId({
597
+ account,
598
+ context
599
+ });
600
+ assertSlackDetachedTargetAllowed(account.accountId, teamId);
534
601
  return jsonResult({
535
602
  ok: true,
536
- info: readOpts ? await slackActionRuntime.getSlackMemberInfo(userId, readOpts) : await slackActionRuntime.getSlackMemberInfo(userId)
603
+ info: await slackActionRuntime.getSlackMemberInfo(userId, buildActionOpts("read", teamId))
537
604
  });
538
605
  }
539
606
  if (action === "emojiList") {
540
607
  if (!isActionEnabled("emojiList")) throw new Error("Slack emoji list is disabled.");
541
608
  const limit = readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." });
542
- const result = readOpts ? await slackActionRuntime.listSlackEmojis(readOpts) : await slackActionRuntime.listSlackEmojis();
609
+ const teamId = resolveTrustedCurrentSlackTeamId({
610
+ account,
611
+ context
612
+ });
613
+ assertSlackDetachedTargetAllowed(account.accountId, teamId);
614
+ const result = await slackActionRuntime.listSlackEmojis(buildActionOpts("read", teamId));
543
615
  if (limit != null && limit > 0 && result.emoji != null) {
544
616
  const entries = Object.entries(result.emoji).toSorted(([a], [b]) => a.localeCompare(b));
545
617
  if (entries.length > limit) return jsonResult({
@@ -0,0 +1,2 @@
1
+ import { t as handleSlackAction } from "./action-runtime-BkGe7ny_.js";
2
+ export { handleSlackAction };