@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
@@ -29,6 +29,9 @@
29
29
  "relay"
30
30
  ]
31
31
  },
32
+ "enterpriseOrgInstall": {
33
+ "type": "boolean"
34
+ },
32
35
  "socketMode": {
33
36
  "type": "object",
34
37
  "properties": {
@@ -819,6 +822,9 @@
819
822
  "commentary": {
820
823
  "type": "boolean"
821
824
  },
825
+ "narration": {
826
+ "type": "boolean"
827
+ },
822
828
  "nativeTaskCards": {
823
829
  "type": "boolean"
824
830
  }
@@ -997,6 +1003,20 @@
997
1003
  },
998
1004
  "additionalProperties": false
999
1005
  },
1006
+ "presenceEvents": {
1007
+ "type": "object",
1008
+ "properties": {
1009
+ "mode": {
1010
+ "type": "string",
1011
+ "enum": [
1012
+ "off",
1013
+ "auto",
1014
+ "on"
1015
+ ]
1016
+ }
1017
+ },
1018
+ "additionalProperties": false
1019
+ },
1000
1020
  "actions": {
1001
1021
  "type": "object",
1002
1022
  "properties": {
@@ -1284,6 +1304,20 @@
1284
1304
  },
1285
1305
  "systemPrompt": {
1286
1306
  "type": "string"
1307
+ },
1308
+ "presenceEvents": {
1309
+ "type": "object",
1310
+ "properties": {
1311
+ "mode": {
1312
+ "type": "string",
1313
+ "enum": [
1314
+ "off",
1315
+ "auto",
1316
+ "on"
1317
+ ]
1318
+ }
1319
+ },
1320
+ "additionalProperties": false
1287
1321
  }
1288
1322
  },
1289
1323
  "additionalProperties": false
@@ -1341,6 +1375,9 @@
1341
1375
  "relay"
1342
1376
  ]
1343
1377
  },
1378
+ "enterpriseOrgInstall": {
1379
+ "type": "boolean"
1380
+ },
1344
1381
  "socketMode": {
1345
1382
  "type": "object",
1346
1383
  "properties": {
@@ -2129,6 +2166,9 @@
2129
2166
  "commentary": {
2130
2167
  "type": "boolean"
2131
2168
  },
2169
+ "narration": {
2170
+ "type": "boolean"
2171
+ },
2132
2172
  "nativeTaskCards": {
2133
2173
  "type": "boolean"
2134
2174
  }
@@ -2307,6 +2347,20 @@
2307
2347
  },
2308
2348
  "additionalProperties": false
2309
2349
  },
2350
+ "presenceEvents": {
2351
+ "type": "object",
2352
+ "properties": {
2353
+ "mode": {
2354
+ "type": "string",
2355
+ "enum": [
2356
+ "off",
2357
+ "auto",
2358
+ "on"
2359
+ ]
2360
+ }
2361
+ },
2362
+ "additionalProperties": false
2363
+ },
2310
2364
  "actions": {
2311
2365
  "type": "object",
2312
2366
  "properties": {
@@ -2594,6 +2648,20 @@
2594
2648
  },
2595
2649
  "systemPrompt": {
2596
2650
  "type": "string"
2651
+ },
2652
+ "presenceEvents": {
2653
+ "type": "object",
2654
+ "properties": {
2655
+ "mode": {
2656
+ "type": "string",
2657
+ "enum": [
2658
+ "off",
2659
+ "auto",
2660
+ "on"
2661
+ ]
2662
+ }
2663
+ },
2664
+ "additionalProperties": false
2597
2665
  }
2598
2666
  },
2599
2667
  "additionalProperties": false
@@ -2658,6 +2726,10 @@
2658
2726
  "label": "Slack",
2659
2727
  "help": "Slack channel provider configuration for bot/app tokens, streaming behavior, and DM policy controls. Keep token handling and thread behavior explicit to avoid noisy workspace interactions."
2660
2728
  },
2729
+ "enterpriseOrgInstall": {
2730
+ "label": "Slack Enterprise Grid Org Install",
2731
+ "help": "Enable only for an Enterprise Grid org-wide bot installation. OpenClaw verifies the token with Slack auth.test at startup; DMs must be disabled or use dmPolicy=\"open\" with allowFrom=[\"*\"]."
2732
+ },
2661
2733
  "dm.policy": {
2662
2734
  "label": "Slack DM Policy",
2663
2735
  "help": "Direct message access control (\"pairing\" recommended). \"open\" requires channels.slack.allowFrom=[\"*\"] (legacy: channels.slack.dm.allowFrom)."
@@ -2774,6 +2846,18 @@
2774
2846
  "label": "Slack Exec Approvals",
2775
2847
  "help": "Slack-native exec approval routing and approver authorization. When unset, OpenClaw auto-enables DM-first native approvals if approvers can be resolved for this workspace account."
2776
2848
  },
2849
+ "presenceEvents": {
2850
+ "label": "Slack Presence Events",
2851
+ "help": "Poll observed human participants and wake the routed agent on away-to-active transitions. Default: \"off\"."
2852
+ },
2853
+ "presenceEvents.mode": {
2854
+ "label": "Slack Presence Event Mode",
2855
+ "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."
2856
+ },
2857
+ "channels.*.presenceEvents.mode": {
2858
+ "label": "Slack Channel Presence Event Mode",
2859
+ "help": "Override presence events for one Slack channel. Use \"on\" to include large threads or top-level channel sessions."
2860
+ },
2777
2861
  "execApprovals.enabled": {
2778
2862
  "label": "Slack Exec Approvals Enabled",
2779
2863
  "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.7.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "description": "OpenClaw Slack channel plugin for channels, DMs, commands, and app events.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,12 +11,13 @@
11
11
  "@slack/bolt": "4.7.3",
12
12
  "@slack/types": "2.21.1",
13
13
  "@slack/web-api": "7.18.0",
14
+ "p-map": "7.0.5",
14
15
  "typebox": "1.3.3",
15
16
  "ws": "8.21.0",
16
17
  "zod": "4.4.3"
17
18
  },
18
19
  "peerDependencies": {
19
- "openclaw": ">=2026.7.1"
20
+ "openclaw": ">=2026.7.2-beta.2"
20
21
  },
21
22
  "peerDependenciesMeta": {
22
23
  "openclaw": {
@@ -49,9 +50,7 @@
49
50
  "SLACK_BOT_TOKEN",
50
51
  "SLACK_USER_TOKEN"
51
52
  ]
52
- },
53
- "specifier": "./configured-state",
54
- "exportName": "hasSlackConfiguredState"
53
+ }
55
54
  }
56
55
  },
57
56
  "install": {
@@ -61,13 +60,13 @@
61
60
  "allowInvalidConfigRecovery": true
62
61
  },
63
62
  "compat": {
64
- "pluginApi": ">=2026.7.1"
63
+ "pluginApi": ">=2026.7.2-beta.2"
65
64
  },
66
65
  "startup": {
67
66
  "deferConfiguredChannelFullLoadUntilAfterListen": true
68
67
  },
69
68
  "build": {
70
- "openclawVersion": "2026.7.1",
69
+ "openclawVersion": "2026.7.2-beta.2",
71
70
  "bundledDist": false
72
71
  },
73
72
  "release": {
@@ -90,6 +89,7 @@
90
89
  "@slack/bolt",
91
90
  "@slack/types",
92
91
  "@slack/web-api",
92
+ "p-map",
93
93
  "typebox",
94
94
  "ws",
95
95
  "zod"
@@ -1,2 +0,0 @@
1
- import { a as resolveSlackAccount } from "./accounts-BOJJiHSr.js";
2
- export { resolveSlackAccount };
@@ -1,2 +0,0 @@
1
- import { t as handleSlackAction } from "./action-runtime-DoQGk_8D.js";
2
- export { handleSlackAction };
@@ -1,2 +0,0 @@
1
- import { SlackConfigSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
2
- export { buildChannelConfigSchema as n, SlackConfigSchema as t };
@@ -1,11 +0,0 @@
1
- //#region extensions/slack/configured-state.ts
2
- const SLACK_CONFIGURED_ENV_KEYS = [
3
- "SLACK_APP_TOKEN",
4
- "SLACK_BOT_TOKEN",
5
- "SLACK_USER_TOKEN"
6
- ];
7
- function hasSlackConfiguredState(params) {
8
- return SLACK_CONFIGURED_ENV_KEYS.some((key) => typeof params.env?.[key] === "string" && params.env[key]?.trim().length > 0);
9
- }
10
- //#endregion
11
- export { hasSlackConfiguredState };
@@ -1,107 +0,0 @@
1
- import { markdownToIR, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers } from "openclaw/plugin-sdk/text-chunking";
2
- //#region extensions/slack/src/format.ts
3
- function escapeSlackMrkdwnSegment(text) {
4
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5
- }
6
- const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
7
- function isAllowedSlackAngleToken(token) {
8
- if (!token.startsWith("<") || !token.endsWith(">")) return false;
9
- const inner = token.slice(1, -1);
10
- return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
11
- }
12
- function escapeSlackMrkdwnContent(text) {
13
- if (!text) return "";
14
- if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
15
- SLACK_ANGLE_TOKEN_RE.lastIndex = 0;
16
- const out = [];
17
- let lastIndex = 0;
18
- for (let match = SLACK_ANGLE_TOKEN_RE.exec(text); match; match = SLACK_ANGLE_TOKEN_RE.exec(text)) {
19
- const matchIndex = match.index ?? 0;
20
- out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex, matchIndex)));
21
- const token = match[0] ?? "";
22
- out.push(isAllowedSlackAngleToken(token) ? token : escapeSlackMrkdwnSegment(token));
23
- lastIndex = matchIndex + token.length;
24
- }
25
- out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex)));
26
- return out.join("");
27
- }
28
- function escapeSlackMrkdwnText(text) {
29
- if (!text) return "";
30
- if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
31
- return text.split("\n").map((line) => {
32
- if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2))}`;
33
- return escapeSlackMrkdwnContent(line);
34
- }).join("\n");
35
- }
36
- function buildSlackLink(link, text) {
37
- const href = link.href.trim();
38
- if (!href) return null;
39
- const trimmedLabel = text.slice(link.start, link.end).trim();
40
- const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
41
- if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
42
- const safeHref = escapeSlackMrkdwnSegment(href);
43
- return {
44
- start: link.start,
45
- end: link.end,
46
- open: `<${safeHref}|`,
47
- close: ">"
48
- };
49
- }
50
- function buildSlackRenderOptions() {
51
- return {
52
- styleMarkers: {
53
- bold: {
54
- open: "*",
55
- close: "*"
56
- },
57
- italic: {
58
- open: "_",
59
- close: "_"
60
- },
61
- strikethrough: {
62
- open: "~",
63
- close: "~"
64
- },
65
- code: {
66
- open: "`",
67
- close: "`"
68
- },
69
- code_block: {
70
- open: "```\n",
71
- close: "```"
72
- }
73
- },
74
- escapeText: escapeSlackMrkdwnText,
75
- buildLink: buildSlackLink
76
- };
77
- }
78
- function markdownToSlackMrkdwn(markdown, options = {}) {
79
- return renderMarkdownWithMarkers(markdownToIR(markdown ?? "", {
80
- linkify: false,
81
- autolink: false,
82
- headingStyle: "bold",
83
- blockquotePrefix: "> ",
84
- tableMode: options.tableMode
85
- }), buildSlackRenderOptions());
86
- }
87
- function normalizeSlackOutboundText(markdown) {
88
- return markdownToSlackMrkdwn(markdown ?? "");
89
- }
90
- function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
91
- const ir = markdownToIR(markdown ?? "", {
92
- linkify: false,
93
- autolink: false,
94
- headingStyle: "bold",
95
- blockquotePrefix: "> ",
96
- tableMode: options.tableMode
97
- });
98
- const renderOptions = buildSlackRenderOptions();
99
- return renderMarkdownIRChunksWithinLimit({
100
- ir,
101
- limit,
102
- renderChunk: (chunk) => renderMarkdownWithMarkers(chunk, renderOptions),
103
- measureRendered: (rendered) => rendered.length
104
- }).map(({ rendered }) => rendered);
105
- }
106
- //#endregion
107
- export { normalizeSlackOutboundText as n, markdownToSlackMrkdwnChunks as t };
@@ -1,272 +0,0 @@
1
- import { T as SLACK_SECTION_TEXT_MAX, _ as buildSlackPresentationBlocks, a as SLACK_TEXT_LIMIT, g as buildSlackInteractiveBlocks, r as parseSlackBlocksInput, v as canRenderSlackPresentation, w as SLACK_PRESENTATION_CAPABILITIES, y as resolveSlackInteractiveBlockOffsets } from "./reply-blocks-BGQ6zSqM.js";
2
- import { n as resolveSlackThreadTsValue } from "./thread-ts-DUGhaYKq.js";
3
- import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-CXpT-vA_.js";
4
- import { t as markdownToSlackMrkdwnChunks } from "./format-YCNoNkM2.js";
5
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
- import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
7
- import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
8
- import { renderMessagePresentationFallbackText, resolveInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
9
- import { resolvePayloadMediaUrls, sendPayloadMediaSequenceAndFinalize, sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
10
- import { attachChannelToResult, createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
11
- //#region extensions/slack/src/outbound-adapter.ts
12
- const loadSlackSendRuntime = createLazyRuntimeModule(() => import("./send.runtime-GPRa63l1.js"));
13
- function resolveRenderedInteractiveBlocks(interactive, previousBlocks) {
14
- if (!interactive) return;
15
- const blocks = buildSlackInteractiveBlocks(interactive, resolveSlackInteractiveBlockOffsets(previousBlocks));
16
- return blocks.length > 0 ? blocks : void 0;
17
- }
18
- function resolveSlackSendIdentity(identity) {
19
- if (!identity) return;
20
- const username = normalizeOptionalString(identity.name);
21
- const iconUrl = normalizeOptionalString(identity.avatarUrl);
22
- const rawEmoji = normalizeOptionalString(identity.emoji);
23
- const iconEmoji = !iconUrl ? rawEmoji : void 0;
24
- if (!username && !iconUrl && !iconEmoji) return;
25
- return {
26
- username,
27
- iconUrl,
28
- iconEmoji
29
- };
30
- }
31
- function buildSlackTextSectionBlocks(text) {
32
- return markdownToSlackMrkdwnChunks(text.trim(), SLACK_SECTION_TEXT_MAX).map((chunk) => ({
33
- type: "section",
34
- text: {
35
- type: "mrkdwn",
36
- text: chunk
37
- }
38
- }));
39
- }
40
- function normalizeComparableSlackText(text) {
41
- return text.trim().replace(/\s+/g, " ");
42
- }
43
- function isPayloadTextRepresentedInInteractive(text, interactive) {
44
- const target = normalizeComparableSlackText(text);
45
- const fragments = interactive?.blocks.flatMap((block) => block.type === "text" ? [normalizeComparableSlackText(block.text)] : []) ?? [];
46
- for (let start = 0; start < fragments.length; start += 1) {
47
- let combined = "";
48
- for (let end = start; end < fragments.length; end += 1) {
49
- combined = normalizeComparableSlackText(`${combined} ${fragments[end]}`);
50
- if (combined === target) return true;
51
- if (combined.length > target.length) break;
52
- }
53
- }
54
- return false;
55
- }
56
- function buildSlackVisiblePayloadTextBlocks(payload) {
57
- const text = normalizeOptionalString(payload.text);
58
- if (!text || isPayloadTextRepresentedInInteractive(text, payload.interactive)) return [];
59
- return buildSlackTextSectionBlocks(text);
60
- }
61
- function buildSlackPresentationFallback(presentation) {
62
- const text = renderMessagePresentationFallbackText({ presentation }).trim();
63
- return {
64
- blocks: buildSlackTextSectionBlocks(text),
65
- text
66
- };
67
- }
68
- function withSlackPresentationData(payload, slackData, presentationData) {
69
- const { presentationBlocks: _presentationBlocks, presentationFallbackText: _presentationFallbackText, ...rest } = slackData ?? {};
70
- return {
71
- ...payload,
72
- channelData: {
73
- ...payload.channelData,
74
- slack: {
75
- ...rest,
76
- ...presentationData
77
- }
78
- }
79
- };
80
- }
81
- async function sendSlackOutboundMessage(params) {
82
- const send = resolveOutboundSendDep(params.deps, "slack") ?? (await loadSlackSendRuntime()).sendMessageSlack;
83
- const slackIdentity = resolveSlackSendIdentity(params.identity);
84
- const threadTs = resolveSlackThreadTsValue({
85
- replyToId: params.replyToId,
86
- threadId: params.threadId
87
- });
88
- return await send(params.to, params.text, {
89
- cfg: params.cfg,
90
- threadTs,
91
- accountId: params.accountId ?? void 0,
92
- ...params.mediaUrl ? {
93
- mediaUrl: params.mediaUrl,
94
- mediaAccess: params.mediaAccess,
95
- mediaLocalRoots: params.mediaLocalRoots,
96
- mediaReadFile: params.mediaReadFile
97
- } : {},
98
- ...params.blocks ? { blocks: params.blocks } : {},
99
- ...slackIdentity ? { identity: slackIdentity } : {},
100
- deliveryQueueId: params.deliveryQueueId,
101
- onPlatformSendDispatch: params.onPlatformSendDispatch,
102
- onDeliveryResult: params.onDeliveryResult ? async (progress) => {
103
- await params.onDeliveryResult?.(attachChannelToResult("slack", progress));
104
- } : void 0
105
- });
106
- }
107
- function resolveSlackBlocks(payload) {
108
- const slackData = payload.channelData?.slack;
109
- const nativeBlocks = parseSlackBlocksInput(slackData?.blocks);
110
- const renderedPresentation = slackData?.presentationBlocks ?? (payload.presentation ? [...buildSlackVisiblePayloadTextBlocks(payload), ...buildSlackPresentationBlocks(payload.presentation, resolveSlackInteractiveBlockOffsets(nativeBlocks))] : []);
111
- const previousBlocks = [...nativeBlocks ?? [], ...renderedPresentation];
112
- const renderedInteractive = resolveRenderedInteractiveBlocks(payload.interactive, previousBlocks);
113
- const mergedBlocks = [...previousBlocks, ...renderedInteractive ?? []];
114
- if (mergedBlocks.length === 0) return;
115
- if (mergedBlocks.length > 50) throw new Error(`Slack blocks cannot exceed 50 items after interactive render`);
116
- return mergedBlocks;
117
- }
118
- const slackOutbound = {
119
- deliveryMode: "direct",
120
- chunker: null,
121
- textChunkLimit: SLACK_TEXT_LIMIT,
122
- normalizePayload: ({ payload, cfg, accountId }) => isSlackInteractiveRepliesEnabled({
123
- cfg,
124
- accountId
125
- }) ? compileSlackInteractiveReplies(payload) : payload,
126
- presentationCapabilities: SLACK_PRESENTATION_CAPABILITIES,
127
- renderPresentation: ({ payload, presentation, ctx }) => {
128
- const payloadForBudget = isSlackInteractiveRepliesEnabled({
129
- cfg: ctx.cfg,
130
- accountId: ctx.accountId
131
- }) ? compileSlackInteractiveReplies(payload) : payload;
132
- const slackData = payload.channelData?.slack;
133
- const nativeBlocks = parseSlackBlocksInput(slackData?.blocks);
134
- const payloadTextBlocks = buildSlackVisiblePayloadTextBlocks(payloadForBudget);
135
- if (canRenderSlackPresentation(presentation)) {
136
- const presentationBlocks = [...payloadTextBlocks, ...buildSlackPresentationBlocks(presentation, resolveSlackInteractiveBlockOffsets(nativeBlocks))];
137
- const previousBlocks = [...nativeBlocks ?? [], ...presentationBlocks];
138
- const interactiveBlocks = resolveRenderedInteractiveBlocks(payloadForBudget.interactive, previousBlocks);
139
- if (presentationBlocks.length > 0 && previousBlocks.length + (interactiveBlocks?.length ?? 0) <= 50) return withSlackPresentationData(payloadForBudget, slackData, { presentationBlocks });
140
- }
141
- const baseInteractiveBlocks = resolveRenderedInteractiveBlocks(payloadForBudget.interactive, nativeBlocks);
142
- if ((nativeBlocks?.length ?? 0) + (baseInteractiveBlocks?.length ?? 0) === 0) return null;
143
- const fallback = buildSlackPresentationFallback(presentation);
144
- const fallbackBlocks = [...payloadTextBlocks, ...fallback.blocks];
145
- if (fallbackBlocks.length === 0) return null;
146
- const fallbackPayload = {
147
- ...payloadForBudget,
148
- text: renderMessagePresentationFallbackText({
149
- text: payloadForBudget.text,
150
- presentation
151
- })
152
- };
153
- const fallbackPreviousBlocks = [...nativeBlocks ?? [], ...fallbackBlocks];
154
- const fallbackInteractiveBlocks = resolveRenderedInteractiveBlocks(payloadForBudget.interactive, fallbackPreviousBlocks);
155
- if (fallbackPreviousBlocks.length + (fallbackInteractiveBlocks?.length ?? 0) <= 50) return withSlackPresentationData(fallbackPayload, slackData, { presentationBlocks: fallbackBlocks });
156
- const separateFallbackText = renderMessagePresentationFallbackText({
157
- text: payloadTextBlocks.length > 0 ? payloadForBudget.text : void 0,
158
- presentation
159
- });
160
- return withSlackPresentationData(payloadTextBlocks.length > 0 ? {
161
- ...payloadForBudget,
162
- text: void 0
163
- } : payloadForBudget, slackData, { presentationFallbackText: separateFallbackText });
164
- },
165
- sendPayload: async (ctx) => {
166
- const payload = {
167
- ...ctx.payload,
168
- text: resolveInteractiveTextFallback({
169
- text: ctx.payload.text,
170
- interactive: ctx.payload.interactive
171
- }) ?? ""
172
- };
173
- const slackData = payload.channelData?.slack;
174
- const presentationFallbackText = normalizeOptionalString(slackData?.presentationFallbackText);
175
- const blocks = resolveSlackBlocks(payload);
176
- if (!blocks) return await sendTextMediaPayload({
177
- channel: "slack",
178
- ctx: {
179
- ...ctx,
180
- payload: presentationFallbackText ? {
181
- ...payload,
182
- text: [normalizeOptionalString(payload.text), presentationFallbackText].filter((part) => Boolean(part)).join("\n\n")
183
- } : payload
184
- },
185
- adapter: slackOutbound
186
- });
187
- return attachChannelToResult("slack", await sendPayloadMediaSequenceAndFinalize({
188
- text: "",
189
- mediaUrls: resolvePayloadMediaUrls(payload),
190
- send: async ({ text, mediaUrl }) => await sendSlackOutboundMessage({
191
- cfg: ctx.cfg,
192
- to: ctx.to,
193
- text,
194
- mediaUrl,
195
- mediaAccess: ctx.mediaAccess,
196
- mediaLocalRoots: ctx.mediaLocalRoots,
197
- mediaReadFile: ctx.mediaReadFile,
198
- accountId: ctx.accountId,
199
- deps: ctx.deps,
200
- replyToId: ctx.replyToId,
201
- threadId: ctx.threadId,
202
- identity: ctx.identity,
203
- onDeliveryResult: ctx.onDeliveryResult
204
- }),
205
- finalize: async () => {
206
- const blockResult = await sendSlackOutboundMessage({
207
- cfg: ctx.cfg,
208
- to: ctx.to,
209
- text: payload.text ?? "",
210
- mediaAccess: ctx.mediaAccess,
211
- mediaLocalRoots: ctx.mediaLocalRoots,
212
- mediaReadFile: ctx.mediaReadFile,
213
- blocks,
214
- accountId: ctx.accountId,
215
- deps: ctx.deps,
216
- replyToId: ctx.replyToId,
217
- threadId: ctx.threadId,
218
- identity: ctx.identity,
219
- onDeliveryResult: ctx.onDeliveryResult
220
- });
221
- if (!presentationFallbackText) return blockResult;
222
- return await sendSlackOutboundMessage({
223
- cfg: ctx.cfg,
224
- to: ctx.to,
225
- text: presentationFallbackText,
226
- mediaAccess: ctx.mediaAccess,
227
- mediaLocalRoots: ctx.mediaLocalRoots,
228
- mediaReadFile: ctx.mediaReadFile,
229
- accountId: ctx.accountId,
230
- deps: ctx.deps,
231
- replyToId: ctx.replyToId,
232
- threadId: ctx.threadId,
233
- identity: ctx.identity,
234
- onDeliveryResult: ctx.onDeliveryResult
235
- });
236
- }
237
- }));
238
- },
239
- ...createAttachedChannelResultAdapter({
240
- channel: "slack",
241
- sendText: async ({ cfg, to, text, accountId, deps, replyToId, threadId, identity, deliveryQueueId, onPlatformSendDispatch, onDeliveryResult }) => await sendSlackOutboundMessage({
242
- cfg,
243
- to,
244
- text,
245
- accountId,
246
- deps,
247
- replyToId,
248
- threadId,
249
- identity,
250
- deliveryQueueId,
251
- onPlatformSendDispatch,
252
- onDeliveryResult
253
- }),
254
- sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId, threadId, identity, onDeliveryResult }) => await sendSlackOutboundMessage({
255
- cfg,
256
- to,
257
- text,
258
- mediaUrl,
259
- mediaAccess,
260
- mediaLocalRoots,
261
- mediaReadFile,
262
- accountId,
263
- deps,
264
- replyToId,
265
- threadId,
266
- identity,
267
- onDeliveryResult
268
- })
269
- })
270
- };
271
- //#endregion
272
- export { slackOutbound };