@openclaw/slack 2026.7.1 → 2026.7.2-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 (72) hide show
  1. package/dist/accounts.runtime-KvftRRek.js +2 -0
  2. package/dist/{action-runtime-DoQGk_8D.js → action-runtime-Cee2ih0s.js} +209 -30
  3. package/dist/action-runtime.runtime-DZfd7IFr.js +2 -0
  4. package/dist/{actions-DMpDmKEA.js → actions-BZiuSTIq.js} +88 -143
  5. package/dist/{actions.runtime-C103_BPW.js → actions.runtime-DoD0-gxw.js} +1 -1
  6. package/dist/api.js +14 -13
  7. package/dist/{approval-handler.runtime-CIUbOt5T.js → approval-handler.runtime-CUPtIM4k.js} +3 -3
  8. package/dist/{channel-BjlsaGHn.js → channel-DaIiGUOp.js} +119 -141
  9. package/dist/channel-config-api.js +1 -1
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/channel-type-Cfm6_6n1.js +109 -0
  12. package/dist/{channel.setup-Dq6syTNU.js → channel.setup-C-mLz50O.js} +3 -3
  13. package/dist/{client-DGxwSL7f.js → client-WIPAS3Yr.js} +46 -2
  14. package/dist/config-api-Df9a1B8C.js +3 -0
  15. package/dist/{config-schema-BzqzFW__.js → config-schema-xPSnK2VK.js} +32 -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-D_yZhjgp.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-85UWiriS.js +2345 -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-CalGciTs.js} +3 -3
  28. package/dist/outbound-adapter-BiLKcnyH.js +228 -0
  29. package/dist/{pipeline.runtime-rpVpay59.js → pipeline.runtime-DofAvTtb.js} +657 -221
  30. package/dist/{policy-Dj-puVPb.js → policy-BVs4LiSa.js} +7 -7
  31. package/dist/preflight-audio.runtime-D5Bgags0.js +3 -0
  32. package/dist/{probe-CuwRDE5j.js → probe-CN0ssfLN.js} +2 -2
  33. package/dist/{provider-C1-DFSpw.js → provider-CmeoUiIM.js} +907 -206
  34. package/dist/{relay-source-D2jv1iGg.js → relay-source-DMmgtvg4.js} +6 -17
  35. package/dist/replies-CJJCp6qz.js +420 -0
  36. package/dist/{resolve-channels-CstkChBE.js → resolve-channels-Rfts6POK.js} +17 -6
  37. package/dist/{resolve-users-C3NP2c-Q.js → resolve-users-y6wAxR8E.js} +11 -6
  38. package/dist/runtime-JSVZSWAj.js +8 -0
  39. package/dist/{runtime-api-CEmqYxR-.js → runtime-api-BGDyOt1D.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-CuxNQZ6v.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-DYp8ca-l.js} +662 -325
  46. package/dist/{send.runtime-GPRa63l1.js → send.runtime-CJLxAt26.js} +1 -1
  47. package/dist/{setup-core-fGd6Gquy.js → setup-core-CkwVLzFO.js} +15 -21
  48. package/dist/setup-plugin-api.js +1 -1
  49. package/dist/{setup-surface-Dv2fIJNB.js → setup-surface-oSd3NX9J.js} +4 -4
  50. package/dist/{shared-CosfcFri.js → shared-D9yz5Otg.js} +17 -38
  51. package/dist/{slash-dispatch.runtime-CcMbbT3_.js → slash-dispatch.runtime-CSja9VuD.js} +1 -1
  52. package/dist/{streaming-compat-DjlgH-Be.js → streaming-compat-3_X-21wW.js} +1 -0
  53. package/dist/{target-parsing-3jYH8LfB.js → target-parsing-N6lHogYZ.js} +16 -3
  54. package/dist/{targets-Dll4NJgs.js → targets-KmjP2E8s.js} +1 -1
  55. package/node_modules/p-map/index.d.ts +155 -0
  56. package/node_modules/p-map/index.js +284 -0
  57. package/node_modules/p-map/license +9 -0
  58. package/node_modules/p-map/package.json +57 -0
  59. package/node_modules/p-map/readme.md +190 -0
  60. package/npm-shrinkwrap.json +16 -3
  61. package/openclaw.plugin.json +84 -0
  62. package/package.json +7 -7
  63. package/dist/accounts.runtime-DWvaCb-X.js +0 -2
  64. package/dist/action-runtime.runtime-BABj3aM-.js +0 -2
  65. package/dist/config-api-DnT9ohtE.js +0 -2
  66. package/dist/configured-state.js +0 -11
  67. package/dist/format-YCNoNkM2.js +0 -107
  68. package/dist/outbound-adapter-DVoBfBW5.js +0 -272
  69. package/dist/replies-DpF38e1y.js +0 -287
  70. package/dist/reply-blocks-BGQ6zSqM.js +0 -877
  71. package/dist/resolve-allowlist-common-CP8SH0Zf.js +0 -43
  72. package/dist/runtime-BOk7xkOl.js +0 -8
@@ -1,9 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { a as resolveSlackAccount, p as resolveSlackBotToken } from "./accounts-BOJJiHSr.js";
3
- import { a as SLACK_TEXT_LIMIT, b as truncateSlackText, i as validateSlackBlocksArray } from "./reply-blocks-BGQ6zSqM.js";
4
- import { a as getSlackWriteClient, r as createSlackWebClient } from "./client-DGxwSL7f.js";
5
- import { l as buildSlackBlocksFallbackText, r as sendMessageSlack } from "./send-DKDXoeoV.js";
6
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { A as buildSlackBlocksFallbackText, B as truncateSlackText, E as stripSlackNativeDataBlocks, M as renderSlackBlockFallbackText, P as SLACK_EDIT_TEXT_LIMIT, Q as validateSlackBlocksArray, T as isSlackInvalidBlocksError, b as appendSlackNativeDataFallbackText, j as buildSlackCompleteBlocksFallbackText, q as escapeSlackMrkdwn, w as hasSlackNativeDataBlock, x as appendSlackNativeDataPlainTextFallback } from "./group-policy-85UWiriS.js";
4
+ import { c as getSlackWriteClient, n as createSlackLookupClient } from "./client-WIPAS3Yr.js";
5
+ import { l as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack } from "./send-DYp8ca-l.js";
6
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { logVerbose, logVerbose as logVerbose$1 } from "openclaw/plugin-sdk/runtime-env";
8
8
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
9
9
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -12,14 +12,20 @@ import fs from "node:fs/promises";
12
12
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
13
13
  import { normalizeHostname } from "openclaw/plugin-sdk/host-runtime";
14
14
  import { resolveRequestUrl } from "openclaw/plugin-sdk/request-url";
15
+ import pMap, { pMapSkip } from "p-map";
15
16
  import { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/runtime-fetch";
16
17
  import { saveRemoteMedia } from "openclaw/plugin-sdk/media-runtime";
17
18
  import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
18
19
  //#region extensions/slack/src/edit-text.ts
19
20
  function buildSlackEditTextPayload(content, blocks) {
20
21
  const trimmedContent = content.trim();
21
- if (trimmedContent) return trimmedContent;
22
- if (blocks?.length) return truncateSlackText(buildSlackBlocksFallbackText(blocks), SLACK_TEXT_LIMIT);
22
+ const blockText = blocks?.length ? buildSlackCompleteBlocksFallbackText(blocks).trim() : "";
23
+ if (trimmedContent && !blockText) return trimmedContent;
24
+ if (trimmedContent) {
25
+ const nativePlainText = blocks?.length ? appendSlackNativeDataPlainTextFallback("", blocks).trim() : "";
26
+ return truncateSlackText(Boolean(blockText && trimmedContent.includes(blockText)) || Boolean(nativePlainText && trimmedContent.includes(nativePlainText)) ? trimmedContent : blockText && !blockText.includes(trimmedContent) ? `${trimmedContent}\n\n${blockText}` : blockText || trimmedContent, SLACK_EDIT_TEXT_LIMIT);
27
+ }
28
+ if (blockText) return truncateSlackText(blockText, SLACK_EDIT_TEXT_LIMIT);
23
29
  return " ";
24
30
  }
25
31
  //#endregion
@@ -34,111 +40,38 @@ function formatSlackFileReferenceList(files) {
34
40
  return files.map((file) => formatSlackFileReference(file)).join(", ");
35
41
  }
36
42
  //#endregion
37
- //#region extensions/slack/src/monitor/media-types.ts
38
- const MAX_SLACK_MEDIA_FILES = 8;
39
- //#endregion
40
43
  //#region extensions/slack/src/monitor/block-text.ts
41
- function readTextObject(value) {
42
- if (!value || typeof value !== "object") return;
43
- return normalizeOptionalString(readStringValue(value.text));
44
- }
45
- function renderSlackRichTextLeaf(element) {
46
- switch (element.type) {
47
- case "text": return readStringValue(element.text) ?? "";
48
- case "link": return readStringValue(element.text) ?? readStringValue(element.url) ?? "";
49
- case "user": {
50
- const userId = readStringValue(element.user_id);
51
- return userId ? `<@${userId}>` : "";
52
- }
53
- case "channel": {
54
- const channelId = readStringValue(element.channel_id);
55
- return channelId ? `<#${channelId}>` : "";
56
- }
57
- case "usergroup": {
58
- const usergroupId = readStringValue(element.usergroup_id);
59
- return usergroupId ? `<!subteam^${usergroupId}>` : "";
60
- }
61
- case "broadcast": {
62
- const range = readStringValue(element.range);
63
- return range ? `<!${range}>` : "";
64
- }
65
- case "emoji": {
66
- const name = readStringValue(element.name);
67
- return name ? `:${name}:` : "";
68
- }
69
- default: return "";
70
- }
71
- }
72
- function renderSlackRichTextElements(elements) {
73
- if (!Array.isArray(elements)) return "";
74
- const parts = [];
75
- for (const rawElement of elements) {
76
- if (!rawElement || typeof rawElement !== "object") continue;
77
- const element = rawElement;
78
- switch (element.type) {
79
- case "rich_text_section":
80
- case "rich_text_preformatted":
81
- case "rich_text_quote":
82
- parts.push(renderSlackRichTextElements(element.elements));
83
- break;
84
- case "rich_text_list": {
85
- const listParts = [];
86
- if (Array.isArray(element.elements)) for (const child of element.elements) {
87
- if (!child || typeof child !== "object") continue;
88
- const rendered = renderSlackRichTextElements(child.elements);
89
- if (rendered) listParts.push(rendered);
90
- }
91
- parts.push(listParts.join("\n"));
92
- break;
93
- }
94
- default:
95
- parts.push(renderSlackRichTextLeaf(element));
96
- break;
97
- }
98
- }
99
- return parts.join("");
100
- }
101
- function readSlackBlockText(block) {
102
- if (!block || typeof block !== "object") return;
103
- const blockLike = block;
104
- switch (blockLike.type) {
105
- case "rich_text": return normalizeOptionalString(renderSlackRichTextElements(blockLike.elements));
106
- case "section": {
107
- const text = readTextObject(blockLike.text);
108
- if (text) return text;
109
- if (!Array.isArray(blockLike.fields)) return;
110
- const fields = blockLike.fields.flatMap((field) => readTextObject(field) ?? []);
111
- return fields.length > 0 ? fields.join("\n") : void 0;
112
- }
113
- case "header": return readTextObject(blockLike.text);
114
- case "context": {
115
- if (!Array.isArray(blockLike.elements)) return;
116
- const parts = blockLike.elements.flatMap((element) => readTextObject(element) ?? []);
117
- return parts.length > 0 ? parts.join(" ") : void 0;
118
- }
119
- case "image": return normalizeOptionalString(readStringValue(blockLike.alt_text)) ?? readTextObject(blockLike.title);
120
- case "video": return readTextObject(blockLike.title) ?? normalizeOptionalString(readStringValue(blockLike.alt_text));
121
- default: return;
122
- }
44
+ function readSlackBlockType(block) {
45
+ return block && typeof block === "object" && !Array.isArray(block) ? block.type : void 0;
123
46
  }
124
47
  function resolveSlackBlocksText(blocks) {
125
48
  if (!blocks?.length) return;
126
49
  const parts = [];
127
50
  let hasRichText = false;
51
+ let hasNativeData = false;
128
52
  for (const block of blocks) {
129
- if (block && typeof block === "object" && block.type === "rich_text") hasRichText = true;
130
- const text = readSlackBlockText(block);
53
+ const blockType = readSlackBlockType(block);
54
+ hasRichText ||= blockType === "rich_text";
55
+ hasNativeData ||= blockType === "data_visualization" || blockType === "data_table";
56
+ const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
131
57
  if (text) parts.push(text);
132
58
  }
133
59
  return parts.length > 0 ? {
134
60
  text: parts.join("\n"),
135
- hasRichText
61
+ hasRichText,
62
+ hasNativeData
136
63
  } : void 0;
137
64
  }
138
65
  function chooseSlackPrimaryText(params) {
139
66
  const { messageText, blocksText } = params;
140
67
  if (!blocksText) return messageText;
141
68
  if (!messageText) return blocksText.text;
69
+ if (blocksText.hasNativeData) {
70
+ const comparableMessageText = messageText.replace(/\s+/g, " ").trim();
71
+ const comparableBlocksText = blocksText.text.replace(/\s+/g, " ").trim();
72
+ if (comparableMessageText.includes(comparableBlocksText)) return messageText;
73
+ return comparableBlocksText.startsWith(comparableMessageText) ? blocksText.text : `${messageText}\n${blocksText.text}`;
74
+ }
142
75
  if (blocksText.hasRichText && blocksText.text.length > messageText.length) return blocksText.text;
143
76
  return blocksText.text.length > messageText.length && blocksText.text.startsWith(messageText) ? blocksText.text : messageText;
144
77
  }
@@ -184,11 +117,19 @@ function resolveSlackAttachmentFallbackText(attachments) {
184
117
  return parts.length > 0 ? parts.join("\n") : void 0;
185
118
  }
186
119
  function resolveSlackMessageText(message) {
187
- return normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments) ?? resolveSlackBlocksFallbackText(message.blocks);
120
+ return chooseSlackPrimaryText({
121
+ messageText: normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments),
122
+ blocksText: resolveSlackBlocksText(message.blocks)
123
+ });
188
124
  }
189
125
  async function resolveSlackThreadStarter(params) {
190
126
  evictThreadStarterCache();
191
- const cacheKey = `${params.channelId}:${params.threadTs}`;
127
+ const cacheKey = params.workspaceScope ? JSON.stringify([
128
+ params.workspaceScope.accountId,
129
+ params.workspaceScope.teamId,
130
+ params.channelId,
131
+ params.threadTs
132
+ ]) : `${params.channelId}:${params.threadTs}`;
192
133
  const cached = THREAD_STARTER_CACHE.get(cacheKey);
193
134
  if (cached) {
194
135
  const now = asDateTimestampMs(Date.now());
@@ -283,7 +224,6 @@ async function resolveSlackThreadHistory(params) {
283
224
  //#endregion
284
225
  //#region extensions/slack/src/monitor/media.ts
285
226
  var media_exports = /* @__PURE__ */ __exportAll({
286
- MAX_SLACK_MEDIA_FILES: () => 8,
287
227
  SLACK_MEDIA_READ_IDLE_TIMEOUT_MS: () => SLACK_MEDIA_READ_IDLE_TIMEOUT_MS,
288
228
  resetSlackThreadStarterCacheForTest: () => resetSlackThreadStarterCacheForTest,
289
229
  resolveSlackAttachmentContent: () => resolveSlackAttachmentContent,
@@ -351,30 +291,14 @@ const SLACK_MEDIA_SSRF_POLICY = {
351
291
  };
352
292
  const SLACK_MEDIA_READ_IDLE_TIMEOUT_MS = 6e4;
353
293
  const SLACK_MEDIA_TOTAL_TIMEOUT_MS = 12e4;
354
- function mergeAbortSignals(signals) {
355
- const activeSignals = signals.filter((signal) => Boolean(signal));
356
- if (activeSignals.length === 0) return;
357
- if (activeSignals.length === 1) return activeSignals[0];
358
- if (typeof AbortSignal.any === "function") return AbortSignal.any(activeSignals);
359
- const controller = new AbortController();
360
- for (const signal of activeSignals) if (signal.aborted) {
361
- controller.abort();
362
- return controller.signal;
363
- }
364
- const abort = () => {
365
- controller.abort();
366
- for (const signal of activeSignals) signal.removeEventListener("abort", abort);
367
- };
368
- for (const signal of activeSignals) signal.addEventListener("abort", abort, { once: true });
369
- return controller.signal;
370
- }
371
294
  async function saveSlackMedia(params) {
372
295
  const timeoutAbortController = params.totalTimeoutMs ? new AbortController() : void 0;
373
- const signal = mergeAbortSignals([
296
+ const abortSignals = [
374
297
  params.abortSignal,
375
298
  params.options.requestInit?.signal ?? void 0,
376
299
  timeoutAbortController?.signal
377
- ]);
300
+ ].filter((signal) => Boolean(signal));
301
+ const signal = abortSignals.length > 1 ? AbortSignal.any(abortSignals) : abortSignals[0];
378
302
  let timedOut = false;
379
303
  let timeoutHandle = null;
380
304
  const savePromise = saveRemoteMedia({
@@ -497,34 +421,21 @@ function resolveForwardedAttachmentImageUrl(attachment) {
497
421
  return null;
498
422
  }
499
423
  }
500
- async function mapLimit(items, limit, fn) {
501
- if (items.length === 0) return [];
502
- const results = [];
503
- results.length = items.length;
504
- let nextIndex = 0;
505
- const workerCount = Math.max(1, Math.min(limit, items.length));
506
- await Promise.all(Array.from({ length: workerCount }, async () => {
507
- while (true) {
508
- const idx = nextIndex++;
509
- if (idx >= items.length) return;
510
- results[idx] = await fn(items[idx]);
511
- }
512
- }));
513
- return results;
514
- }
515
424
  /**
516
425
  * Downloads all files attached to a Slack message and returns them as an array.
517
426
  * Returns `null` when no files could be downloaded.
518
427
  */
519
428
  async function resolveSlackMedia(params) {
520
429
  const files = params.files ?? [];
521
- const results = (await mapLimit(files.length > 8 ? files.slice(0, 8) : files, MAX_SLACK_MEDIA_CONCURRENCY, async (file) => {
430
+ const resolved = await pMap(files.length > 8 ? files.slice(0, 8) : files, async (file) => {
431
+ const preloaded = params.preloadedMedia?.get(file);
432
+ if (preloaded) return preloaded;
522
433
  const eventUrl = file.url_private_download ?? file.url_private;
523
434
  const url = eventUrl ?? await fetchFreshSlackFileUrl({
524
435
  file,
525
436
  client: params.client
526
437
  });
527
- if (!url) return null;
438
+ if (!url) return pMapSkip;
528
439
  const result = await downloadSlackMediaFile({
529
440
  file,
530
441
  url,
@@ -534,12 +445,12 @@ async function resolveSlackMedia(params) {
534
445
  totalTimeoutMs: params.totalTimeoutMs,
535
446
  abortSignal: params.abortSignal
536
447
  }).catch(() => null);
537
- if (result || !eventUrl) return result;
448
+ if (result || !eventUrl) return result ?? pMapSkip;
538
449
  const freshUrl = await fetchFreshSlackFileUrl({
539
450
  file,
540
451
  client: params.client
541
452
  });
542
- if (!freshUrl) return null;
453
+ if (!freshUrl) return pMapSkip;
543
454
  return await downloadSlackMediaFile({
544
455
  file,
545
456
  url: freshUrl,
@@ -548,9 +459,12 @@ async function resolveSlackMedia(params) {
548
459
  readIdleTimeoutMs: params.readIdleTimeoutMs,
549
460
  totalTimeoutMs: params.totalTimeoutMs,
550
461
  abortSignal: params.abortSignal
551
- }).catch(() => null);
552
- })).filter((entry) => Boolean(entry));
553
- return results.length > 0 ? results : null;
462
+ }).catch(() => null) ?? pMapSkip;
463
+ }, {
464
+ concurrency: MAX_SLACK_MEDIA_CONCURRENCY,
465
+ stopOnError: true
466
+ });
467
+ return resolved.length > 0 ? resolved : null;
554
468
  }
555
469
  /** Extracts text and media from forwarded-message attachments. Returns null when empty. */
556
470
  async function resolveSlackAttachmentContent(params) {
@@ -706,7 +620,7 @@ function hasSlackPlatformError(err, code) {
706
620
  async function getClient(opts = {}, mode = "read") {
707
621
  if (opts.client) return opts.client;
708
622
  const token = resolveToken(opts.token, opts.accountId, opts.cfg);
709
- return mode === "write" ? getSlackWriteClient(token) : createSlackWebClient(token);
623
+ return mode === "write" ? getSlackWriteClient(token) : createSlackLookupClient(token);
710
624
  }
711
625
  async function resolveBotUserId(client) {
712
626
  const auth = await client.auth.test();
@@ -775,6 +689,10 @@ async function sendSlackMessage(to, content, opts) {
775
689
  client: opts.client,
776
690
  threadTs: opts.threadTs,
777
691
  replyBroadcast: opts.replyBroadcast,
692
+ ...opts.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
693
+ ...opts.textIsSlackPlainText ? { textIsSlackPlainText: true } : {},
694
+ ...opts.authoredTextPlacement ? { authoredTextPlacement: opts.authoredTextPlacement } : {},
695
+ ...Object.hasOwn(opts, "nativeDataFallbackBaseText") ? { nativeDataFallbackBaseText: opts.nativeDataFallbackBaseText } : {},
778
696
  ...opts.uploadFileName ? { uploadFileName: opts.uploadFileName } : {},
779
697
  ...opts.uploadTitle ? { uploadTitle: opts.uploadTitle } : {},
780
698
  blocks: opts.blocks
@@ -783,12 +701,39 @@ async function sendSlackMessage(to, content, opts) {
783
701
  async function editSlackMessage(channelId, messageId, content, opts = {}) {
784
702
  const client = await getClient(opts, "write");
785
703
  const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
786
- await client.chat.update({
704
+ const editText = buildSlackEditTextPayload(content, blocks);
705
+ const hasNativeData = hasSlackNativeDataBlock(blocks);
706
+ const nativeFallbackText = hasNativeData ? appendSlackNativeDataFallbackText(editText, blocks) : editText;
707
+ if (hasNativeData && nativeFallbackText.length > 4e3) throw new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_LIMIT)}-character edit limit. Send a new message instead.`);
708
+ const update = {
787
709
  channel: channelId,
788
710
  ts: messageId,
789
- text: buildSlackEditTextPayload(content, blocks),
711
+ text: hasNativeData ? truncateSlackText(nativeFallbackText, SLACK_EDIT_TEXT_LIMIT) : nativeFallbackText,
790
712
  ...blocks ? { blocks } : {}
791
- });
713
+ };
714
+ try {
715
+ await client.chat.update(update);
716
+ } catch (error) {
717
+ if (!hasSlackNativeDataBlock(blocks) || !isSlackInvalidBlocksError(error)) throw error;
718
+ logVerbose("slack edit: native data block rejected, retrying with text fallback");
719
+ const survivorText = buildSlackBlocksFallbackText(stripSlackNativeDataBlocks(blocks)) ?? "";
720
+ const authoredEditText = content.trim();
721
+ const fallbackPlan = buildSlackNativeDataDeliveryPlan({
722
+ baseText: authoredEditText && !survivorText.includes(authoredEditText) ? authoredEditText : "",
723
+ blocks: blocks ?? []
724
+ });
725
+ if (fallbackPlan.fallbackMessages.length !== 1) throw new Error("Slack native chart or table edit fallback requires multiple messages. Send a new message instead.", { cause: error });
726
+ const fallback = fallbackPlan.fallbackMessages[0];
727
+ if (!fallback || fallback.text.length > 4e3) throw new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_LIMIT)}-character edit limit. Send a new message instead.`, { cause: error });
728
+ const fallbackText = fallback.blocks ? escapeSlackMrkdwn(fallback.text) : truncateSlackText(appendSlackNativeDataFallbackText(editText, blocks), SLACK_EDIT_TEXT_LIMIT);
729
+ if (fallbackText.length > 4e3) throw new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_LIMIT)}-character edit limit. Send a new message instead.`, { cause: error });
730
+ await client.chat.update({
731
+ channel: channelId,
732
+ ts: messageId,
733
+ text: fallbackText,
734
+ ...fallback.blocks ? { blocks: fallback.blocks } : {}
735
+ });
736
+ }
792
737
  }
793
738
  async function deleteSlackMessage(channelId, messageId, opts = {}) {
794
739
  await (await getClient(opts, "write")).chat.delete({
@@ -952,4 +897,4 @@ async function downloadSlackFile(fileId, opts) {
952
897
  }))?.[0] ?? null;
953
898
  }
954
899
  //#endregion
955
- export { buildSlackEditTextPayload as C, formatSlackFileReference as S, resolveSlackThreadHistory as _, listSlackEmojis as a, resolveSlackBlocksText as b, pinSlackMessage as c, removeOwnSlackReactions as d, removeSlackReaction as f, media_exports as g, unpinSlackMessage as h, getSlackMemberInfo as i, reactSlackMessage as l, sendSlackMessage as m, downloadSlackFile as n, listSlackPins as o, resolveSlackConversationName as p, editSlackMessage as r, listSlackReactions as s, deleteSlackMessage as t, readSlackMessages as u, resolveSlackThreadStarter as v, MAX_SLACK_MEDIA_FILES as x, chooseSlackPrimaryText as y };
900
+ export { buildSlackEditTextPayload as S, resolveSlackThreadHistory as _, listSlackEmojis as a, resolveSlackBlocksText as b, pinSlackMessage as c, removeOwnSlackReactions as d, removeSlackReaction as f, media_exports as g, unpinSlackMessage as h, getSlackMemberInfo as i, reactSlackMessage as l, sendSlackMessage as m, downloadSlackFile as n, listSlackPins as o, resolveSlackConversationName as p, editSlackMessage as r, listSlackReactions as s, deleteSlackMessage as t, readSlackMessages as u, resolveSlackThreadStarter as v, formatSlackFileReference as x, chooseSlackPrimaryText as y };
@@ -1,2 +1,2 @@
1
- import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, h as unpinSlackMessage, i as getSlackMemberInfo, l as reactSlackMessage, m as sendSlackMessage, n as downloadSlackFile, o as listSlackPins, p as resolveSlackConversationName, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-DMpDmKEA.js";
1
+ import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, h as unpinSlackMessage, i as getSlackMemberInfo, l as reactSlackMessage, m as sendSlackMessage, n as downloadSlackFile, o as listSlackPins, p as resolveSlackConversationName, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-BZiuSTIq.js";
2
2
  export { deleteSlackMessage, downloadSlackFile, editSlackMessage, getSlackMemberInfo, listSlackEmojis, listSlackPins, listSlackReactions, pinSlackMessage, reactSlackMessage, readSlackMessages, removeOwnSlackReactions, removeSlackReaction, resolveSlackConversationName, sendSlackMessage, unpinSlackMessage };
package/dist/api.js CHANGED
@@ -1,18 +1,19 @@
1
1
  import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath, t as handleSlackHttpRequest } from "./registry-bbjH7IHX.js";
2
2
  import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, r as mergeSlackAccountConfig, t as listEnabledSlackAccounts, u as resolveSlackReplyToMode } from "./accounts-BOJJiHSr.js";
3
3
  import { t as inspectSlackAccount } from "./account-inspect-Di7ditqZ.js";
4
- import { i as resolveSlackChannelId, n as normalizeSlackMessagingTarget, r as parseSlackTarget, t as looksLikeSlackTargetId } from "./target-parsing-3jYH8LfB.js";
5
- import "./targets-Dll4NJgs.js";
6
- import { a as resolveSlackAutoThreadId, i as resolveSlackChannelType, n as buildSlackThreadingToolContext, r as resetSlackChannelTypeCacheForTest, t as slackPlugin } from "./channel-BjlsaGHn.js";
7
- import { _ as buildSlackPresentationBlocks, d as normalizeAllowListLower, f as normalizeSlackAllowOwnerEntry, g as buildSlackInteractiveBlocks, h as resolveSlackUserAllowed, i as validateSlackBlocksArray, l as allowListMatches, m as resolveSlackAllowListMatch, n as SLACK_MAX_BLOCKS, o as resolveSlackGroupRequireMention, p as normalizeSlackSlug, r as parseSlackBlocksInput, s as resolveSlackGroupToolPolicy, u as normalizeAllowList } from "./reply-blocks-BGQ6zSqM.js";
8
- import { n as extractSlackToolSend, r as listSlackMessageActions } from "./message-tool-api-BgWKyu2r.js";
9
- import { n as isSlackInteractiveRepliesEnabled, r as parseSlackOptionsLine, t as compileSlackInteractiveReplies } from "./interactive-replies-CXpT-vA_.js";
10
- import { a as getSlackWriteClient, c as resolveSlackWebClientOptions, i as createSlackWriteClient, l as resolveSlackWriteClientOptions, n as createSlackTokenCacheKey, o as SLACK_DEFAULT_RETRY_OPTIONS, r as createSlackWebClient, s as SLACK_WRITE_RETRY_OPTIONS, t as clearSlackWriteClientCacheForTest } from "./client-DGxwSL7f.js";
11
- import { t as slackSetupPlugin } from "./channel.setup-Dq6syTNU.js";
12
- import { a as clearSlackThreadParticipationCache, c as recordSlackThreadParticipation, o as hasSlackThreadParticipation } from "./send-DKDXoeoV.js";
13
- import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, h as unpinSlackMessage, i as getSlackMemberInfo, l as reactSlackMessage, m as sendSlackMessage, n as downloadSlackFile, o as listSlackPins, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-DMpDmKEA.js";
14
- import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-BZuS8141.js";
15
- import { t as probeSlack } from "./probe-CuwRDE5j.js";
4
+ import { a as resolveSlackChannelId, i as parseSlackTarget, n as looksLikeSlackTargetId, r as normalizeSlackMessagingTarget } from "./target-parsing-N6lHogYZ.js";
5
+ import "./targets-KmjP2E8s.js";
6
+ import { n as buildSlackThreadingToolContext, r as resolveSlackAutoThreadId, t as slackPlugin } from "./channel-DaIiGUOp.js";
7
+ import { L as buildSlackInteractiveBlocks, Q as validateSlackBlocksArray, R as buildSlackPresentationBlocks, X as SLACK_MAX_BLOCKS, Z as parseSlackBlocksInput, c as normalizeAllowListLower, d as resolveSlackAllowListMatch, f as resolveSlackUserAllowed, l as normalizeSlackAllowOwnerEntry, n as resolveSlackGroupRequireMention, o as allowListMatches, r as resolveSlackGroupToolPolicy, s as normalizeAllowList, u as normalizeSlackSlug } from "./group-policy-85UWiriS.js";
8
+ import { n as extractSlackToolSend, r as listSlackMessageActions } from "./message-tool-api-CA9jZrCY.js";
9
+ import { n as isSlackInteractiveRepliesEnabled, r as parseSlackOptionsLine, t as compileSlackInteractiveReplies } from "./interactive-replies-BilWUdcI.js";
10
+ import { a as createSlackWebClient, c as getSlackWriteClient, d as resolveSlackWebClientOptions, f as resolveSlackWriteClientOptions, i as createSlackTokenCacheKey, l as SLACK_DEFAULT_RETRY_OPTIONS, o as createSlackWriteClient, t as clearSlackWriteClientCacheForTest, u as SLACK_WRITE_RETRY_OPTIONS } from "./client-WIPAS3Yr.js";
11
+ import { n as resetSlackChannelTypeCacheForTest, r as resolveSlackChannelType } from "./channel-type-Cfm6_6n1.js";
12
+ import { t as slackSetupPlugin } from "./channel.setup-C-mLz50O.js";
13
+ import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, h as unpinSlackMessage, i as getSlackMemberInfo, l as reactSlackMessage, m as sendSlackMessage, n as downloadSlackFile, o as listSlackPins, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-BZiuSTIq.js";
14
+ import { a as clearSlackThreadParticipationCache, c as recordSlackThreadParticipation, o as hasSlackThreadParticipation } from "./send-DYp8ca-l.js";
15
+ import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-DRkFujwG.js";
16
+ import { t as probeSlack } from "./probe-CN0ssfLN.js";
16
17
  import { t as collectSlackSecurityAuditFindings } from "./security-audit-CikQhBUY.js";
17
- import { n as resolveSlackRuntimeGroupPolicy } from "./provider-C1-DFSpw.js";
18
+ import { n as resolveSlackRuntimeGroupPolicy } from "./provider-CmeoUiIM.js";
18
19
  export { SLACK_DEFAULT_RETRY_OPTIONS, SLACK_MAX_BLOCKS, SLACK_WRITE_RETRY_OPTIONS, resetSlackChannelTypeCacheForTest as __resetSlackChannelTypeCacheForTest, resetSlackChannelTypeCacheForTest, allowListMatches, buildSlackInteractiveBlocks, buildSlackPresentationBlocks, buildSlackThreadingToolContext, clearSlackThreadParticipationCache, clearSlackWriteClientCacheForTest, collectSlackSecurityAuditFindings, compileSlackInteractiveReplies, createSlackTokenCacheKey, createSlackWebClient, createSlackWriteClient, deleteSlackMessage, downloadSlackFile, editSlackMessage, extractSlackToolSend, getSlackMemberInfo, getSlackWriteClient, handleSlackHttpRequest, hasSlackThreadParticipation, inspectSlackAccount, isSlackInteractiveRepliesEnabled, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig, listSlackEmojis, listSlackMessageActions, listSlackPins, listSlackReactions, looksLikeSlackTargetId, mergeSlackAccountConfig, normalizeAllowList, normalizeAllowListLower, normalizeSlackAllowOwnerEntry, normalizeSlackMessagingTarget, normalizeSlackSlug, normalizeSlackWebhookPath, parseSlackBlocksInput, parseSlackOptionsLine, parseSlackTarget, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, recordSlackThreadParticipation, registerSlackHttpHandler, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAllowListMatch, resolveSlackAutoThreadId, resolveSlackChannelId, resolveSlackChannelType, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackReplyToMode, resolveSlackRuntimeGroupPolicy, resolveSlackUserAllowed, resolveSlackWebClientOptions, resolveSlackWriteClientOptions, sendSlackMessage, slackPlugin, slackSetupPlugin, unpinSlackMessage, validateSlackBlocksArray };
@@ -1,5 +1,5 @@
1
- import { D as isSlackAnyNativeApprovalClientEnabled, H as normalizeSlackApproverId, P as shouldHandleSlackNativeApprovalRequest, b as truncateSlackText, j as resolveSlackApprovalKind, t as resolveSlackReplyBlocks } from "./reply-blocks-BGQ6zSqM.js";
2
- import { r as sendMessageSlack } from "./send-DKDXoeoV.js";
1
+ import { B as truncateSlackText, et as isSlackAnyNativeApprovalClientEnabled, g as resolveSlackReplyBlocks, mt as normalizeSlackApproverId, ot as shouldHandleSlackNativeApprovalRequest } from "./group-policy-85UWiriS.js";
2
+ import { r as sendMessageSlack } from "./send-DYp8ca-l.js";
3
3
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
5
5
  import { buildApprovalPresentationFromActionDescriptors } from "openclaw/plugin-sdk/approval-reply-runtime";
@@ -291,7 +291,7 @@ const slackApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
291
291
  return shouldHandleSlackNativeApprovalRequest({
292
292
  cfg: params.cfg,
293
293
  accountId: resolved.accountId,
294
- approvalKind: resolveSlackApprovalKind(params.request),
294
+ approvalKind: params.approvalKind,
295
295
  request: params.request
296
296
  });
297
297
  }