@openclaw/slack 2026.9.1-beta.1 → 2026.9.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 (99) hide show
  1. package/dist/{account-inspect-CN2hBsim.js → account-inspect-C3sePHWa.js} +3 -3
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{action-runtime-BoSeX09X.js → action-runtime-DftQWpI4.js} +84 -66
  4. package/dist/action-runtime.runtime-rHI3UAh4.js +2 -0
  5. package/dist/{actions-XdQyjG_p.js → actions-CFkvEv1d.js} +198 -54
  6. package/dist/api.js +14 -14
  7. package/dist/{approval-handler.runtime-DxXfGX_Z.js → approval-handler.runtime-BeILKdw4.js} +47 -25
  8. package/dist/{channel-C_vnTgxo.js → channel-CmOuxbOD.js} +76 -133
  9. package/dist/channel-config-api.js +1 -1
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/{channel-type-j-2lalcC.js → channel-type-BWt2CRaI.js} +2 -2
  12. package/dist/{channel.setup-aal8tokM.js → channel.setup-D5z1ReaT.js} +29 -23
  13. package/dist/{config-schema-CN3XZRX5.js → config-schema-JDx_f9Zb.js} +26 -17
  14. package/dist/{cursor-pages-eX7p8Wwt.js → cursor-pages-ByFwo-Py.js} +7 -1
  15. package/dist/{directory-config-DqfQ42OV.js → directory-config-Bmw4ykSy.js} +4 -3
  16. package/dist/directory-contract-api.js +1 -1
  17. package/dist/{directory-live-lC6X_Ru-.js → directory-live-BuBPHmju.js} +3 -8
  18. package/dist/{doctor-contract-BAy7-EUQ.js → doctor-contract-BNjw9bxb.js} +5 -4
  19. package/dist/doctor-contract-api.js +1 -1
  20. package/dist/{message-tool-api-CWosHSi5.js → message-tool-api-uNEfQYGY.js} +19 -2
  21. package/dist/message-tool-api.js +1 -1
  22. package/dist/{monitor-DrNCGneD.js → monitor-DI07pfJl.js} +3 -3
  23. package/dist/{outbound-adapter-DkT2vUE9.js → outbound-adapter-B5QyTRpJ.js} +96 -91
  24. package/dist/{pipeline.runtime-CRRng_Nw.js → pipeline.runtime-BdIwZgm4.js} +596 -920
  25. package/dist/{policy-BoP6t88v.js → policy-Bh5TOqII.js} +7 -4
  26. package/dist/{probe-4_aHtVT3.js → probe-Biy--yhL.js} +251 -12
  27. package/dist/{provider-D4nDgxCh.js → provider-DoaUvAM4.js} +5621 -4944
  28. package/dist/{relay-source-CEmze11m.js → relay-source-D4uecp68.js} +6 -4
  29. package/dist/{replies-D9XMM_S0.js → replies-DENuTcPO.js} +21 -16
  30. package/dist/reply-blocks-PRkhyAN7.js +790 -0
  31. package/dist/{resolve-channels-DSamDgVs.js → resolve-channels-DQGV2VrE.js} +6 -10
  32. package/dist/{resolve-users-CIzwbaJR.js → resolve-users-DRGt_Q4I.js} +5 -4
  33. package/dist/runtime-api.js +10 -10
  34. package/dist/{scopes-BBrUzpBH.js → scopes-CZzeGdWV.js} +1 -1
  35. package/dist/{send-DtjEnlLh.js → send-DElUcgIs.js} +32 -24
  36. package/dist/send-results-eeOu_HYm.js +23 -0
  37. package/dist/{send.runtime-DQeNKa2J.js → send.runtime-C8D6cKGm.js} +1 -1
  38. package/dist/{group-policy-CU1tEGpS.js → session-status-BynwcZSO.js} +284 -1013
  39. package/dist/setup-plugin-api.js +1 -1
  40. package/dist/{setup-surface-CsBCM4rP.js → setup-surface-B1_gpGBl.js} +5 -5
  41. package/dist/{shared-D9GeeR9K.js → shared-CNQsWJT7.js} +7 -5
  42. package/dist/{slash-dispatch.runtime-Chr3YHnT.js → slash-dispatch.runtime-DhsXavSY.js} +2 -2
  43. package/dist/{target-parsing-BnMD2ZqZ.js → target-parsing-PbxGDbr9.js} +11 -6
  44. package/dist/{targets-Cx5W_n3W.js → targets-7FexXJ62.js} +1 -1
  45. package/dist/{thread-ts-DUGhaYKq.js → thread-ts-CukseRVL.js} +5 -1
  46. package/node_modules/@slack/bolt/node_modules/negotiator/lib/accept.js +54 -0
  47. package/node_modules/@slack/bolt/node_modules/negotiator/lib/charset.js +10 -34
  48. package/node_modules/@slack/bolt/node_modules/negotiator/lib/encoding.js +9 -30
  49. package/node_modules/@slack/bolt/node_modules/negotiator/lib/language.js +15 -36
  50. package/node_modules/@slack/bolt/node_modules/negotiator/lib/mediaType.js +16 -134
  51. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
  52. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +71 -0
  53. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
  54. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
  55. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
  56. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +52 -0
  57. package/node_modules/@slack/bolt/node_modules/negotiator/package.json +16 -10
  58. package/node_modules/typebox/build/format/email.mjs +1 -1
  59. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
  60. package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
  61. package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
  62. package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
  63. package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
  64. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  65. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  66. package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
  67. package/node_modules/typebox/build/system/memory/create.mjs +3 -4
  68. package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
  69. package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
  70. package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
  71. package/node_modules/typebox/build/system/memory/update.mjs +3 -2
  72. package/node_modules/typebox/package.json +1 -1
  73. package/node_modules/undici/lib/dispatcher/balanced-pool.js +4 -2
  74. package/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
  75. package/node_modules/undici/lib/dispatcher/client-h2.js +70 -14
  76. package/node_modules/undici/lib/dispatcher/client.js +6 -2
  77. package/node_modules/undici/lib/handler/cache-handler.js +21 -5
  78. package/node_modules/undici/lib/handler/retry-handler.js +42 -7
  79. package/node_modules/undici/lib/interceptor/cache.js +20 -1
  80. package/node_modules/undici/lib/interceptor/decompress.js +146 -14
  81. package/node_modules/undici/lib/interceptor/dump.js +10 -23
  82. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +245 -150
  83. package/node_modules/undici/lib/web/websocket/connection.js +1 -1
  84. package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
  85. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
  86. package/node_modules/undici/package.json +1 -1
  87. package/node_modules/undici/types/interceptors.d.ts +2 -0
  88. package/openclaw.plugin.json +17 -9
  89. package/package.json +6 -6
  90. package/skills/_vendor/slack-skills-plugin.LICENSE +21 -0
  91. package/skills/_vendor/slack-skills-plugin.json +31 -0
  92. package/skills/block-kit/SKILL.md +37 -0
  93. package/skills/block-kit/references/official-block-kit.md +257 -0
  94. package/skills/block-kit/references/official-common-patterns.md +385 -0
  95. package/skills/slack/SKILL.md +1 -1
  96. package/dist/action-runtime.runtime-Dpa16J87.js +0 -2
  97. package/dist/conversation-binding-route-DFVLUdYF.js +0 -115
  98. package/dist/slack-client-kind-hSfjXyUM.js +0 -94
  99. package/node_modules/@slack/bolt/node_modules/negotiator/HISTORY.md +0 -114
@@ -0,0 +1,790 @@
1
+ import { B as SLACK_REPLY_LINK_ACTION_ID, C as buildSlackBlocksFallbackText, F as SLACK_CALLBACK_BUTTON_ACTION_ID, I as SLACK_CALLBACK_SELECT_ACTION_ID, J as markdownToSlackMrkdwnChunks, L as SLACK_QUESTION_BUTTON_ACTION_ID, N as SLACK_APPROVAL_BUTTON_ACTION_ID, P as SLACK_APPROVAL_SELECT_ACTION_ID, Q as hasSlackDataVisualizationBlock, T as renderSlackBlockFallbackText, V as SLACK_REPLY_SELECT_ACTION_ID, X as buildSlackDataVisualizationBlock, Z as canRenderSlackDataVisualization, et as buildSlackDataTableBlock, g as buildSlackNativeDataAccessibilityText, it as renderSlackMessagePresentationFallbackText, j as truncateSlackText, m as appendSlackNativeDataFallbackText, nt as countSlackDataTableCellCharacters, q as chunkSlackMrkdwnText, rt as renderSlackMessagePresentationChartFallbackText, st as parseSlackBlocksInput, tt as countSlackDataTableBlocksCellCharacters, v as hasSlackNativeDataBlock, z as SLACK_REPLY_BUTTON_ACTION_ID } from "./session-status-BynwcZSO.js";
2
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
4
+ import { legacyInteractiveReplyToPresentation, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
5
+ import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
6
+ import { resolveAskUserQuestionOptionIndex, resolveAskUserQuestionOptionIndices } from "openclaw/plugin-sdk/reply-payload";
7
+ import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
8
+ import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
9
+ const SLACK_BUTTON_VALUE_MAX = 2e3;
10
+ const SLACK_SECTION_TEXT_MAX = 3e3;
11
+ const SLACK_PRESENTATION_CAPABILITIES = {
12
+ supported: true,
13
+ buttons: true,
14
+ selects: true,
15
+ context: true,
16
+ divider: true,
17
+ charts: true,
18
+ tables: true,
19
+ limits: {
20
+ actions: {
21
+ maxActionsPerRow: 25,
22
+ maxValueBytes: SLACK_BUTTON_VALUE_MAX,
23
+ supportsStyles: true
24
+ },
25
+ selects: {
26
+ maxOptions: 100,
27
+ maxValueBytes: 150
28
+ },
29
+ text: {
30
+ encoding: "characters",
31
+ markdownDialect: "slack-mrkdwn",
32
+ supportsEdit: true
33
+ }
34
+ }
35
+ };
36
+ //#endregion
37
+ //#region extensions/slack/src/approval-actions.ts
38
+ const SLACK_APPROVAL_VALUE_PREFIX = "openclaw:approval:v1:";
39
+ const SLACK_APPROVAL_HEADER_BLOCK_ID = "openclaw_approval_header";
40
+ function isApprovalDecision(value) {
41
+ return value === "allow-once" || value === "allow-always" || value === "deny";
42
+ }
43
+ /** Encode portable approval facts without exposing a slash command to Slack callbacks. */
44
+ function encodeSlackApprovalAction(action) {
45
+ const encode = (approvalId) => `${SLACK_APPROVAL_VALUE_PREFIX}${JSON.stringify({
46
+ approvalId,
47
+ approvalKind: action.approvalKind,
48
+ decision: action.decision
49
+ })}`;
50
+ const exact = encode(action.approvalId);
51
+ return exact.length <= 2e3 ? exact : encode(buildApprovalResolutionRef({
52
+ approvalId: action.approvalId,
53
+ approvalKind: action.approvalKind
54
+ }));
55
+ }
56
+ /** Decode only the exact Slack-owned approval envelope. Malformed callbacks fail closed. */
57
+ function decodeSlackApprovalAction(value) {
58
+ if (typeof value !== "string" || !value.startsWith(SLACK_APPROVAL_VALUE_PREFIX)) return null;
59
+ try {
60
+ const decoded = JSON.parse(value.slice(21));
61
+ if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return null;
62
+ const record = decoded;
63
+ if (Object.keys(record).length !== 3 || typeof record.approvalId !== "string" || record.approvalId.length === 0 || record.approvalKind !== "exec" && record.approvalKind !== "plugin" || !isApprovalDecision(record.decision)) return null;
64
+ return {
65
+ type: "approval",
66
+ approvalId: record.approvalId,
67
+ approvalKind: record.approvalKind,
68
+ decision: record.decision
69
+ };
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ //#endregion
75
+ //#region extensions/slack/src/question-actions.ts
76
+ const SLACK_QUESTION_VALUE_PREFIX = "slq1:";
77
+ const QUESTION_RECORD_ID_PATTERN = /^ask_[a-f0-9]{32}$/u;
78
+ function encodeSlackQuestionAction(action) {
79
+ if (!QUESTION_RECORD_ID_PATTERN.test(action.questionId) || !Number.isInteger(action.optionIndex) || action.optionIndex < 0 || action.optionIndex > 3) return;
80
+ const value = `${SLACK_QUESTION_VALUE_PREFIX}${action.questionId}:${action.optionIndex}`;
81
+ return value.length <= 2e3 ? value : void 0;
82
+ }
83
+ function decodeSlackQuestionAction(value) {
84
+ if (typeof value !== "string" || value.length > 2e3) return null;
85
+ const match = /^slq1:(ask_[a-f0-9]{32}):([0-3])$/u.exec(value);
86
+ return match?.[1] && match[2] ? {
87
+ questionId: match[1],
88
+ optionIndex: Number(match[2])
89
+ } : null;
90
+ }
91
+ async function resolveSlackQuestionAction(params) {
92
+ let result;
93
+ try {
94
+ result = await (params.resolveQuestion ?? questionGatewayRuntime.resolveOption)({
95
+ cfg: params.cfg,
96
+ questionId: params.action.questionId,
97
+ optionIndex: params.action.optionIndex,
98
+ senderId: params.userId,
99
+ clientDisplayName: `Slack question (${params.accountId})`
100
+ });
101
+ } catch {
102
+ await params.respond("Could not submit this answer.").catch(() => {});
103
+ return;
104
+ }
105
+ await params.respond(result.status === "answered" ? "Answer submitted." : "This question was already answered.").catch(() => {});
106
+ }
107
+ //#endregion
108
+ //#region extensions/slack/src/blocks-render.ts
109
+ const SLACK_BUTTON_URL_MAX = 3e3;
110
+ function buildSlackReplyButtonActionId(buttonIndex, choiceIndex) {
111
+ return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
112
+ }
113
+ function buildSlackReplyLinkActionId(buttonIndex, choiceIndex) {
114
+ return `${SLACK_REPLY_LINK_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
115
+ }
116
+ function buildSlackReplySelectActionId(selectIndex) {
117
+ return `${SLACK_REPLY_SELECT_ACTION_ID}:${String(selectIndex)}`;
118
+ }
119
+ function buildSlackApprovalButtonActionId(buttonIndex, choiceIndex) {
120
+ return `${SLACK_APPROVAL_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
121
+ }
122
+ function buildSlackApprovalSelectActionId(selectIndex) {
123
+ return `${SLACK_APPROVAL_SELECT_ACTION_ID}:${String(selectIndex)}`;
124
+ }
125
+ function buildSlackCallbackButtonActionId(buttonIndex, choiceIndex) {
126
+ return `${SLACK_CALLBACK_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
127
+ }
128
+ function buildSlackCallbackSelectActionId(selectIndex) {
129
+ return `${SLACK_CALLBACK_SELECT_ACTION_ID}:${String(selectIndex)}`;
130
+ }
131
+ function buildSlackQuestionButtonActionId(buttonIndex, choiceIndex) {
132
+ return `${SLACK_QUESTION_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
133
+ }
134
+ function resolveSlackButtonStyle(style) {
135
+ if (style === "primary" || style === "danger") return style;
136
+ if (style === "success") return "primary";
137
+ }
138
+ function resolveSlackActionTarget(action, questionOptionIndices) {
139
+ if (!action) return;
140
+ if (action.type === "approval") return {
141
+ kind: "approval",
142
+ value: encodeSlackApprovalAction(action)
143
+ };
144
+ if (action.type === "question") {
145
+ if ("intent" in action) return;
146
+ const optionIndex = resolveAskUserQuestionOptionIndex({
147
+ questionOptionIndices,
148
+ questionId: action.questionId,
149
+ optionValue: action.optionValue
150
+ });
151
+ const value = optionIndex === void 0 ? void 0 : encodeSlackQuestionAction({
152
+ questionId: action.questionId,
153
+ optionIndex
154
+ });
155
+ return value ? {
156
+ kind: "question",
157
+ value
158
+ } : void 0;
159
+ }
160
+ if (action.type === "url" || action.type === "web-app") {
161
+ const url = normalizeOptionalString(action.url);
162
+ return url ? {
163
+ kind: "link",
164
+ url
165
+ } : void 0;
166
+ }
167
+ if (action.type === "callback") {
168
+ const value = normalizeOptionalString(action.value);
169
+ return value ? {
170
+ kind: "callback",
171
+ value
172
+ } : void 0;
173
+ }
174
+ const command = normalizeOptionalString(action.command);
175
+ return command && parseExecApprovalCommandText(command) ? {
176
+ kind: "reply",
177
+ value: command
178
+ } : void 0;
179
+ }
180
+ function resolveSlackButtonTarget(button, questionOptionIndices) {
181
+ if (button.action !== void 0) {
182
+ const action = resolveMessagePresentationButtonAction(button);
183
+ return action ? resolveSlackActionTarget(action, questionOptionIndices) : void 0;
184
+ }
185
+ const legacyUrl = normalizeOptionalString(button.url ?? button.webApp?.url ?? button.web_app?.url);
186
+ if (legacyUrl && isWithinSlackLimit(legacyUrl, SLACK_BUTTON_URL_MAX)) return {
187
+ kind: "link",
188
+ url: legacyUrl
189
+ };
190
+ const legacyValue = normalizeOptionalString(button.value);
191
+ if (legacyValue) return {
192
+ kind: "reply",
193
+ value: legacyValue
194
+ };
195
+ return legacyUrl ? {
196
+ kind: "link",
197
+ url: legacyUrl
198
+ } : void 0;
199
+ }
200
+ function isSlackTextFallbackButton(button) {
201
+ const action = resolveMessagePresentationButtonAction(button);
202
+ return action?.type === "question" && "intent" in action && action.intent === "custom-input";
203
+ }
204
+ function resolveSlackOptionTarget(option) {
205
+ if (option.action !== void 0) {
206
+ const action = resolveMessagePresentationOptionAction(option);
207
+ const target = action ? resolveSlackActionTarget(action) : void 0;
208
+ return target?.kind === "link" || target?.kind === "question" ? void 0 : target;
209
+ }
210
+ const value = normalizeOptionalString(option.value);
211
+ return value ? {
212
+ kind: "reply",
213
+ value
214
+ } : void 0;
215
+ }
216
+ function isWithinSlackLimit(value, maxLength) {
217
+ return value.length <= maxLength;
218
+ }
219
+ function isRenderableSlackOption(option) {
220
+ return isWithinSlackLimit(option.value, 150);
221
+ }
222
+ function readSlackBlockId(block) {
223
+ const value = block.block_id;
224
+ return typeof value === "string" ? value : void 0;
225
+ }
226
+ function readSlackOpenClawBlockIndex(blockId, prefix) {
227
+ if (!blockId.startsWith(prefix)) return;
228
+ const value = Number.parseInt(blockId.slice(prefix.length), 10);
229
+ return Number.isSafeInteger(value) && value > 0 ? value : void 0;
230
+ }
231
+ /** Resolve existing Block Kit indexes and native-data budgets before appending portable blocks. */
232
+ function resolveSlackBlockOffsets(blocks) {
233
+ let buttonIndexOffset = 0;
234
+ const dataTableCellCharacterCountOffset = countSlackDataTableBlocksCellCharacters(blocks) ?? 10001;
235
+ let dataVisualizationCountOffset = 0;
236
+ let selectIndexOffset = 0;
237
+ for (const block of blocks ?? []) {
238
+ if (hasSlackDataVisualizationBlock([block])) dataVisualizationCountOffset += 1;
239
+ const blockId = readSlackBlockId(block);
240
+ if (!blockId) continue;
241
+ buttonIndexOffset = Math.max(buttonIndexOffset, readSlackOpenClawBlockIndex(blockId, "openclaw_reply_buttons_") ?? 0);
242
+ selectIndexOffset = Math.max(selectIndexOffset, readSlackOpenClawBlockIndex(blockId, "openclaw_reply_select_") ?? 0);
243
+ }
244
+ return {
245
+ buttonIndexOffset,
246
+ dataTableCellCharacterCountOffset,
247
+ dataVisualizationCountOffset,
248
+ selectIndexOffset
249
+ };
250
+ }
251
+ /**
252
+ * @deprecated Use buildSlackPresentationBlocks with MessagePresentation.
253
+ */
254
+ function buildSlackInteractiveBlocks(interactive, options = {}) {
255
+ return buildSlackPresentationBlocks(interactive ? legacyInteractiveReplyToPresentation(interactive) : void 0, options);
256
+ }
257
+ /** Render portable presentation blocks as Slack Block Kit blocks. */
258
+ function buildSlackPresentationBlocks(presentation, options = {}) {
259
+ if (!presentation) return [];
260
+ const renderTablesNatively = canRenderSlackPresentationTables(presentation, options);
261
+ const blocks = [];
262
+ if (presentation.title) blocks.push({
263
+ type: "header",
264
+ text: {
265
+ type: "plain_text",
266
+ text: truncateSlackText(presentation.title, 150),
267
+ emoji: true
268
+ }
269
+ });
270
+ let buttonIndex = options.buttonIndexOffset ?? 0;
271
+ let dataTableCellCharacterCount = options.dataTableCellCharacterCountOffset ?? 0;
272
+ let dataVisualizationCount = options.dataVisualizationCountOffset ?? 0;
273
+ let selectIndex = options.selectIndexOffset ?? 0;
274
+ for (const block of presentation.blocks) {
275
+ if (block.type === "text" || block.type === "context") {
276
+ const text = block.text.trim();
277
+ if (!text) continue;
278
+ for (const chunk of chunkSlackMrkdwnText(text, SLACK_SECTION_TEXT_MAX)) blocks.push(block.type === "context" ? {
279
+ type: "context",
280
+ elements: [{
281
+ type: "mrkdwn",
282
+ text: chunk,
283
+ verbatim: true
284
+ }]
285
+ } : {
286
+ type: "section",
287
+ text: {
288
+ type: "mrkdwn",
289
+ text: chunk
290
+ }
291
+ });
292
+ continue;
293
+ }
294
+ if (block.type === "divider") {
295
+ blocks.push({ type: "divider" });
296
+ continue;
297
+ }
298
+ if (block.type === "buttons") {
299
+ const rendered = buildSlackPresentationButtonBlock(block, buttonIndex + 1, options.questionOptionIndices);
300
+ if (rendered) {
301
+ buttonIndex += 1;
302
+ blocks.push(rendered);
303
+ }
304
+ continue;
305
+ }
306
+ if (block.type === "chart") {
307
+ const rendered = dataVisualizationCount < 2 ? buildSlackPresentationChartBlock(block) : void 0;
308
+ if (rendered) {
309
+ dataVisualizationCount += 1;
310
+ blocks.push(rendered);
311
+ } else {
312
+ const fallback = renderSlackMessagePresentationChartFallbackText(block);
313
+ blocks.push(...chunkTextForOutbound(fallback, SLACK_SECTION_TEXT_MAX).map((text) => ({
314
+ type: "context",
315
+ elements: [{
316
+ type: "mrkdwn",
317
+ text,
318
+ verbatim: true
319
+ }]
320
+ })));
321
+ }
322
+ continue;
323
+ }
324
+ if (block.type === "table") {
325
+ if (!renderTablesNatively) continue;
326
+ const rendered = buildSlackDataTableBlock(block, { cellCharacterCountOffset: dataTableCellCharacterCount });
327
+ if (rendered) {
328
+ dataTableCellCharacterCount += countSlackDataTableCellCharacters(rendered);
329
+ blocks.push(rendered);
330
+ }
331
+ continue;
332
+ }
333
+ if (block.type === "select") {
334
+ const rendered = buildSlackPresentationSelectBlock(block, selectIndex + 1);
335
+ if (rendered) {
336
+ selectIndex += 1;
337
+ blocks.push(rendered);
338
+ }
339
+ }
340
+ }
341
+ return blocks;
342
+ }
343
+ function buildSlackPresentationChartBlock(block) {
344
+ return buildSlackDataVisualizationBlock(block);
345
+ }
346
+ function buildSlackPresentationButtonBlock(block, buttonIndex, questionOptionIndices) {
347
+ const elements = block.buttons.flatMap((button, choiceIndex) => {
348
+ const target = resolveSlackButtonTarget(button, questionOptionIndices);
349
+ if (!target || (target.kind === "link" ? !isWithinSlackLimit(target.url, SLACK_BUTTON_URL_MAX) : !isWithinSlackLimit(target.value, 2e3))) return [];
350
+ const style = resolveSlackButtonStyle(button.style);
351
+ return [{
352
+ type: "button",
353
+ action_id: target.kind === "link" ? buildSlackReplyLinkActionId(buttonIndex, choiceIndex) : target.kind === "approval" ? buildSlackApprovalButtonActionId(buttonIndex, choiceIndex) : target.kind === "callback" ? buildSlackCallbackButtonActionId(buttonIndex, choiceIndex) : target.kind === "question" ? buildSlackQuestionButtonActionId(buttonIndex, choiceIndex) : buildSlackReplyButtonActionId(buttonIndex, choiceIndex),
354
+ text: {
355
+ type: "plain_text",
356
+ text: truncateSlackText(button.label, 75),
357
+ emoji: true
358
+ },
359
+ ...target.kind === "link" ? { url: target.url } : { value: target.value },
360
+ ...style ? { style } : {}
361
+ }];
362
+ }).slice(0, 25);
363
+ return elements.length > 0 ? {
364
+ type: "actions",
365
+ block_id: `openclaw_reply_buttons_${buttonIndex}`,
366
+ elements
367
+ } : void 0;
368
+ }
369
+ /** True when every portable table fits Slack's native per-message table budget. */
370
+ function canRenderSlackPresentationTables(presentation, options = {}) {
371
+ let cellCharacterCount = options.dataTableCellCharacterCountOffset ?? 0;
372
+ for (const block of presentation.blocks) {
373
+ if (block.type !== "table") continue;
374
+ const rendered = buildSlackDataTableBlock(block, { cellCharacterCountOffset: cellCharacterCount });
375
+ if (!rendered) return false;
376
+ cellCharacterCount += countSlackDataTableCellCharacters(rendered);
377
+ }
378
+ return true;
379
+ }
380
+ /** True when native Slack rendering preserves every portable control. */
381
+ function canRenderSlackPresentation(presentation, options = {}) {
382
+ if (presentation.title && !isWithinSlackLimit(presentation.title.trim(), 150)) return false;
383
+ if (!canRenderSlackPresentationTables(presentation, options)) return false;
384
+ let dataVisualizationCount = options.dataVisualizationCountOffset ?? 0;
385
+ for (const block of presentation.blocks) {
386
+ if (block.type === "text" || block.type === "context") continue;
387
+ if (block.type === "buttons") {
388
+ let nativeButtonCount = 0;
389
+ if (!(block.buttons.every((button) => {
390
+ if (isSlackTextFallbackButton(button)) return true;
391
+ nativeButtonCount += 1;
392
+ if (!isWithinSlackLimit(button.label, 75)) return false;
393
+ const target = resolveSlackButtonTarget(button, options.questionOptionIndices);
394
+ return target ? target.kind === "link" ? isWithinSlackLimit(target.url, SLACK_BUTTON_URL_MAX) : isWithinSlackLimit(target.value, 2e3) : false;
395
+ }) && nativeButtonCount <= 25)) return false;
396
+ continue;
397
+ }
398
+ if (block.type === "select") {
399
+ if (!(isWithinSlackLimit(normalizeOptionalString(block.placeholder) ?? "Choose an option", 75) && block.options.length <= 100 && (!block.placeholder || isWithinSlackLimit(block.placeholder, 75)) && block.options.every((option) => {
400
+ if (!isWithinSlackLimit(option.label, 75)) return false;
401
+ const target = resolveSlackOptionTarget(option);
402
+ return target ? isRenderableSlackOption({
403
+ label: option.label,
404
+ ...target
405
+ }) : false;
406
+ }) && new Set(block.options.map((option) => resolveSlackOptionTarget(option)?.kind)).size === 1)) return false;
407
+ continue;
408
+ }
409
+ if (block.type === "chart") {
410
+ if (dataVisualizationCount >= 2 || !canRenderSlackDataVisualization(block)) return false;
411
+ dataVisualizationCount += 1;
412
+ continue;
413
+ }
414
+ if (block.type === "table") continue;
415
+ }
416
+ return true;
417
+ }
418
+ function buildSlackPresentationSelectBlock(block, selectIndex) {
419
+ const options = block.options.flatMap((option) => {
420
+ const target = resolveSlackOptionTarget(option);
421
+ return target ? [{
422
+ label: option.label,
423
+ ...target
424
+ }] : [];
425
+ }).filter(isRenderableSlackOption).slice(0, 100);
426
+ const optionKinds = new Set(options.map((option) => option.kind));
427
+ return options.length > 0 && optionKinds.size === 1 ? {
428
+ type: "actions",
429
+ block_id: `openclaw_reply_select_${selectIndex}`,
430
+ elements: [{
431
+ type: "static_select",
432
+ action_id: options[0]?.kind === "approval" ? buildSlackApprovalSelectActionId(selectIndex) : options[0]?.kind === "callback" ? buildSlackCallbackSelectActionId(selectIndex) : buildSlackReplySelectActionId(selectIndex),
433
+ placeholder: {
434
+ type: "plain_text",
435
+ text: truncateSlackText(normalizeOptionalString(block.placeholder) ?? "Choose an option", 75),
436
+ emoji: true
437
+ },
438
+ options: options.map((option) => ({
439
+ text: {
440
+ type: "plain_text",
441
+ text: truncateSlackText(option.label, 75),
442
+ emoji: true
443
+ },
444
+ value: option.value
445
+ }))
446
+ }]
447
+ } : void 0;
448
+ }
449
+ //#endregion
450
+ //#region extensions/slack/src/authored-text.ts
451
+ function normalizeComparableSlackText(text) {
452
+ return text.trim().replace(/\s+/g, " ");
453
+ }
454
+ function isSlackAuthoredTextRepresentedInInteractive(text, interactive) {
455
+ return isSlackAuthoredTextRepresentedInFragments(text, interactive?.blocks.flatMap((block) => block.type === "text" ? [block.text] : []) ?? []);
456
+ }
457
+ function isSlackAuthoredTextRepresentedInFragments(text, rawFragments) {
458
+ const target = normalizeComparableSlackText(text);
459
+ const fragments = rawFragments.map(normalizeComparableSlackText).filter(Boolean);
460
+ for (let start = 0; start < fragments.length; start += 1) {
461
+ let combined = "";
462
+ for (let end = start; end < fragments.length; end += 1) {
463
+ combined = normalizeComparableSlackText(`${combined} ${fragments[end]}`);
464
+ if (combined === target) return true;
465
+ if (combined.length > target.length) break;
466
+ }
467
+ }
468
+ return false;
469
+ }
470
+ /** Resolve placement from producer facts, before accessibility text changes the payload text. */
471
+ function resolveSlackAuthoredTextPlacement(params) {
472
+ const text = normalizeOptionalString(params.text);
473
+ if (!text) return "none";
474
+ return params.renderedInBlocks || isSlackAuthoredTextRepresentedInFragments(text, params.renderedTextFragments ?? []) || isSlackAuthoredTextRepresentedInInteractive(text, params.interactive) ? "blocks" : "outside-blocks";
475
+ }
476
+ //#endregion
477
+ //#region extensions/slack/src/reply-blocks.ts
478
+ function parseSlackReplyBlockSegments(value) {
479
+ if (value === void 0) return;
480
+ if (!Array.isArray(value)) throw new Error("Slack rendered presentation segments must be an array");
481
+ return value.map((raw) => {
482
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("Slack rendered presentation segment must be an object");
483
+ const segment = raw;
484
+ if (segment.kind === "text" && typeof segment.text === "string" && segment.mrkdwn === false) return {
485
+ kind: "text",
486
+ text: segment.text,
487
+ mrkdwn: false
488
+ };
489
+ if (segment.kind === "blocks") {
490
+ const blocks = parseSlackBlocksInput(segment.blocks);
491
+ if (blocks?.length) return {
492
+ kind: "blocks",
493
+ blocks
494
+ };
495
+ }
496
+ throw new Error("Slack rendered presentation segment is invalid");
497
+ });
498
+ }
499
+ /** Convert compiled segments into ordered sender calls without re-inferring text placement. */
500
+ function resolveSlackReplyDeliveryMessages(params) {
501
+ const messages = [];
502
+ let outsideText = params.authoredTextPlacement === "outside-blocks" ? params.text?.trim() ?? "" : "";
503
+ for (const segment of params.segments) {
504
+ if (segment.kind === "text") {
505
+ const text = [outsideText, segment.text].filter(Boolean).join("\n\n");
506
+ outsideText = "";
507
+ if (text) messages.push({
508
+ text,
509
+ textIsSlackPlainText: true
510
+ });
511
+ continue;
512
+ }
513
+ const baseText = outsideText;
514
+ outsideText = "";
515
+ const text = buildSlackNativeDataAccessibilityText(baseText, segment.blocks) || buildSlackBlocksFallbackText(segment.blocks);
516
+ const authoredTextPlacement = baseText ? "outside-blocks" : params.authoredTextPlacement === "blocks" ? "blocks" : "none";
517
+ messages.push({
518
+ text,
519
+ blocks: segment.blocks,
520
+ authoredTextPlacement,
521
+ ...baseText ? { nativeDataFallbackBaseText: baseText } : {}
522
+ });
523
+ }
524
+ if (outsideText) messages.push({
525
+ text: outsideText,
526
+ authoredTextPlacement: "outside-blocks"
527
+ });
528
+ return messages;
529
+ }
530
+ function resolveSlackReplyText(payload, text = payload.text) {
531
+ const presentation = normalizeMessagePresentation(payload.presentation);
532
+ return presentation ? renderSlackMessagePresentationFallbackText({
533
+ text,
534
+ presentation
535
+ }) : text ?? "";
536
+ }
537
+ function resolveSlackReplyRenderPlan(payload, text = payload.text) {
538
+ const hasStructuredContent = hasSlackReplyStructuredContent(payload);
539
+ const resolution = resolveSlackReplyBlockResolution({
540
+ ...payload,
541
+ text
542
+ }, { materializeAuthoredText: hasStructuredContent });
543
+ const messages = resolveSlackReplyDeliveryMessages({
544
+ authoredTextPlacement: resolution.authoredTextPlacement,
545
+ segments: resolution.segments,
546
+ text
547
+ });
548
+ if (messages.length <= 1) {
549
+ const [message] = messages;
550
+ const sourceText = text?.trim() ?? "";
551
+ const blocks = message?.authoredTextPlacement === "blocks" ? addPreviewVerbatimToAuthoredTextBlocks(message.blocks, sourceText) : message?.blocks;
552
+ let renderedText = message?.text ?? resolveSlackReplyText(payload, text);
553
+ let textIsSlackMrkdwn = Boolean(message && !message.textIsSlackPlainText && (message.authoredTextPlacement !== "outside-blocks" || message.nativeDataFallbackBaseText));
554
+ if (blocks?.length && sourceText) {
555
+ if (hasSlackNativeDataBlock(blocks)) {
556
+ renderedText = appendSlackNativeDataFallbackText(sourceText, blocks) || renderedText;
557
+ textIsSlackMrkdwn = true;
558
+ } else if (message?.authoredTextPlacement === "blocks") {
559
+ renderedText = sourceText;
560
+ textIsSlackMrkdwn = false;
561
+ }
562
+ }
563
+ return {
564
+ mode: "single",
565
+ text: renderedText,
566
+ ...blocks ? { blocks } : {},
567
+ ...textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {}
568
+ };
569
+ }
570
+ const blockPart = messages.find((message) => message.blocks?.length);
571
+ return {
572
+ mode: "split",
573
+ fallbackText: messages.map((message) => message.text).filter(Boolean).join("\n\n"),
574
+ ...blockPart ? { blockPart: {
575
+ text: blockPart.text,
576
+ blocks: blockPart.blocks
577
+ } } : {}
578
+ };
579
+ }
580
+ function readSlackChannelBlocks(payload) {
581
+ const slackData = payload.channelData?.slack;
582
+ if (!slackData || typeof slackData !== "object" || Array.isArray(slackData)) return [];
583
+ return parseSlackBlocksInput(slackData.blocks) ?? [];
584
+ }
585
+ function hasSlackReplyStructuredContent(payload) {
586
+ return Boolean(readSlackChannelBlocks(payload).length || normalizeMessagePresentation(payload.presentation) || payload.interactive?.blocks.length);
587
+ }
588
+ function renderSlackAuthoredTextFragments(blocks) {
589
+ return blocks.flatMap((block) => {
590
+ if (block.type === "actions") return [];
591
+ const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
592
+ return text ? [text] : [];
593
+ });
594
+ }
595
+ function buildSlackAuthoredTextBlocks(text) {
596
+ return markdownToSlackMrkdwnChunks(text, SLACK_SECTION_TEXT_MAX).map((chunk) => ({
597
+ type: "section",
598
+ text: {
599
+ type: "mrkdwn",
600
+ text: chunk,
601
+ verbatim: true
602
+ }
603
+ }));
604
+ }
605
+ function addPreviewVerbatimToAuthoredTextBlocks(blocks, sourceText) {
606
+ if (!blocks?.length || !sourceText) return blocks;
607
+ const authoredChunks = new Set(markdownToSlackMrkdwnChunks(sourceText, SLACK_SECTION_TEXT_MAX));
608
+ return blocks.map((block) => {
609
+ const text = block.text;
610
+ if (block.type !== "section" || text?.type !== "mrkdwn" || typeof text.text !== "string" || !authoredChunks.has(text.text)) return block;
611
+ return {
612
+ ...block,
613
+ text: {
614
+ ...text,
615
+ verbatim: true
616
+ }
617
+ };
618
+ });
619
+ }
620
+ function readLastBlockSegment(segments) {
621
+ const last = segments.at(-1);
622
+ return last?.kind === "blocks" ? last.blocks : [];
623
+ }
624
+ function readAllNativeBlocks(segments) {
625
+ return segments.flatMap((segment) => segment.kind === "blocks" ? segment.blocks : []);
626
+ }
627
+ function appendTextSegment(segments, text) {
628
+ const trimmed = text.trim();
629
+ if (!trimmed) return;
630
+ const last = segments.at(-1);
631
+ if (last?.kind === "text") {
632
+ last.text = `${last.text}\n\n${trimmed}`;
633
+ return;
634
+ }
635
+ segments.push({
636
+ kind: "text",
637
+ text: trimmed,
638
+ mrkdwn: false
639
+ });
640
+ }
641
+ function appendBlockSegment(segments, blocks, startNew = false) {
642
+ let shouldStartNew = startNew;
643
+ for (const block of blocks) {
644
+ const last = segments.at(-1);
645
+ if (!shouldStartNew && last?.kind === "blocks" && last.blocks.length < 50) last.blocks.push(block);
646
+ else segments.push({
647
+ kind: "blocks",
648
+ blocks: [block]
649
+ });
650
+ shouldStartNew = false;
651
+ }
652
+ }
653
+ function resolvePresentationRenderOptions(segments, mode) {
654
+ const allOffsets = resolveSlackBlockOffsets(readAllNativeBlocks(segments));
655
+ return {
656
+ ...mode === "current" ? resolveSlackBlockOffsets(readLastBlockSegment(segments)) : {},
657
+ buttonIndexOffset: allOffsets.buttonIndexOffset,
658
+ selectIndexOffset: allOffsets.selectIndexOffset
659
+ };
660
+ }
661
+ function renderNativePresentation(presentation, options) {
662
+ if (!canRenderSlackPresentation(presentation, options)) return;
663
+ const blocks = buildSlackPresentationBlocks(presentation, options);
664
+ return blocks.length > 0 ? blocks : void 0;
665
+ }
666
+ function appendPresentationPart(segments, presentation, questionOptionIndices) {
667
+ const currentBlocks = readLastBlockSegment(segments);
668
+ const currentRendered = renderNativePresentation(presentation, {
669
+ ...resolvePresentationRenderOptions(segments, "current"),
670
+ questionOptionIndices
671
+ });
672
+ if (currentRendered && currentBlocks.length + currentRendered.length <= 50) {
673
+ appendBlockSegment(segments, currentRendered);
674
+ return;
675
+ }
676
+ const freshRendered = renderNativePresentation(presentation, {
677
+ ...resolvePresentationRenderOptions(segments, "new-message"),
678
+ questionOptionIndices
679
+ });
680
+ if (freshRendered) {
681
+ appendBlockSegment(segments, freshRendered, true);
682
+ return;
683
+ }
684
+ appendTextSegment(segments, renderMessagePresentationFallbackText({ presentation }));
685
+ }
686
+ const SLACK_BUTTON_CONTROL_ACTION_IDS = [
687
+ SLACK_APPROVAL_BUTTON_ACTION_ID,
688
+ SLACK_CALLBACK_BUTTON_ACTION_ID,
689
+ SLACK_QUESTION_BUTTON_ACTION_ID,
690
+ SLACK_REPLY_BUTTON_ACTION_ID,
691
+ SLACK_REPLY_LINK_ACTION_ID
692
+ ];
693
+ const SLACK_SELECT_CONTROL_ACTION_IDS = [
694
+ SLACK_APPROVAL_SELECT_ACTION_ID,
695
+ SLACK_CALLBACK_SELECT_ACTION_ID,
696
+ SLACK_REPLY_SELECT_ACTION_ID
697
+ ];
698
+ function readGeneratedSlackControlRowKey(block) {
699
+ const record = block;
700
+ if (record.type !== "actions" || typeof record.block_id !== "string") return;
701
+ const expectedElementType = /^openclaw_reply_buttons_[1-9]\d*$/.test(record.block_id) ? "button" : /^openclaw_reply_select_[1-9]\d*$/.test(record.block_id) ? "static_select" : void 0;
702
+ if (!expectedElementType || !Array.isArray(record.elements) || record.elements.length === 0) return;
703
+ const actionIds = expectedElementType === "button" ? SLACK_BUTTON_CONTROL_ACTION_IDS : SLACK_SELECT_CONTROL_ACTION_IDS;
704
+ const elements = record.elements.map((element) => {
705
+ if (!element || typeof element !== "object" || Array.isArray(element)) return;
706
+ const { action_id: actionId, ...content } = element;
707
+ const actionFamily = typeof actionId === "string" ? actionIds.find((candidate) => actionId.startsWith(`${candidate}:`)) : void 0;
708
+ return actionFamily && content.type === expectedElementType ? [actionFamily, content] : void 0;
709
+ });
710
+ return elements.some((element) => element === void 0) ? void 0 : JSON.stringify(elements);
711
+ }
712
+ function subtractMirroredSlackControlRows(params) {
713
+ const remainingMirrors = /* @__PURE__ */ new Map();
714
+ for (const block of params.presentationBlocks) {
715
+ const key = readGeneratedSlackControlRowKey(block);
716
+ if (key) remainingMirrors.set(key, (remainingMirrors.get(key) ?? 0) + 1);
717
+ }
718
+ return params.interactiveBlocks.filter((block) => {
719
+ const key = readGeneratedSlackControlRowKey(block);
720
+ const remaining = key ? remainingMirrors.get(key) ?? 0 : 0;
721
+ if (!key || remaining === 0) return true;
722
+ remainingMirrors.set(key, remaining - 1);
723
+ return false;
724
+ });
725
+ }
726
+ /**
727
+ * Resolve reply content into transport-order segments. Each blocks segment is
728
+ * one Slack message; text segments carry complete fallback content between it.
729
+ */
730
+ function resolveSlackReplyBlockResolution(payload, options = {}) {
731
+ const segments = [];
732
+ const channelBlocks = readSlackChannelBlocks(payload);
733
+ let compiledChannelBlocks = channelBlocks;
734
+ let authoredTextKnownInBlocks = false;
735
+ if (options.materializeAuthoredText) {
736
+ const rawTextFragments = renderSlackAuthoredTextFragments(channelBlocks);
737
+ const initialPlacement = resolveSlackAuthoredTextPlacement({
738
+ text: payload.text,
739
+ interactive: payload.interactive,
740
+ renderedTextFragments: rawTextFragments
741
+ });
742
+ authoredTextKnownInBlocks = initialPlacement === "blocks";
743
+ const text = normalizeOptionalString(payload.text);
744
+ if (text && initialPlacement === "outside-blocks") {
745
+ const textBlocks = buildSlackAuthoredTextBlocks(text);
746
+ if (resolveSlackAuthoredTextPlacement({
747
+ text: renderSlackAuthoredTextFragments(textBlocks).join(" "),
748
+ renderedTextFragments: rawTextFragments
749
+ }) !== "blocks") compiledChannelBlocks = [...channelBlocks, ...textBlocks];
750
+ authoredTextKnownInBlocks = true;
751
+ }
752
+ }
753
+ if (compiledChannelBlocks.length > 0) appendBlockSegment(segments, compiledChannelBlocks);
754
+ const presentation = normalizeMessagePresentation(payload.presentation);
755
+ const questionOptionIndices = resolveAskUserQuestionOptionIndices(payload);
756
+ const presentationBlockOffset = readAllNativeBlocks(segments).length;
757
+ if (presentation?.title) appendPresentationPart(segments, {
758
+ title: presentation.title,
759
+ blocks: []
760
+ }, questionOptionIndices);
761
+ for (const block of presentation?.blocks ?? []) appendPresentationPart(segments, { blocks: [block] }, questionOptionIndices);
762
+ const renderedPresentationBlocks = readAllNativeBlocks(segments).slice(presentationBlockOffset);
763
+ appendBlockSegment(segments, subtractMirroredSlackControlRows({
764
+ interactiveBlocks: buildSlackInteractiveBlocks(payload.interactive, {
765
+ ...resolveSlackBlockOffsets(readAllNativeBlocks(segments)),
766
+ questionOptionIndices
767
+ }),
768
+ presentationBlocks: renderedPresentationBlocks
769
+ }));
770
+ const renderedTextFragments = segments.flatMap((segment) => {
771
+ if (segment.kind === "text") return [segment.text];
772
+ return renderSlackAuthoredTextFragments(segment.blocks);
773
+ });
774
+ const authoredTextPlacement = resolveSlackAuthoredTextPlacement({
775
+ text: payload.text,
776
+ interactive: payload.interactive,
777
+ renderedTextFragments
778
+ });
779
+ return {
780
+ authoredTextPlacement: authoredTextKnownInBlocks ? "blocks" : authoredTextPlacement,
781
+ segments
782
+ };
783
+ }
784
+ /** Return the single-message native shape when no ordered text fallback is required. */
785
+ function resolveSlackReplyBlocks(payload) {
786
+ const { segments } = resolveSlackReplyBlockResolution(payload);
787
+ return segments.length === 1 && segments[0]?.kind === "blocks" ? segments[0].blocks : void 0;
788
+ }
789
+ //#endregion
790
+ export { resolveSlackReplyDeliveryMessages as a, buildSlackInteractiveBlocks as c, decodeSlackQuestionAction as d, resolveSlackQuestionAction as f, SLACK_SECTION_TEXT_MAX as g, SLACK_PRESENTATION_CAPABILITIES as h, resolveSlackReplyBlocks as i, buildSlackPresentationBlocks as l, decodeSlackApprovalAction as m, parseSlackReplyBlockSegments as n, resolveSlackReplyRenderPlan as o, SLACK_APPROVAL_HEADER_BLOCK_ID as p, resolveSlackReplyBlockResolution as r, resolveSlackAuthoredTextPlacement as s, hasSlackReplyStructuredContent as t, canRenderSlackPresentation as u };