@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
@@ -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 buildSlackCompleteBlocksFallbackText, C as hasSlackNativeDataBlock, K as escapeSlackMrkdwn, N as SLACK_EDIT_TEXT_LIMIT, T as stripSlackNativeDataBlocks, Z as validateSlackBlocksArray, b as appendSlackNativeDataPlainTextFallback, j as renderSlackBlockFallbackText, k as buildSlackBlocksFallbackText, w as isSlackInvalidBlocksError, y as appendSlackNativeDataFallbackText, z as truncateSlackText } from "./group-policy-C-b2ZnSl.js";
4
+ import { n as createSlackLookupClient, s as getSlackWriteClient } from "./client-D2F6m8CP.js";
5
+ import { l as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack } from "./send-NEfJ0GvM.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
@@ -38,107 +44,37 @@ function formatSlackFileReferenceList(files) {
38
44
  const MAX_SLACK_MEDIA_FILES = 8;
39
45
  //#endregion
40
46
  //#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
- }
47
+ function readSlackBlockType(block) {
48
+ return block && typeof block === "object" && !Array.isArray(block) ? block.type : void 0;
123
49
  }
124
50
  function resolveSlackBlocksText(blocks) {
125
51
  if (!blocks?.length) return;
126
52
  const parts = [];
127
53
  let hasRichText = false;
54
+ let hasNativeData = false;
128
55
  for (const block of blocks) {
129
- if (block && typeof block === "object" && block.type === "rich_text") hasRichText = true;
130
- const text = readSlackBlockText(block);
56
+ const blockType = readSlackBlockType(block);
57
+ hasRichText ||= blockType === "rich_text";
58
+ hasNativeData ||= blockType === "data_visualization" || blockType === "data_table";
59
+ const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
131
60
  if (text) parts.push(text);
132
61
  }
133
62
  return parts.length > 0 ? {
134
63
  text: parts.join("\n"),
135
- hasRichText
64
+ hasRichText,
65
+ hasNativeData
136
66
  } : void 0;
137
67
  }
138
68
  function chooseSlackPrimaryText(params) {
139
69
  const { messageText, blocksText } = params;
140
70
  if (!blocksText) return messageText;
141
71
  if (!messageText) return blocksText.text;
72
+ if (blocksText.hasNativeData) {
73
+ const comparableMessageText = messageText.replace(/\s+/g, " ").trim();
74
+ const comparableBlocksText = blocksText.text.replace(/\s+/g, " ").trim();
75
+ if (comparableMessageText.includes(comparableBlocksText)) return messageText;
76
+ return comparableBlocksText.startsWith(comparableMessageText) ? blocksText.text : `${messageText}\n${blocksText.text}`;
77
+ }
142
78
  if (blocksText.hasRichText && blocksText.text.length > messageText.length) return blocksText.text;
143
79
  return blocksText.text.length > messageText.length && blocksText.text.startsWith(messageText) ? blocksText.text : messageText;
144
80
  }
@@ -184,11 +120,19 @@ function resolveSlackAttachmentFallbackText(attachments) {
184
120
  return parts.length > 0 ? parts.join("\n") : void 0;
185
121
  }
186
122
  function resolveSlackMessageText(message) {
187
- return normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments) ?? resolveSlackBlocksFallbackText(message.blocks);
123
+ return chooseSlackPrimaryText({
124
+ messageText: normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments),
125
+ blocksText: resolveSlackBlocksText(message.blocks)
126
+ });
188
127
  }
189
128
  async function resolveSlackThreadStarter(params) {
190
129
  evictThreadStarterCache();
191
- const cacheKey = `${params.channelId}:${params.threadTs}`;
130
+ const cacheKey = params.workspaceScope ? JSON.stringify([
131
+ params.workspaceScope.accountId,
132
+ params.workspaceScope.teamId,
133
+ params.channelId,
134
+ params.threadTs
135
+ ]) : `${params.channelId}:${params.threadTs}`;
192
136
  const cached = THREAD_STARTER_CACHE.get(cacheKey);
193
137
  if (cached) {
194
138
  const now = asDateTimestampMs(Date.now());
@@ -351,30 +295,14 @@ const SLACK_MEDIA_SSRF_POLICY = {
351
295
  };
352
296
  const SLACK_MEDIA_READ_IDLE_TIMEOUT_MS = 6e4;
353
297
  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
298
  async function saveSlackMedia(params) {
372
299
  const timeoutAbortController = params.totalTimeoutMs ? new AbortController() : void 0;
373
- const signal = mergeAbortSignals([
300
+ const abortSignals = [
374
301
  params.abortSignal,
375
302
  params.options.requestInit?.signal ?? void 0,
376
303
  timeoutAbortController?.signal
377
- ]);
304
+ ].filter((signal) => Boolean(signal));
305
+ const signal = abortSignals.length > 1 ? AbortSignal.any(abortSignals) : abortSignals[0];
378
306
  let timedOut = false;
379
307
  let timeoutHandle = null;
380
308
  const savePromise = saveRemoteMedia({
@@ -497,34 +425,21 @@ function resolveForwardedAttachmentImageUrl(attachment) {
497
425
  return null;
498
426
  }
499
427
  }
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
428
  /**
516
429
  * Downloads all files attached to a Slack message and returns them as an array.
517
430
  * Returns `null` when no files could be downloaded.
518
431
  */
519
432
  async function resolveSlackMedia(params) {
520
433
  const files = params.files ?? [];
521
- const results = (await mapLimit(files.length > 8 ? files.slice(0, 8) : files, MAX_SLACK_MEDIA_CONCURRENCY, async (file) => {
434
+ const resolved = await pMap(files.length > 8 ? files.slice(0, 8) : files, async (file) => {
435
+ const preloaded = params.preloadedMedia?.get(file);
436
+ if (preloaded) return preloaded;
522
437
  const eventUrl = file.url_private_download ?? file.url_private;
523
438
  const url = eventUrl ?? await fetchFreshSlackFileUrl({
524
439
  file,
525
440
  client: params.client
526
441
  });
527
- if (!url) return null;
442
+ if (!url) return pMapSkip;
528
443
  const result = await downloadSlackMediaFile({
529
444
  file,
530
445
  url,
@@ -534,12 +449,12 @@ async function resolveSlackMedia(params) {
534
449
  totalTimeoutMs: params.totalTimeoutMs,
535
450
  abortSignal: params.abortSignal
536
451
  }).catch(() => null);
537
- if (result || !eventUrl) return result;
452
+ if (result || !eventUrl) return result ?? pMapSkip;
538
453
  const freshUrl = await fetchFreshSlackFileUrl({
539
454
  file,
540
455
  client: params.client
541
456
  });
542
- if (!freshUrl) return null;
457
+ if (!freshUrl) return pMapSkip;
543
458
  return await downloadSlackMediaFile({
544
459
  file,
545
460
  url: freshUrl,
@@ -548,9 +463,12 @@ async function resolveSlackMedia(params) {
548
463
  readIdleTimeoutMs: params.readIdleTimeoutMs,
549
464
  totalTimeoutMs: params.totalTimeoutMs,
550
465
  abortSignal: params.abortSignal
551
- }).catch(() => null);
552
- })).filter((entry) => Boolean(entry));
553
- return results.length > 0 ? results : null;
466
+ }).catch(() => null) ?? pMapSkip;
467
+ }, {
468
+ concurrency: MAX_SLACK_MEDIA_CONCURRENCY,
469
+ stopOnError: true
470
+ });
471
+ return resolved.length > 0 ? resolved : null;
554
472
  }
555
473
  /** Extracts text and media from forwarded-message attachments. Returns null when empty. */
556
474
  async function resolveSlackAttachmentContent(params) {
@@ -706,7 +624,7 @@ function hasSlackPlatformError(err, code) {
706
624
  async function getClient(opts = {}, mode = "read") {
707
625
  if (opts.client) return opts.client;
708
626
  const token = resolveToken(opts.token, opts.accountId, opts.cfg);
709
- return mode === "write" ? getSlackWriteClient(token) : createSlackWebClient(token);
627
+ return mode === "write" ? getSlackWriteClient(token) : createSlackLookupClient(token);
710
628
  }
711
629
  async function resolveBotUserId(client) {
712
630
  const auth = await client.auth.test();
@@ -775,6 +693,10 @@ async function sendSlackMessage(to, content, opts) {
775
693
  client: opts.client,
776
694
  threadTs: opts.threadTs,
777
695
  replyBroadcast: opts.replyBroadcast,
696
+ ...opts.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
697
+ ...opts.textIsSlackPlainText ? { textIsSlackPlainText: true } : {},
698
+ ...opts.authoredTextPlacement ? { authoredTextPlacement: opts.authoredTextPlacement } : {},
699
+ ...Object.hasOwn(opts, "nativeDataFallbackBaseText") ? { nativeDataFallbackBaseText: opts.nativeDataFallbackBaseText } : {},
778
700
  ...opts.uploadFileName ? { uploadFileName: opts.uploadFileName } : {},
779
701
  ...opts.uploadTitle ? { uploadTitle: opts.uploadTitle } : {},
780
702
  blocks: opts.blocks
@@ -783,12 +705,39 @@ async function sendSlackMessage(to, content, opts) {
783
705
  async function editSlackMessage(channelId, messageId, content, opts = {}) {
784
706
  const client = await getClient(opts, "write");
785
707
  const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
786
- await client.chat.update({
708
+ const editText = buildSlackEditTextPayload(content, blocks);
709
+ const hasNativeData = hasSlackNativeDataBlock(blocks);
710
+ const nativeFallbackText = hasNativeData ? appendSlackNativeDataFallbackText(editText, blocks) : editText;
711
+ 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.`);
712
+ const update = {
787
713
  channel: channelId,
788
714
  ts: messageId,
789
- text: buildSlackEditTextPayload(content, blocks),
715
+ text: hasNativeData ? truncateSlackText(nativeFallbackText, SLACK_EDIT_TEXT_LIMIT) : nativeFallbackText,
790
716
  ...blocks ? { blocks } : {}
791
- });
717
+ };
718
+ try {
719
+ await client.chat.update(update);
720
+ } catch (error) {
721
+ if (!hasSlackNativeDataBlock(blocks) || !isSlackInvalidBlocksError(error)) throw error;
722
+ logVerbose("slack edit: native data block rejected, retrying with text fallback");
723
+ const survivorText = buildSlackBlocksFallbackText(stripSlackNativeDataBlocks(blocks)) ?? "";
724
+ const authoredEditText = content.trim();
725
+ const fallbackPlan = buildSlackNativeDataDeliveryPlan({
726
+ baseText: authoredEditText && !survivorText.includes(authoredEditText) ? authoredEditText : "",
727
+ blocks: blocks ?? []
728
+ });
729
+ 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 });
730
+ const fallback = fallbackPlan.fallbackMessages[0];
731
+ 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 });
732
+ const fallbackText = fallback.blocks ? escapeSlackMrkdwn(fallback.text) : truncateSlackText(appendSlackNativeDataFallbackText(editText, blocks), SLACK_EDIT_TEXT_LIMIT);
733
+ 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 });
734
+ await client.chat.update({
735
+ channel: channelId,
736
+ ts: messageId,
737
+ text: fallbackText,
738
+ ...fallback.blocks ? { blocks: fallback.blocks } : {}
739
+ });
740
+ }
792
741
  }
793
742
  async function deleteSlackMessage(channelId, messageId, opts = {}) {
794
743
  await (await getClient(opts, "write")).chat.delete({
@@ -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-DkTcWmpT.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-B0_j6C6z.js";
7
+ import { I as buildSlackInteractiveBlocks, L as buildSlackPresentationBlocks, X as parseSlackBlocksInput, Y as SLACK_MAX_BLOCKS, Z as validateSlackBlocksArray, a as allowListMatches, c as normalizeSlackAllowOwnerEntry, d as resolveSlackUserAllowed, l as normalizeSlackSlug, n as resolveSlackGroupToolPolicy, o as normalizeAllowList, s as normalizeAllowListLower, t as resolveSlackGroupRequireMention, u as resolveSlackAllowListMatch } from "./group-policy-C-b2ZnSl.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 createSlackWriteClient, c as SLACK_DEFAULT_RETRY_OPTIONS, d as resolveSlackWriteClientOptions, i as createSlackWebClient, l as SLACK_WRITE_RETRY_OPTIONS, r as createSlackTokenCacheKey, s as getSlackWriteClient, t as clearSlackWriteClientCacheForTest, u as resolveSlackWebClientOptions } from "./client-D2F6m8CP.js";
11
+ import { n as resetSlackChannelTypeCacheForTest, r as resolveSlackChannelType } from "./channel-type-BpeTezY4.js";
12
+ import { t as slackSetupPlugin } from "./channel.setup-BQFut21T.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-DkTcWmpT.js";
14
+ import { a as clearSlackThreadParticipationCache, c as recordSlackThreadParticipation, o as hasSlackThreadParticipation } from "./send-NEfJ0GvM.js";
15
+ import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-DRkFujwG.js";
16
+ import { t as probeSlack } from "./probe-CfALk0l4.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-Ds-y-imP.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 { $ as isSlackAnyNativeApprovalClientEnabled, at as shouldHandleSlackNativeApprovalRequest, h as resolveSlackReplyBlocks, pt as normalizeSlackApproverId, z as truncateSlackText } from "./group-policy-C-b2ZnSl.js";
2
+ import { r as sendMessageSlack } from "./send-NEfJ0GvM.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
  }