@openclaw/slack 2026.8.1-beta.2 → 2026.8.1-beta.3

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 (54) hide show
  1. package/dist/{account-inspect-Drw2gAiN.js → account-inspect-YJvFBbCR.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-CK4AVI2_.js → accounts-BlzxuYle.js} +5 -1
  4. package/dist/{accounts.runtime-Cb7QwWBz.js → accounts.runtime-CbabBL8x.js} +1 -1
  5. package/dist/{action-runtime-BkGe7ny_.js → action-runtime-D6jg2CQd.js} +64 -68
  6. package/dist/action-runtime.runtime-JtoOK9l5.js +2 -0
  7. package/dist/{actions-BTDXwwE3.js → actions-DFk0ANVB.js} +52 -212
  8. package/dist/{actions.runtime-DLFyUkvg.js → actions.runtime-CYLsYRai.js} +1 -1
  9. package/dist/api.js +14 -14
  10. package/dist/{approval-handler.runtime-CJaNzAq2.js → approval-handler.runtime-BNvAoKdK.js} +4 -2
  11. package/dist/{channel-D_tovcUL.js → channel-CA5w7qDF.js} +78 -39
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel-type-B9MSdoGN.js → channel-type-CZWv55Wu.js} +3 -7
  15. package/dist/{channel.setup-Bch9dYmA.js → channel.setup-CpyYsEXH.js} +4 -4
  16. package/dist/{config-schema-xto5jFIx.js → config-schema-CN3XZRX5.js} +23 -7
  17. package/dist/conversation-binding-route-DFVLUdYF.js +115 -0
  18. package/dist/{directory-config-CNBz8lJa.js → directory-config-BGYyuzWh.js} +1 -1
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-CFKUtW9E.js → directory-live-DjUJQLbq.js} +2 -2
  21. package/dist/{group-policy-c4RP9bjc.js → group-policy-DyfB_ZIE.js} +38 -24
  22. package/dist/{message-tool-api-BykQB4AU.js → message-tool-api-CqMr5Rmc.js} +2 -2
  23. package/dist/message-tool-api.js +1 -1
  24. package/dist/{monitor-1nF1NtqT.js → monitor-Chrecrb9.js} +3 -3
  25. package/dist/{outbound-adapter-S81tsswN.js → outbound-adapter-DuRqAQXK.js} +18 -8
  26. package/dist/{pipeline.runtime-BvYsM5JO.js → pipeline.runtime-Bbfd5VFW.js} +376 -324
  27. package/dist/{policy-TapwbeaT.js → policy-BKXSxrIS.js} +1 -1
  28. package/dist/{probe-HoEg_WxB.js → probe-BVA65leh.js} +1 -1
  29. package/dist/{provider-CDNvBXUi.js → provider-CUUiwsg2.js} +65 -44
  30. package/dist/{relay-source-C9leF11u.js → relay-source-mhpMMRG-.js} +1 -1
  31. package/dist/{replies-CeOfv82I.js → replies-SnWyXcsL.js} +36 -25
  32. package/dist/{resolve-channels-CNPrxaXY.js → resolve-channels-BSpqC8jU.js} +1 -1
  33. package/dist/{resolve-users-Dzomuwnr.js → resolve-users-Dvz9pDe0.js} +1 -1
  34. package/dist/{runtime-api-Cj9nxBNv.js → runtime-api-DBi7xc_g.js} +2 -2
  35. package/dist/runtime-api.js +11 -11
  36. package/dist/{scopes-cYXKkrRD.js → scopes-BSk4GZvZ.js} +1 -1
  37. package/dist/security-contract-api.js +1 -1
  38. package/dist/{send-Nor0iBwY.js → send-CtnOxKCc.js} +58 -78
  39. package/dist/{send.runtime-BmgNe6S9.js → send.runtime-kYctMHSd.js} +1 -1
  40. package/dist/setup-plugin-api.js +1 -1
  41. package/dist/{setup-surface-CbX1-Knh.js → setup-surface-BPFfp6So.js} +6 -6
  42. package/dist/{shared-zdT5AMp-.js → shared-DJBaslN7.js} +13 -7
  43. package/dist/{block-text-YtiNkqmx.js → slack-client-kind-BXyOOICI.js} +17 -2
  44. package/dist/{slash-dispatch.runtime-Bnr9GR1S.js → slash-dispatch.runtime-Cf2FTrnf.js} +2 -2
  45. package/openclaw.plugin.json +43 -1
  46. package/package.json +4 -6
  47. package/dist/account-reply-mode-DrUXogvO.js +0 -14
  48. package/dist/action-runtime.runtime-D9I6uc0Q.js +0 -2
  49. package/node_modules/p-map/index.d.ts +0 -155
  50. package/node_modules/p-map/index.js +0 -285
  51. package/node_modules/p-map/license +0 -9
  52. package/node_modules/p-map/package.json +0 -57
  53. package/node_modules/p-map/readme.md +0 -190
  54. package/dist/{security-audit-DR097212.js → security-audit-B_yKr7MW.js} +1 -1
@@ -1,50 +1,41 @@
1
- import { a as resolveSlackAccount, l as resolveSlackOperationToken } from "./accounts-CK4AVI2_.js";
1
+ import { a as resolveSlackAccount, l as resolveSlackOperationToken } from "./accounts-BlzxuYle.js";
2
2
  import { a as parseSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-BnMD2ZqZ.js";
3
- import { A as chunkSlackMrkdwnText, B as SLACK_TEXT_LIMIT, C as buildSlackNativeDataAccessibilityText, E as isSlackInvalidBlocksError, F as renderSlackBlockFallbackText, G as truncateSlackText, K as truncateSlackTextByUtf8Bytes, L as SLACK_EDIT_TEXT_MAX_BYTES, P as buildSlackCompleteBlocksFallbackText, R as SLACK_MESSAGE_TEXT_HARD_LIMIT, S as appendSlackNativeDataPlainTextFallback, T as hasSlackNativeDataBlock, j as markdownToSlackMrkdwnChunks, k as stripSlackNativeDataBlocks, p as assertSlackDetachedTargetAllowed, q as SLACK_QUESTION_FINALIZATION_BLOCKS, tt as resolveSlackQuestionActionIds, ut as validateSlackBlocksArray, w as createSlackNativeDataBaseTextConsumer, z as SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT } from "./group-policy-c4RP9bjc.js";
3
+ import { B as SLACK_EDIT_TEXT_MAX_BYTES, D as createSlackNativeDataBaseTextConsumer, E as buildSlackNativeDataAccessibilityText, H as SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT, J as truncateSlackText, L as buildSlackCompleteBlocksFallbackText, M as stripSlackNativeDataBlocks, N as chunkSlackMrkdwnText, O as hasSlackNativeDataBlock, P as markdownToSlackMrkdwnChunks, R as renderSlackBlockFallbackText, T as appendSlackNativeDataPlainTextFallback, U as SLACK_TEXT_LIMIT, V as SLACK_MESSAGE_TEXT_HARD_LIMIT, X as SLACK_QUESTION_FINALIZATION_BLOCKS, Y as truncateSlackTextByUtf8Bytes, g as assertSlackDetachedTargetAllowed, it as resolveSlackQuestionActionIds, k as isSlackInvalidBlocksError, mt as validateSlackBlocksArray } from "./group-policy-DyfB_ZIE.js";
4
4
  import { n as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-DUGhaYKq.js";
5
- import { a as createSlackReadClient, d as getSlackWriteClient, r as formatSlackError, s as createSlackTokenCacheKey } from "./probe-HoEg_WxB.js";
5
+ import { a as createSlackReadClient, d as getSlackWriteClient, r as formatSlackError, s as createSlackTokenCacheKey } from "./probe-BVA65leh.js";
6
6
  import { t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.js";
7
- import { i as loadOutboundMediaFromUrl } from "./runtime-api-Cj9nxBNv.js";
7
+ import { i as loadOutboundMediaFromUrl } from "./runtime-api-DBi7xc_g.js";
8
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
10
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
10
+ import { logVerbose, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
11
+ import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
11
12
  import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
12
- import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
13
+ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
13
14
  import { createHash, createHmac } from "node:crypto";
14
15
  import { withTrustedEnvProxyGuardedFetchMode } from "openclaw/plugin-sdk/fetch-runtime";
15
16
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
16
17
  import { PlatformMessageNotDispatchedError, extractErrorCode, readErrorName } from "openclaw/plugin-sdk/error-runtime";
17
18
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
18
19
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
19
- import { chunkMarkdownTextWithMode, isSilentReplyText, resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
20
+ import { chunkMarkdownTextWithMode, resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
20
21
  import { resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
21
22
  import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
22
23
  import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
23
24
  import { extensionForMime } from "openclaw/plugin-sdk/media-mime";
25
+ import { retryAsync } from "openclaw/plugin-sdk/retry-runtime";
24
26
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
25
27
  import { createPersistentDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
26
28
  import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
27
29
  //#region extensions/slack/src/native-data-fallback.ts
28
30
  const SLACK_SECTION_PLAIN_TEXT_MAX = 3e3;
29
31
  const SLACK_EMPTY_BLOCK_FALLBACK = "Shared a Block Kit message";
30
- function sliceSlackTextChunk(text, start, limit) {
31
- return sliceUtf16Safe(text, start, Math.min(text.length, start + limit)) || Array.from(text.slice(start))[0] || "";
32
- }
33
32
  function chunkSlackTextAtHardLimit(text, limit = SLACK_MESSAGE_TEXT_HARD_LIMIT) {
34
- const effectiveLimit = Math.max(1, Math.floor(limit));
35
- const chunks = [];
36
- let offset = 0;
37
- while (offset < text.length) {
38
- const chunk = sliceSlackTextChunk(text, offset, effectiveLimit);
39
- if (!chunk) throw new Error("Slack plain-text fallback chunking made no progress.");
40
- chunks.push(chunk);
41
- offset += chunk.length;
42
- }
43
- return chunks;
33
+ if (!text) return [];
34
+ return chunkTextForOutbound(text, Math.max(1, Math.floor(limit)), { preserveWhitespace: true });
44
35
  }
45
36
  function fitsSlackTextLimit(text, limit) {
46
37
  if (text.length <= limit) return true;
47
- return sliceSlackTextChunk(text, 0, limit).length === text.length;
38
+ return truncateUtf16Safe(text, limit).length === text.length;
48
39
  }
49
40
  function buildPlainTextBlocks(text, textLimit) {
50
41
  return chunkSlackTextAtHardLimit(text, Math.min(textLimit, SLACK_SECTION_PLAIN_TEXT_MAX)).map((chunk, index) => {
@@ -154,6 +145,7 @@ function hasCustomIdentity$1(identity) {
154
145
  async function postSlackMessageWithIdentityFallback(params) {
155
146
  const { basePayload, identity, post } = params;
156
147
  try {
148
+ if (!identity) return await post(basePayload);
157
149
  if (identity?.iconUrl) return await post({
158
150
  ...basePayload,
159
151
  ...identity.username ? { username: identity.username } : {},
@@ -262,11 +254,6 @@ function hasSlackDnsRequestSignal(err) {
262
254
  }
263
255
  return false;
264
256
  }
265
- function delaySlackDnsRetry(attempt) {
266
- return new Promise((resolve) => {
267
- setTimeout(resolve, SLACK_DNS_RETRY_BASE_DELAY_MS * Math.max(1, attempt));
268
- });
269
- }
270
257
  function resolveSlackUploadTimeoutLogUrl(url) {
271
258
  try {
272
259
  return new URL(url).origin;
@@ -340,14 +327,22 @@ function resolveSlackUploadTransportPolicy(params) {
340
327
  };
341
328
  }
342
329
  async function withSlackDnsRequestRetry(operation, fn) {
343
- for (const attempt of Array.from({ length: 3 }, (_, index) => index)) try {
344
- return await fn();
345
- } catch (err) {
346
- if (attempt >= SLACK_DNS_RETRY_ATTEMPTS || !hasSlackDnsRequestSignal(err)) throw err;
347
- logVerbose(`slack send: retrying ${operation} after transient DNS request error (${attempt + 1}/${SLACK_DNS_RETRY_ATTEMPTS})`);
348
- await delaySlackDnsRetry(attempt + 1);
349
- }
350
- throw new Error("unreachable Slack DNS retry loop exit");
330
+ return await retryAsync(fn, {
331
+ attempts: 3,
332
+ minDelayMs: 0,
333
+ shouldRetry: hasSlackDnsRequestSignal,
334
+ delayMs: ({ attempt }) => SLACK_DNS_RETRY_BASE_DELAY_MS * Math.max(1, attempt),
335
+ onRetry: ({ attempt }) => {
336
+ logVerbose(`slack send: retrying ${operation} after transient DNS request error (${attempt}/${SLACK_DNS_RETRY_ATTEMPTS})`);
337
+ },
338
+ sleep: (delayMs) => sleepWithAbort(delayMs)
339
+ });
340
+ }
341
+ function requireSlackPostMessageTimestamp(response) {
342
+ if (response.ok === false) throw new Error(`Slack chat.postMessage failed: ${formatSlackError(response.error, "unknown error")}`);
343
+ const timestamp = response.ts?.trim();
344
+ if (!timestamp) throw new Error("Slack chat.postMessage returned no message timestamp");
345
+ return timestamp;
351
346
  }
352
347
  async function postSlackMessageBestEffort(params) {
353
348
  const basePayload = buildSlackPostMessagePayload(params);
@@ -356,11 +351,19 @@ async function postSlackMessageBestEffort(params) {
356
351
  response: await withSlackDnsRequestRetry("chat.postMessage", () => postChatMessage(payload)),
357
352
  identity
358
353
  });
359
- return await postSlackMessageWithIdentityFallback({
354
+ const posted = await postSlackMessageWithIdentityFallback({
360
355
  basePayload,
361
356
  identity: params.identity,
362
357
  post
363
358
  });
359
+ const timestamp = requireSlackPostMessageTimestamp(posted.response);
360
+ return {
361
+ ...posted,
362
+ response: {
363
+ ...posted.response,
364
+ ts: timestamp
365
+ }
366
+ };
364
367
  }
365
368
  async function uploadSlackFile(params) {
366
369
  const { buffer, contentType, fileName } = await loadOutboundMediaFromUrl(params.mediaUrl, {
@@ -605,7 +608,7 @@ async function updateMessageSlack(params) {
605
608
  }
606
609
  function createSlackSendReceipt(params) {
607
610
  return createMessageReceiptFromOutboundResults({
608
- results: params.platformMessageIds.map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown" && messageId !== "suppressed").map((messageId) => {
611
+ results: params.platformMessageIds.map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown").map((messageId) => {
609
612
  const result = {
610
613
  channel: "slack",
611
614
  messageId
@@ -658,7 +661,6 @@ function resolveSlackDelivery(params) {
658
661
  credential: SLACK_ENTERPRISE_LISTENER_QUEUE_CREDENTIAL,
659
662
  identity: normalizeSlackSendIdentity(params.opts.identity),
660
663
  recipient: params.recipient,
661
- requireMessageTimestamp: true,
662
664
  teamId: params.eventScope.teamId,
663
665
  unfurl: { unfurlMedia: params.account.config.unfurlMedia },
664
666
  ...params.eventScope.uploadCompletionClient ? { upload: Object.freeze({
@@ -681,7 +683,6 @@ function resolveSlackDelivery(params) {
681
683
  explicit: params.opts.identity
682
684
  }),
683
685
  recipient: params.recipient,
684
- requireMessageTimestamp: false,
685
686
  teamId: params.recipient.teamId,
686
687
  unfurl: params.recipient.teamId ? { unfurlMedia: params.account.config.unfurlMedia } : {
687
688
  unfurlLinks: params.account.config.unfurlLinks,
@@ -689,10 +690,6 @@ function resolveSlackDelivery(params) {
689
690
  }
690
691
  });
691
692
  }
692
- function assertSlackPostMessageResponse(response, required) {
693
- if (!required || response.ok && response.ts) return;
694
- throw new Error(response.ok ? "Slack chat.postMessage returned no message timestamp" : `Slack chat.postMessage failed: ${formatSlackError(response.error, "unknown error")}`);
695
- }
696
693
  function resolveSlackTextChunkLimit(params) {
697
694
  const configuredLimit = params.textLimit ?? resolveTextChunkLimit(params.cfg, "slack", params.accountId, { fallbackLimit: 8e3 });
698
695
  return Math.min(configuredLimit, SLACK_TEXT_LIMIT);
@@ -1057,17 +1054,6 @@ async function sendMessageSlack(to, message, opts) {
1057
1054
  const eventScope = resolveSlackSendEventScope({ opts });
1058
1055
  const recipient = eventScope ? parseEnterpriseEventRecipient(to) : parseRecipient(to);
1059
1056
  if (!eventScope) assertSlackDetachedTargetAllowed(account.accountId, recipient.teamId);
1060
- if (isSilentReplyText(normalizedMessage) && !opts.mediaUrl && !opts.blocks) {
1061
- logVerbose("slack send: suppressed NO_REPLY token before API call");
1062
- return {
1063
- messageId: "suppressed",
1064
- channelId: "",
1065
- receipt: createSlackSendReceipt({
1066
- platformMessageIds: [],
1067
- kind: "unknown"
1068
- })
1069
- };
1070
- }
1071
1057
  const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
1072
1058
  if (!normalizedMessage && !opts.mediaUrl && !blocks) throw new Error("Slack send requires text, blocks, or media");
1073
1059
  const queuedOpts = Object.freeze({ ...opts });
@@ -1185,8 +1171,7 @@ async function sendMessageSlackQueuedInner(params) {
1185
1171
  ...usesOrderedBlockAccessibility ? { mrkdwn: false } : {},
1186
1172
  unfurl
1187
1173
  });
1188
- assertSlackPostMessageResponse(response, delivery.requireMessageTimestamp);
1189
- const messageId = response.ts ?? "unknown";
1174
+ const messageId = response.ts;
1190
1175
  deliveredChannelId = resolvePostedMessageChannelId(response, channelId);
1191
1176
  const deliveredThreadTs = resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs);
1192
1177
  return await reportDelivery({
@@ -1231,12 +1216,10 @@ async function sendMessageSlackQueuedInner(params) {
1231
1216
  unfurl
1232
1217
  });
1233
1218
  const response = posted.response;
1234
- assertSlackPostMessageResponse(response, delivery.requireMessageTimestamp);
1235
1219
  sendIdentity = posted.identity;
1236
- lastMessageId = response.ts ?? lastMessageId;
1220
+ lastMessageId = response.ts;
1237
1221
  deliveredChannelId = resolvePostedMessageChannelId(response, deliveredChannelId);
1238
1222
  canonicalDeliveredThreadTs ??= resolvePostedMessageThreadTs(response);
1239
- if (!response.ts) continue;
1240
1223
  sentMessageIds.push(response.ts);
1241
1224
  const deliveredThreadTs = resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs);
1242
1225
  const fallbackDelivery = await reportDelivery({
@@ -1252,7 +1235,7 @@ async function sendMessageSlackQueuedInner(params) {
1252
1235
  }, fallback.blocks);
1253
1236
  if (fallbackDelivery.meta?.slackQuestionActionIds.length) questionDelivery = fallbackDelivery;
1254
1237
  }
1255
- const messageId = lastMessageId || "unknown";
1238
+ const messageId = lastMessageId;
1256
1239
  const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
1257
1240
  return {
1258
1241
  messageId,
@@ -1263,7 +1246,7 @@ async function sendMessageSlackQueuedInner(params) {
1263
1246
  slackQuestionMessageId: questionDelivery.messageId
1264
1247
  } } : {},
1265
1248
  receipt: createSlackSendReceipt({
1266
- platformMessageIds: sentMessageIds.length ? sentMessageIds : [messageId],
1249
+ platformMessageIds: sentMessageIds,
1267
1250
  channelId: deliveredChannelId,
1268
1251
  kind: fallbackMessages.some((message) => message.blocks) ? "card" : "text",
1269
1252
  threadTs: deliveredThreadTs
@@ -1337,34 +1320,31 @@ async function sendMessageSlackQueuedInner(params) {
1337
1320
  unfurl
1338
1321
  });
1339
1322
  const response = posted.response;
1340
- assertSlackPostMessageResponse(response, delivery.requireMessageTimestamp);
1341
1323
  sendIdentity = posted.identity;
1342
- lastMessageId = response.ts ?? lastMessageId;
1324
+ lastMessageId = response.ts;
1343
1325
  deliveredChannelId = resolvePostedMessageChannelId(response, deliveredChannelId);
1344
1326
  canonicalDeliveredThreadTs ??= resolvePostedMessageThreadTs(response);
1345
- if (response.ts) {
1346
- sentMessageIds.push(response.ts);
1347
- await reportDelivery({
1348
- messageId: response.ts,
1327
+ sentMessageIds.push(response.ts);
1328
+ await reportDelivery({
1329
+ messageId: response.ts,
1330
+ channelId: deliveredChannelId,
1331
+ threadTs: resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs),
1332
+ receipt: createSlackSendReceipt({
1333
+ platformMessageIds: [response.ts],
1349
1334
  channelId: deliveredChannelId,
1350
- threadTs: resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs),
1351
- receipt: createSlackSendReceipt({
1352
- platformMessageIds: [response.ts],
1353
- channelId: deliveredChannelId,
1354
- kind: "text",
1355
- threadTs: resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs)
1356
- })
1357
- });
1358
- }
1335
+ kind: "text",
1336
+ threadTs: resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs)
1337
+ })
1338
+ });
1359
1339
  }
1360
- const messageId = lastMessageId || "unknown";
1340
+ const messageId = lastMessageId;
1361
1341
  const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
1362
1342
  return {
1363
1343
  messageId,
1364
1344
  channelId: deliveredChannelId,
1365
1345
  threadTs: deliveredThreadTs,
1366
1346
  receipt: createSlackSendReceipt({
1367
- platformMessageIds: sentMessageIds.length ? sentMessageIds : [messageId],
1347
+ platformMessageIds: sentMessageIds,
1368
1348
  channelId: deliveredChannelId,
1369
1349
  kind: opts.mediaUrl ? "media" : "text",
1370
1350
  threadTs: deliveredThreadTs
@@ -1372,4 +1352,4 @@ async function sendMessageSlackQueuedInner(params) {
1372
1352
  };
1373
1353
  }
1374
1354
  //#endregion
1375
- export { updateMessageSlack as a, hasSlackThreadFailureNotice as c, recordSlackThreadFailureNotice as d, recordSlackThreadParticipation as f, setSlackDefaultSendIdentity as i, hasSlackThreadParticipation as l, chunkSlackTextAtHardLimit as m, resolveSlackDmChannelId as n, clearSlackThreadFailureNotice as o, buildSlackNativeDataDeliveryPlan as p, sendMessageSlack as r, clearSlackThreadParticipationCache as s, reconcileSlackUnknownSend as t, hasSlackThreadParticipationWithPersistence as u };
1355
+ export { updateMessageSlack as a, hasSlackThreadFailureNotice as c, recordSlackThreadFailureNotice as d, recordSlackThreadParticipation as f, chunkSlackTextAtHardLimit as h, setSlackDefaultSendIdentity as i, hasSlackThreadParticipation as l, buildSlackNativeDataDeliveryPlan as m, resolveSlackDmChannelId as n, clearSlackThreadFailureNotice as o, requireSlackPostMessageTimestamp as p, sendMessageSlack as r, clearSlackThreadParticipationCache as s, reconcileSlackUnknownSend as t, hasSlackThreadParticipationWithPersistence as u };
@@ -1,2 +1,2 @@
1
- import { a as updateMessageSlack, n as resolveSlackDmChannelId, r as sendMessageSlack, t as reconcileSlackUnknownSend } from "./send-Nor0iBwY.js";
1
+ import { a as updateMessageSlack, n as resolveSlackDmChannelId, r as sendMessageSlack, t as reconcileSlackUnknownSend } from "./send-CtnOxKCc.js";
2
2
  export { reconcileSlackUnknownSend, resolveSlackDmChannelId, sendMessageSlack, updateMessageSlack };
@@ -1,2 +1,2 @@
1
- import { t as slackSetupPlugin } from "./channel.setup-Bch9dYmA.js";
1
+ import { t as slackSetupPlugin } from "./channel.setup-CpyYsEXH.js";
2
2
  export { slackSetupPlugin };
@@ -1,9 +1,9 @@
1
- import { i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-CK4AVI2_.js";
2
- import { t as inspectSlackAccount } from "./account-inspect-Drw2gAiN.js";
3
- import "./shared-zdT5AMp-.js";
4
- import { o as SLACK_CHANNEL, r as createSlackSetupWizardBase } from "./channel.setup-Bch9dYmA.js";
5
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-CNPrxaXY.js";
6
- import { t as resolveSlackUserAllowlist } from "./resolve-users-Dzomuwnr.js";
1
+ import { i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-BlzxuYle.js";
2
+ import { t as inspectSlackAccount } from "./account-inspect-YJvFBbCR.js";
3
+ import "./shared-DJBaslN7.js";
4
+ import { o as SLACK_CHANNEL, r as createSlackSetupWizardBase } from "./channel.setup-CpyYsEXH.js";
5
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-BSpqC8jU.js";
6
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-Dvz9pDe0.js";
7
7
  import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { resolveBasicAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
9
9
  import { createSetupTranslator, noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, patchChannelConfigForAccount, promptResolvedAllowFrom, resolveEntriesWithOptionalToken, resolveSetupAccountId, splitSetupEntries } from "openclaw/plugin-sdk/setup-runtime";
@@ -1,14 +1,14 @@
1
- import { n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig, s as resolveSlackAccountDmPolicy } from "./accounts-CK4AVI2_.js";
2
- import { t as inspectSlackAccount } from "./account-inspect-Drw2gAiN.js";
1
+ import { n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig, s as resolveSlackAccountDmPolicy } from "./accounts-BlzxuYle.js";
2
+ import { t as inspectSlackAccount } from "./account-inspect-YJvFBbCR.js";
3
3
  import { a as parseSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
4
4
  import { t as isSlackPluginAccountConfigured } from "./account-configured-BwfXBo_F.js";
5
- import { b as getChatChannelMeta, t as probeSlack } from "./probe-HoEg_WxB.js";
6
- import { n as slackBaseConfigAdapter, t as slackSetupPlugin } from "./channel.setup-Bch9dYmA.js";
5
+ import { b as getChatChannelMeta, t as probeSlack } from "./probe-BVA65leh.js";
6
+ import { n as slackBaseConfigAdapter, t as slackSetupPlugin } from "./channel.setup-CpyYsEXH.js";
7
7
  import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BAy7-EUQ.js";
8
8
  import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DxmvbxBF.js";
9
9
  import { adaptScopedAccountAccessor, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
10
10
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
11
- import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, createDangerousNameMatchingMutableAllowlistWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
11
+ import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, createConditionalWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
12
12
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
13
13
  import { asObjectRecord } from "openclaw/plugin-sdk/runtime-doctor-migrations";
14
14
  //#region extensions/slack/src/security.ts
@@ -45,10 +45,16 @@ const collectSlackSecurityWarnings = createOpenProviderConfiguredRouteWarningCol
45
45
  remediation: "Set channels.slack.groupPolicy=\"allowlist\" and configure channels.slack.channels"
46
46
  }
47
47
  });
48
- const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-DR097212.js").then((n) => n.n));
48
+ const collectSlackSecurityFindings = createConditionalWarningCollector.findings({
49
+ collectWarnings: collectSlackSecurityWarnings,
50
+ checkId: "channels.slack.groups.open",
51
+ severity: "critical",
52
+ title: "Slack security warning"
53
+ });
54
+ const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-B_yKr7MW.js").then((n) => n.n));
49
55
  const slackSecurityAdapter = {
50
56
  resolveDmPolicy: resolveSlackDmPolicy,
51
- collectWarnings: collectSlackSecurityWarnings,
57
+ collectWarnings: collectSlackSecurityFindings,
52
58
  collectAuditFindings: async (params) => {
53
59
  const { collectSlackSecurityAuditFindings } = await loadSlackSecurityAuditModule();
54
60
  return await collectSlackSecurityAuditFindings(params);
@@ -1,5 +1,8 @@
1
- import { F as renderSlackBlockFallbackText } from "./group-policy-c4RP9bjc.js";
1
+ import { R as renderSlackBlockFallbackText } from "./group-policy-DyfB_ZIE.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { normalizeHostname } from "openclaw/plugin-sdk/host-runtime";
4
+ import { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/runtime-fetch";
5
+ import { saveRemoteMedia } from "openclaw/plugin-sdk/media-runtime";
3
6
  //#region extensions/slack/src/monitor/block-text.ts
4
7
  function readSlackBlockType(block) {
5
8
  return block && typeof block === "object" && !Array.isArray(block) ? block.type : void 0;
@@ -76,4 +79,16 @@ function chooseSlackPrimaryText(params) {
76
79
  return blocksText.text.length > messageText.length && blocksText.text.startsWith(messageText) ? blocksText.text : messageText;
77
80
  }
78
81
  //#endregion
79
- export { resolveSlackMessageText as a, resolveSlackBlocksText as i, hasSlackTableBlock as n, isSlackUnfurlAttachment as r, hasSlackMessageTableBlock as t };
82
+ //#region extensions/slack/src/monitor/slack-client-kind.ts
83
+ /** Detects the isolated GovSlack API plane without consulting mutable config. */
84
+ function isGovSlackClient(client) {
85
+ if (!client?.slackApiUrl) return false;
86
+ try {
87
+ const apiUrl = new URL(client.slackApiUrl);
88
+ return apiUrl.protocol === "https:" && !apiUrl.port && normalizeHostname(apiUrl.hostname) === "slack-gov.com";
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ //#endregion
94
+ export { hasSlackTableBlock as a, resolveSlackMessageText as c, hasSlackMessageTableBlock as i, fetchWithRuntimeDispatcher as n, isSlackUnfurlAttachment as o, saveRemoteMedia as r, resolveSlackBlocksText as s, isGovSlackClient as t };
@@ -1,7 +1,7 @@
1
- import { r as deliverSlackSlashReplies$1 } from "./replies-CeOfv82I.js";
1
+ import { r as deliverSlackSlashReplies$1 } from "./replies-SnWyXcsL.js";
2
2
  import { resolveAgentRoute as resolveAgentRoute$1 } from "openclaw/plugin-sdk/routing";
3
- import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
4
3
  import { resolveConversationLabel as resolveConversationLabel$1 } from "openclaw/plugin-sdk/conversation-runtime";
4
+ import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
5
5
  import { dispatchChannelInboundTurn as dispatchChannelInboundTurn$1, isChannelPartialDeliveryError as isChannelPartialDeliveryError$1 } from "openclaw/plugin-sdk/channel-inbound";
6
6
  import { finalizeInboundContext as finalizeInboundContext$1, resolveChunkMode as resolveChunkMode$1 } from "openclaw/plugin-sdk/reply-runtime";
7
7
  //#region extensions/slack/src/monitor/slash-dispatch.runtime.ts
@@ -267,6 +267,13 @@
267
267
  "narration": {
268
268
  "type": "boolean"
269
269
  },
270
+ "style": {
271
+ "type": "string",
272
+ "enum": [
273
+ "card",
274
+ "compact"
275
+ ]
276
+ },
270
277
  "nativeTaskCards": {
271
278
  "type": "boolean"
272
279
  }
@@ -1164,6 +1171,10 @@
1164
1171
  "auto",
1165
1172
  "on"
1166
1173
  ]
1174
+ },
1175
+ "prompt": {
1176
+ "type": "string",
1177
+ "maxLength": 20000
1167
1178
  }
1168
1179
  },
1169
1180
  "additionalProperties": false
@@ -1399,6 +1410,10 @@
1399
1410
  "auto",
1400
1411
  "on"
1401
1412
  ]
1413
+ },
1414
+ "prompt": {
1415
+ "type": "string",
1416
+ "maxLength": 20000
1402
1417
  }
1403
1418
  },
1404
1419
  "additionalProperties": false
@@ -1664,6 +1679,13 @@
1664
1679
  "narration": {
1665
1680
  "type": "boolean"
1666
1681
  },
1682
+ "style": {
1683
+ "type": "string",
1684
+ "enum": [
1685
+ "card",
1686
+ "compact"
1687
+ ]
1688
+ },
1667
1689
  "nativeTaskCards": {
1668
1690
  "type": "boolean"
1669
1691
  }
@@ -2558,6 +2580,10 @@
2558
2580
  "auto",
2559
2581
  "on"
2560
2582
  ]
2583
+ },
2584
+ "prompt": {
2585
+ "type": "string",
2586
+ "maxLength": 20000
2561
2587
  }
2562
2588
  },
2563
2589
  "additionalProperties": false
@@ -2793,6 +2819,10 @@
2793
2819
  "auto",
2794
2820
  "on"
2795
2821
  ]
2822
+ },
2823
+ "prompt": {
2824
+ "type": "string",
2825
+ "maxLength": 20000
2796
2826
  }
2797
2827
  },
2798
2828
  "additionalProperties": false
@@ -2915,9 +2945,13 @@
2915
2945
  "label": "Slack Draft Command Text",
2916
2946
  "help": "Command/exec detail in preview tool-progress lines: \"status\" is the safe default; \"raw\" opts into command text."
2917
2947
  },
2948
+ "streaming.progress.style": {
2949
+ "label": "Slack Progress Style",
2950
+ "help": "Slack progress presentation: \"card\" (default) uses structured task/session cards; \"compact\" keeps one editable text draft that the final answer replaces in place when Slack can safely edit it."
2951
+ },
2918
2952
  "streaming.progress.nativeTaskCards": {
2919
2953
  "label": "Slack Native Progress Task Cards",
2920
- "help": "Slack native task-card progress updates when channels.slack.streaming.mode=\"progress\" and streaming.nativeTransport is enabled. Set false to fall back to the Block Kit progress card. Default: true."
2954
+ "help": "Slack native task-card progress updates when channels.slack.streaming.mode=\"progress\", progress.style=\"card\", and streaming.nativeTransport is enabled. Set false to fall back to the Block Kit progress card. Default: true."
2921
2955
  },
2922
2956
  "streaming.progress.label": {
2923
2957
  "label": "Slack Progress Label",
@@ -3011,10 +3045,18 @@
3011
3045
  "label": "Slack Presence Event Mode",
3012
3046
  "help": "\"off\" disables polling; \"auto\" covers DMs, MPIMs, and recent threads with up to 8 observed people; \"on\" also covers larger threads and top-level channels."
3013
3047
  },
3048
+ "presenceEvents.prompt": {
3049
+ "label": "Slack Presence Event Prompt",
3050
+ "help": "Replace the default greeting guidance appended after presence facts. Use an empty string to omit event-specific guidance and let workspace instructions such as AGENTS.md govern behavior. Maximum: 20,000 characters."
3051
+ },
3014
3052
  "channels.*.presenceEvents.mode": {
3015
3053
  "label": "Slack Channel Presence Event Mode",
3016
3054
  "help": "Override presence events for one Slack channel. Use \"on\" to include large threads or top-level channel sessions."
3017
3055
  },
3056
+ "channels.*.presenceEvents.prompt": {
3057
+ "label": "Slack Channel Presence Event Prompt",
3058
+ "help": "Override the account-level presence-event prompt for one Slack channel. Maximum: 20,000 characters."
3059
+ },
3018
3060
  "execApprovals.enabled": {
3019
3061
  "label": "Slack Exec Approvals Enabled",
3020
3062
  "help": "Controls Slack native exec approvals for this account: unset or \"auto\" enables DM-first native approvals when approvers can be resolved, true forces native approvals on, and false disables them."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/slack",
3
- "version": "2026.8.1-beta.2",
3
+ "version": "2026.8.1-beta.3",
4
4
  "description": "OpenClaw Slack channel plugin for channels, DMs, commands, and app events.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,14 +13,13 @@
13
13
  "@slack/types": "3.0.0",
14
14
  "@slack/web-api": "8.0.0",
15
15
  "get-east-asian-width": "1.6.0",
16
- "p-map": "7.0.6",
17
16
  "typebox": "1.3.6",
18
17
  "undici": "7.29.0",
19
18
  "ws": "8.21.1",
20
19
  "zod": "4.4.3"
21
20
  },
22
21
  "peerDependencies": {
23
- "openclaw": ">=2026.8.1-beta.2"
22
+ "openclaw": ">=2026.8.1-beta.3"
24
23
  },
25
24
  "peerDependenciesMeta": {
26
25
  "openclaw": {
@@ -150,10 +149,10 @@
150
149
  "allowInvalidConfigRecovery": true
151
150
  },
152
151
  "compat": {
153
- "pluginApi": ">=2026.8.1-beta.2"
152
+ "pluginApi": ">=2026.8.1-beta.3"
154
153
  },
155
154
  "build": {
156
- "openclawVersion": "2026.8.1-beta.2",
155
+ "openclawVersion": "2026.8.1-beta.3",
157
156
  "bundledDist": false
158
157
  },
159
158
  "release": {
@@ -177,7 +176,6 @@
177
176
  "@slack/types",
178
177
  "@slack/web-api",
179
178
  "get-east-asian-width",
180
- "p-map",
181
179
  "typebox",
182
180
  "undici",
183
181
  "ws",
@@ -1,14 +0,0 @@
1
- //#region extensions/slack/src/account-reply-mode.ts
2
- function normalizeSlackChatType(raw) {
3
- const value = raw?.trim().toLowerCase();
4
- if (!value) return;
5
- if (value === "direct" || value === "dm") return "direct";
6
- if (value === "group" || value === "channel") return value;
7
- }
8
- function resolveSlackReplyToMode(account, chatType) {
9
- const normalized = normalizeSlackChatType(chatType ?? void 0);
10
- if (normalized && account.replyToModeByChatType?.[normalized] !== void 0) return account.replyToModeByChatType[normalized] ?? "off";
11
- return account.replyToMode ?? "off";
12
- }
13
- //#endregion
14
- export { resolveSlackReplyToMode as t };
@@ -1,2 +0,0 @@
1
- import { t as handleSlackAction } from "./action-runtime-BkGe7ny_.js";
2
- export { handleSlackAction };