@openclaw/slack 2026.11.3 → 2026.11.5-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 (220) hide show
  1. package/dist/.setup/{account-inspect-CmkKiSb9.mjs → account-inspect-BLVha-ov.mjs} +11 -8
  2. package/dist/.setup/{accounts-msihSF3-.mjs → accounts-CGJScKtk.mjs} +10 -1
  3. package/dist/.setup/{action-runtime-ChRfnnBu.mjs → action-runtime-D01wBhx5.mjs} +38 -45
  4. package/dist/.setup/action-runtime.runtime-VQGaR6g8.mjs +1 -0
  5. package/dist/.setup/{actions-By7tvpvv.mjs → actions-D5S6D_BU.mjs} +89 -76
  6. package/dist/.setup/{approval-handler.runtime-D8ArtDQt.mjs → approval-handler.runtime-Buw5jh2Y.mjs} +26 -30
  7. package/dist/.setup/{approval-message-updates-DT7XBPbV.mjs → approval-message-updates-pmXcve5E.mjs} +1 -1
  8. package/dist/.setup/{channel-DLFiMJm2.mjs → channel-C_R98Nbv.mjs} +569 -339
  9. package/dist/.setup/{channel-type-BEFP2ORi.mjs → channel-type-B5P3w9eA.mjs} +4 -8
  10. package/dist/.setup/{channel.setup-CzFw73mU.mjs → channel.setup-Lq2OxKkF.mjs} +13 -13
  11. package/dist/.setup/{config-schema-DNnh6bWU.mjs → config-schema-BWAaa5au.mjs} +3 -7
  12. package/dist/.setup/cursor-pages-CATAzbTT.mjs +313 -0
  13. package/dist/.setup/{directory-config-Cjj0N8R0.mjs → directory-config-D-hf9KGQ.mjs} +3 -3
  14. package/dist/.setup/{directory-live-BIKD-5B_.mjs → directory-live-onKAFI1E.mjs} +4 -4
  15. package/dist/.setup/{doctor-contract-Cd4-VzIM.mjs → doctor-contract-9-QJRCXk.mjs} +37 -45
  16. package/dist/.setup/{message-tool-api-BS5ekEA_.mjs → message-tool-api-LGIgVXJf.mjs} +4 -3
  17. package/dist/.setup/{monitor-CV6Z6FKP.mjs → monitor-Cm1TuqxN.mjs} +3424 -3703
  18. package/dist/.setup/{outbound-adapter-9dbnYtL1.mjs → outbound-adapter-C-95EWl2.mjs} +30 -36
  19. package/dist/.setup/paths-B1u59oLK.mjs +8 -0
  20. package/dist/.setup/{pipeline.runtime-DLIQf1Bo.mjs → pipeline.runtime-DGnV6akc.mjs} +416 -534
  21. package/dist/.setup/{policy-yhn48xf5.mjs → policy-DxhGRvc2.mjs} +1 -2
  22. package/dist/.setup/{session-status-Dv8wNBEt.mjs → probe-DANukR3O.mjs} +1206 -839
  23. package/dist/.setup/question-delivery-CWC7sRhH.mjs +39 -0
  24. package/dist/.setup/{relay-source-CxDcrn16.mjs → relay-source-DoyOlTbK.mjs} +5 -3
  25. package/dist/.setup/{replies-MRkrg3rC.mjs → replies-BcmUKord.mjs} +34 -19
  26. package/dist/.setup/{reply-blocks-Ca-raz2z.mjs → reply-blocks-BzsXUUUL.mjs} +201 -206
  27. package/dist/.setup/{resolve-channels-DRRhElwz.mjs → resolve-channels-XDPgnesf.mjs} +4 -7
  28. package/dist/.setup/{resolve-users-Cz8e17ky.mjs → resolve-users-aDAv24U2.mjs} +8 -16
  29. package/dist/.setup/runtime-setter-api-Cx_PV-xu.mjs +2 -0
  30. package/dist/.setup/{scopes-DfQVi8Jw.mjs → scopes-BocHwImV.mjs} +2 -1
  31. package/dist/.setup/secret-contract-api-BlLz88mj.mjs +2 -0
  32. package/dist/.setup/{secret-contract-vVRMoE1D.mjs → secret-contract-uiQtoNlu.mjs} +2 -2
  33. package/dist/.setup/{send-results-eeOu_HYm.mjs → send-results-BGxlroJ-.mjs} +3 -4
  34. package/dist/.setup/{send-C-8wY0lK.mjs → send-yK6_-px6.mjs} +297 -334
  35. package/dist/.setup/setup-plugin-api-Cfz58xoh.mjs +2 -0
  36. package/dist/.setup/{setup-surface--n8VsDvV.mjs → setup-surface-C0KRtyqa.mjs} +5 -6
  37. package/dist/.setup/{slash-dispatch.runtime-D3Wq45ER.mjs → slash-dispatch.runtime-CyVC3bYx.mjs} +2 -2
  38. package/dist/.setup/{target-parsing-FFE26kOV.mjs → target-parsing-Bx2UZniD.mjs} +1 -2
  39. package/dist/.setup/{targets-C6LZQL1Q.mjs → targets-D-ASeWHy.mjs} +1 -1
  40. package/dist/.source-module-urls/c5ffd0957b234c7c12090e7de4eca2482ef339b8561e078da55b734211b0ba58.json +1 -0
  41. package/dist/account-inspect-api.js +1 -1
  42. package/dist/api.js +16 -17
  43. package/dist/channel-config-api.js +1 -2
  44. package/dist/channel-plugin-api.js +1 -2
  45. package/dist/directory-contract-api.js +1 -2
  46. package/dist/doctor-contract-api.js +1 -2
  47. package/dist/index.js +0 -6
  48. package/dist/message-tool-api.js +1 -2
  49. package/dist/runtime-api.js +10 -12
  50. package/dist/runtime-setter-api.js +1 -2
  51. package/dist/secret-contract-api.js +1 -2
  52. package/dist/security-contract-api.js +1 -2
  53. package/dist/setup-entry.js +3 -3
  54. package/dist/setup-plugin-api.js +1 -2
  55. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  56. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  57. package/node_modules/@slack/bolt/node_modules/@types/node/util.d.ts +6 -3
  58. package/node_modules/@slack/bolt/node_modules/content-disposition/README.md +105 -35
  59. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.d.ts +72 -0
  60. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js +388 -0
  61. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js.map +1 -0
  62. package/node_modules/@slack/bolt/node_modules/content-disposition/package.json +31 -19
  63. package/node_modules/@slack/bolt/node_modules/content-type/README.md +34 -57
  64. package/node_modules/@slack/bolt/node_modules/content-type/package.json +35 -25
  65. package/node_modules/@slack/bolt/node_modules/express/Readme.md +15 -9
  66. package/node_modules/@slack/bolt/node_modules/express/lib/application.js +2 -2
  67. package/node_modules/@slack/bolt/node_modules/express/lib/request.js +32 -19
  68. package/node_modules/@slack/bolt/node_modules/express/lib/response.js +27 -30
  69. package/node_modules/@slack/bolt/node_modules/express/package.json +10 -10
  70. package/node_modules/@slack/bolt/node_modules/qs/.github/THREAT_MODEL.md +4 -2
  71. package/node_modules/@slack/bolt/node_modules/qs/CHANGELOG.md +38 -14
  72. package/node_modules/@slack/bolt/node_modules/qs/README.md +31 -3
  73. package/node_modules/@slack/bolt/node_modules/qs/dist/qs.js +20 -20
  74. package/node_modules/@slack/bolt/node_modules/qs/lib/parse.js +94 -4
  75. package/node_modules/@slack/bolt/node_modules/qs/lib/stringify.js +4 -4
  76. package/node_modules/@slack/bolt/node_modules/qs/lib/utils.js +130 -6
  77. package/node_modules/@slack/bolt/node_modules/qs/package.json +4 -4
  78. package/node_modules/@slack/bolt/node_modules/qs/test/parse.js +174 -0
  79. package/node_modules/@slack/bolt/node_modules/qs/test/stringify.js +263 -33
  80. package/node_modules/@slack/bolt/node_modules/qs/test/utils.js +184 -0
  81. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  82. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  83. package/node_modules/@slack/web-api/node_modules/@types/node/util.d.ts +6 -3
  84. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  85. package/node_modules/typebox/build/format/duration.mjs +2 -2
  86. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  87. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  88. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  89. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  90. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  91. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  92. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  93. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  94. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  95. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  96. package/node_modules/typebox/build/schema/build.mjs +1 -0
  97. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  98. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  99. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  100. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  101. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  102. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  103. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  104. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  105. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  106. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  107. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  108. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  109. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  110. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  111. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  112. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  113. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  114. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  115. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  116. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  117. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  118. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  119. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  120. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  121. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  122. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  123. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  124. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  125. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  126. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  127. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  128. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  129. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  130. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  131. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  132. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  133. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  134. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  135. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  136. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  137. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  138. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  139. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  140. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  141. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  142. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  143. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  144. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  145. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  146. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  147. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  148. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  149. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  150. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  151. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  152. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  153. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  154. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  155. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  156. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  157. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  158. package/node_modules/typebox/package.json +1 -1
  159. package/node_modules/typebox/readme.md +1 -1
  160. package/node_modules/undici/docs/docs/api/Interceptors.md +15 -2
  161. package/node_modules/undici/lib/dispatcher/client-h2.js +78 -3
  162. package/node_modules/undici/lib/dispatcher/pool-base.js +20 -3
  163. package/node_modules/undici/package.json +3 -3
  164. package/node_modules/undici/types/api.d.ts +1 -1
  165. package/node_modules/undici/types/utility.d.ts +4 -4
  166. package/node_modules/zod/package.json +1 -1
  167. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  168. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  169. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  170. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  171. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  172. package/node_modules/zod/src/v4/core/util.ts +13 -0
  173. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  174. package/node_modules/zod/v4/core/compile.cjs +8 -0
  175. package/node_modules/zod/v4/core/compile.js +8 -0
  176. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  177. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  178. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  179. package/node_modules/zod/v4/core/schemas.js +30 -0
  180. package/node_modules/zod/v4/core/util.cjs +15 -0
  181. package/node_modules/zod/v4/core/util.d.cts +2 -0
  182. package/node_modules/zod/v4/core/util.d.ts +2 -0
  183. package/node_modules/zod/v4/core/util.js +14 -0
  184. package/node_modules/zod/v4/core/versions.cjs +1 -1
  185. package/node_modules/zod/v4/core/versions.js +1 -1
  186. package/openclaw.plugin.json +6 -30
  187. package/package.json +7 -7
  188. package/dist/.setup/action-runtime.runtime-vLxx_7s2.mjs +0 -2
  189. package/dist/.setup/http-C9sM-FXe.mjs +0 -2
  190. package/dist/.setup/plugin-routes-D4qozHVn.mjs +0 -22
  191. package/dist/.setup/probe-IiHogLQN.mjs +0 -694
  192. package/dist/.setup/registry-DizWcnNp.mjs +0 -36
  193. package/dist/.setup/runtime-setter-api-CMFvhrAr.mjs +0 -3
  194. package/dist/.setup/secret-contract-api-DK9gZldc.mjs +0 -3
  195. package/dist/.setup/setup-plugin-api-BGD1TYnK.mjs +0 -3
  196. package/dist/.setup/shared-BhJHIZs1.mjs +0 -259
  197. package/dist/http-routes-api.js +0 -2
  198. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/LICENSE +0 -22
  199. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +0 -71
  200. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +0 -52
  201. package/node_modules/@slack/bolt/node_modules/content-disposition/index.js +0 -536
  202. package/node_modules/@slack/bolt/node_modules/content-type/HISTORY.md +0 -29
  203. package/node_modules/@slack/bolt/node_modules/content-type/index.js +0 -225
  204. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +0 -22
  205. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +0 -71
  206. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +0 -46
  207. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +0 -176
  208. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +0 -1
  209. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +0 -52
  210. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/LICENSE +0 -22
  211. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +0 -71
  212. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +0 -46
  213. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +0 -176
  214. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +0 -1
  215. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +0 -52
  216. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  217. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
  218. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.d.ts +0 -0
  219. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js +0 -0
  220. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js.map +0 -0
@@ -1,9 +1,36 @@
1
- import { $ as buildSlackDataVisualizationBlock, D as buildSlackCompleteBlocksFallbackText, E as buildSlackBlocksFallbackText, I as SLACK_BUTTON_ACTION_IDS, J as encodeSlackQuestionAction, O as renderSlackBlockFallbackText, P as truncateSlackText, V as SLACK_SELECT_ACTION_IDS, X as chunkSlackMrkdwnText, Z as markdownToSlackMrkdwnChunks, at as renderSlackMessagePresentationChartFallbackText, b as hasSlackNativeDataBlock, et as hasSlackDataVisualizationBlock, g as appendSlackNativeDataFallbackText, ht as parseSlackBlocksInput, it as countSlackDataTableCellCharacters, nt as buildSlackDataTableBlock, pt as SLACK_SECTION_TEXT_MAX, rt as countSlackDataTableBlocksCellCharacters, ut as encodeSlackApprovalAction, v as buildSlackNativeDataAccessibilityText } from "./session-status-Dv8wNBEt.mjs";
1
+ import { Ct as markdownToSlackMrkdwnChunks, E as buildSlackNativeDataAccessibilityText, F as truncateSlackText, H as SLACK_SELECT_ACTION_IDS, L as SLACK_BUTTON_ACTION_IDS, O as hasSlackNativeDataBlock, St as chunkSlackMrkdwnText, Tt as escapeSlackMrkdwn, X as encodeSlackQuestionAction, at as buildSlackCompleteBlocksFallbackText, ct as hasSlackDataVisualizationBlock, dt as countSlackDataTableBlocksCellCharacters, et as encodeSlackApprovalAction, ft as countSlackDataTableCellCharacters, gt as renderSlackMessagePresentationChartFallbackText, ht as SLACK_SECTION_TEXT_MAX, it as buildSlackBlocksFallbackText, nt as parseSlackBlocksInput, ot as renderSlackBlockFallbackText, st as buildSlackDataVisualizationBlock, ut as buildSlackDataTableBlock, w as appendSlackNativeDataFallbackText } from "./probe-DANukR3O.mjs";
2
2
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
4
4
  import { legacyInteractiveReplyToPresentation, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
5
- import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
6
5
  import { resolveAskUserQuestionOptionIndex, resolveAskUserQuestionOptionIndices, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
6
+ import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
7
+ //#region extensions/slack/src/authored-text.ts
8
+ function isSlackAuthoredTextRepresentedInFragments(plan, fragments) {
9
+ if (plan.length === 0) return false;
10
+ if (fragments.some((_, start) => plan.every((text, index) => text === fragments[start + index]))) return true;
11
+ const [text] = plan;
12
+ if (plan.length !== 1 || !text || /[*_~`<]/u.test(text)) return false;
13
+ for (let start = 0; start < fragments.length; start += 1) {
14
+ let offset = 0;
15
+ for (let end = start; end < fragments.length; end += 1) {
16
+ const fragment = fragments[end];
17
+ if (typeof fragment !== "string" || !text.startsWith(fragment, offset)) break;
18
+ offset += fragment.length;
19
+ if (offset === text.length) return true;
20
+ if (!/\s/u.test(text[offset] ?? "")) break;
21
+ while (/\s/u.test(text[offset] ?? "")) offset += 1;
22
+ }
23
+ }
24
+ return false;
25
+ }
26
+ /** Resolve placement from producer facts, before accessibility text changes the payload text. */
27
+ function resolveSlackAuthoredTextPlacement(params) {
28
+ const text = normalizeOptionalString(params.text);
29
+ if (!text) return "none";
30
+ const fragments = (params.renderedTextFragments ?? params.interactive?.blocks.flatMap((block) => block.type === "text" ? [block.text] : []) ?? []).map((fragment) => fragment?.trim() ?? null).filter((fragment) => fragment !== "");
31
+ return isSlackAuthoredTextRepresentedInFragments((params.authoredChunks ?? [text]).map((fragment) => fragment.trim()).filter(Boolean), fragments) ? "blocks" : "outside-blocks";
32
+ }
33
+ //#endregion
7
34
  //#region extensions/slack/src/blocks-render.ts
8
35
  const SLACK_BUTTON_URL_MAX = 3e3;
9
36
  function buildSlackPlainText(text, maxLength) {
@@ -13,10 +40,6 @@ function buildSlackPlainText(text, maxLength) {
13
40
  emoji: true
14
41
  };
15
42
  }
16
- function resolveSlackButtonStyle(style) {
17
- if (style === "primary" || style === "danger") return style;
18
- if (style === "success") return "primary";
19
- }
20
43
  function resolveSlackActionTarget(action, questionOptionIndices) {
21
44
  if (!action) return;
22
45
  if (action.type === "approval") return {
@@ -59,42 +82,10 @@ function resolveSlackActionTarget(action, questionOptionIndices) {
59
82
  value: command
60
83
  } : void 0;
61
84
  }
62
- function resolveSlackButtonTarget(button, questionOptionIndices) {
63
- if (button.action !== void 0) {
64
- const action = resolveMessagePresentationButtonAction(button);
65
- return action ? resolveSlackActionTarget(action, questionOptionIndices) : void 0;
66
- }
67
- const legacyUrl = normalizeOptionalString(button.url ?? button.webApp?.url ?? button.web_app?.url);
68
- if (legacyUrl && legacyUrl.length <= SLACK_BUTTON_URL_MAX) return {
69
- kind: "link",
70
- url: legacyUrl
71
- };
72
- const legacyValue = normalizeOptionalString(button.value);
73
- if (legacyValue) return {
74
- kind: "reply",
75
- value: legacyValue
76
- };
77
- return legacyUrl ? {
78
- kind: "link",
79
- url: legacyUrl
80
- } : void 0;
81
- }
82
85
  function isSlackTextFallbackButton(button) {
83
86
  const action = resolveMessagePresentationButtonAction(button);
84
87
  return action?.type === "question" && "intent" in action && action.intent === "custom-input";
85
88
  }
86
- function resolveSlackOptionTarget(option) {
87
- if (option.action !== void 0) {
88
- const action = resolveMessagePresentationOptionAction(option);
89
- const target = action ? resolveSlackActionTarget(action) : void 0;
90
- return target?.kind === "link" || target?.kind === "question" ? void 0 : target;
91
- }
92
- const value = normalizeOptionalString(option.value);
93
- return value ? {
94
- kind: "reply",
95
- value
96
- } : void 0;
97
- }
98
89
  function readSlackOpenClawBlockIndex(blockId, prefix) {
99
90
  if (!blockId.startsWith(prefix)) return;
100
91
  const value = Number.parseInt(blockId.slice(prefix.length), 10);
@@ -136,7 +127,18 @@ function buildSlackPresentationBlocksIfComplete(presentation, options = {}) {
136
127
  function compileSlackPresentationBlocks(presentation, options, requireComplete) {
137
128
  if (!presentation) return [];
138
129
  if (requireComplete && presentation.title && presentation.title.trim().length > 150) return;
139
- const tables = buildSlackPresentationTables(presentation, options);
130
+ let tables = [];
131
+ let cellCharacterCount = options.dataTableCellCharacterCountOffset ?? 0;
132
+ for (const block of presentation.blocks) {
133
+ if (block.type !== "table") continue;
134
+ const table = buildSlackDataTableBlock(block, { cellCharacterCountOffset: cellCharacterCount });
135
+ if (!table) {
136
+ tables = void 0;
137
+ break;
138
+ }
139
+ cellCharacterCount += countSlackDataTableCellCharacters(table);
140
+ tables.push(table);
141
+ }
140
142
  if (requireComplete && !tables) return;
141
143
  const blocks = [];
142
144
  if (presentation.title) blocks.push({
@@ -175,8 +177,79 @@ function compileSlackPresentationBlocks(presentation, options, requireComplete)
175
177
  }
176
178
  if (block.type === "buttons" || block.type === "select") {
177
179
  const index = controlIndices[block.type] + 1;
178
- const elements = block.type === "buttons" ? buildSlackPresentationButtonElements(block, index, options.questionOptionIndices, requireComplete) : buildSlackPresentationSelectElements(block, index, requireComplete);
179
- if (!elements) return;
180
+ let elements;
181
+ if (block.type === "buttons") {
182
+ let complete = true;
183
+ const buttons = block.buttons.flatMap((button, choiceIndex) => {
184
+ const questionOptionIndices = options.questionOptionIndices;
185
+ let target;
186
+ if (button.action !== void 0) {
187
+ const action = resolveMessagePresentationButtonAction(button);
188
+ target = action ? resolveSlackActionTarget(action, questionOptionIndices) : void 0;
189
+ } else {
190
+ const legacyUrl = normalizeOptionalString(button.url ?? button.webApp?.url ?? button.web_app?.url);
191
+ if (legacyUrl && legacyUrl.length <= SLACK_BUTTON_URL_MAX) target = {
192
+ kind: "link",
193
+ url: legacyUrl
194
+ };
195
+ else {
196
+ const legacyValue = normalizeOptionalString(button.value);
197
+ target = legacyValue ? {
198
+ kind: "reply",
199
+ value: legacyValue
200
+ } : legacyUrl ? {
201
+ kind: "link",
202
+ url: legacyUrl
203
+ } : void 0;
204
+ }
205
+ }
206
+ if (!target || (target.kind === "link" ? target.url.length > SLACK_BUTTON_URL_MAX : target.value.length > 2e3)) {
207
+ if (requireComplete && !isSlackTextFallbackButton(button)) complete = false;
208
+ return [];
209
+ }
210
+ if (button.label.length > 75) complete = false;
211
+ const style = button.style === "success" ? "primary" : button.style === "primary" || button.style === "danger" ? button.style : void 0;
212
+ return [{
213
+ type: "button",
214
+ action_id: `${SLACK_BUTTON_ACTION_IDS[target.kind]}:${index}:${choiceIndex + 1}`,
215
+ text: buildSlackPlainText(button.label, 75),
216
+ ...target.kind === "link" ? { url: target.url } : { value: target.value },
217
+ ...style ? { style } : {}
218
+ }];
219
+ });
220
+ if (requireComplete && (!complete || buttons.length > 25)) return;
221
+ elements = buttons.slice(0, 25);
222
+ } else {
223
+ const placeholder = normalizeOptionalString(block.placeholder) ?? "Choose an option";
224
+ const candidates = block.options.map((option) => {
225
+ if (option.action !== void 0) {
226
+ const action = resolveMessagePresentationOptionAction(option);
227
+ const target = action ? resolveSlackActionTarget(action) : void 0;
228
+ return target && target.kind !== "link" && target.kind !== "question" ? {
229
+ label: option.label,
230
+ ...target
231
+ } : void 0;
232
+ }
233
+ const value = normalizeOptionalString(option.value);
234
+ return value ? {
235
+ label: option.label,
236
+ kind: "reply",
237
+ value
238
+ } : void 0;
239
+ });
240
+ if (requireComplete && (placeholder.length > 75 || block.options.length > 100 || block.placeholder && block.placeholder.length > 75 || !candidates.every((option) => option && option.label.length <= 75 && option.value.length <= 150) || new Set(candidates.map((option) => option?.kind)).size !== 1)) return;
241
+ const selectOptions = candidates.flatMap((option) => option && option.value.length <= 150 ? [option] : []).slice(0, 100);
242
+ const optionKinds = new Set(selectOptions.map((option) => option.kind));
243
+ elements = selectOptions.length > 0 && optionKinds.size === 1 ? [{
244
+ type: "static_select",
245
+ action_id: `${SLACK_SELECT_ACTION_IDS[selectOptions[0].kind]}:${index}`,
246
+ placeholder: buildSlackPlainText(placeholder, 75),
247
+ options: selectOptions.map((option) => ({
248
+ text: buildSlackPlainText(option.label, 75),
249
+ value: option.value
250
+ }))
251
+ }] : [];
252
+ }
180
253
  if (elements.length > 0) {
181
254
  controlIndices[block.type] = index;
182
255
  blocks.push({
@@ -212,92 +285,6 @@ function compileSlackPresentationBlocks(presentation, options, requireComplete)
212
285
  }
213
286
  return blocks;
214
287
  }
215
- function buildSlackPresentationButtonElements(block, buttonIndex, questionOptionIndices, requireComplete) {
216
- let complete = true;
217
- const elements = block.buttons.flatMap((button, choiceIndex) => {
218
- const target = resolveSlackButtonTarget(button, questionOptionIndices);
219
- if (!target || (target.kind === "link" ? target.url.length > SLACK_BUTTON_URL_MAX : target.value.length > 2e3)) {
220
- if (requireComplete && !isSlackTextFallbackButton(button)) complete = false;
221
- return [];
222
- }
223
- if (button.label.length > 75) complete = false;
224
- const style = resolveSlackButtonStyle(button.style);
225
- return [{
226
- type: "button",
227
- action_id: `${SLACK_BUTTON_ACTION_IDS[target.kind]}:${buttonIndex}:${choiceIndex + 1}`,
228
- text: buildSlackPlainText(button.label, 75),
229
- ...target.kind === "link" ? { url: target.url } : { value: target.value },
230
- ...style ? { style } : {}
231
- }];
232
- });
233
- if (requireComplete && (!complete || elements.length > 25)) return;
234
- return elements.slice(0, 25);
235
- }
236
- /** Admit tables together: one invalid or over-budget table keeps every table on the text path. */
237
- function buildSlackPresentationTables(presentation, options = {}) {
238
- const tables = [];
239
- let cellCharacterCount = options.dataTableCellCharacterCountOffset ?? 0;
240
- for (const block of presentation.blocks) {
241
- if (block.type !== "table") continue;
242
- const table = buildSlackDataTableBlock(block, { cellCharacterCountOffset: cellCharacterCount });
243
- if (!table) return;
244
- cellCharacterCount += countSlackDataTableCellCharacters(table);
245
- tables.push(table);
246
- }
247
- return tables;
248
- }
249
- function buildSlackPresentationSelectElements(block, selectIndex, requireComplete) {
250
- const placeholder = normalizeOptionalString(block.placeholder) ?? "Choose an option";
251
- const candidates = block.options.map((option) => {
252
- const target = resolveSlackOptionTarget(option);
253
- return target ? {
254
- label: option.label,
255
- ...target
256
- } : void 0;
257
- });
258
- if (requireComplete && (placeholder.length > 75 || block.options.length > 100 || block.placeholder && block.placeholder.length > 75 || !candidates.every((option) => option && option.label.length <= 75 && option.value.length <= 150) || new Set(candidates.map((option) => option?.kind)).size !== 1)) return;
259
- const options = candidates.flatMap((option) => option && option.value.length <= 150 ? [option] : []).slice(0, 100);
260
- const optionKinds = new Set(options.map((option) => option.kind));
261
- return options.length > 0 && optionKinds.size === 1 ? [{
262
- type: "static_select",
263
- action_id: `${SLACK_SELECT_ACTION_IDS[options[0].kind]}:${selectIndex}`,
264
- placeholder: buildSlackPlainText(placeholder, 75),
265
- options: options.map((option) => ({
266
- text: buildSlackPlainText(option.label, 75),
267
- value: option.value
268
- }))
269
- }] : [];
270
- }
271
- //#endregion
272
- //#region extensions/slack/src/authored-text.ts
273
- function normalizeComparableSlackText(text) {
274
- return text.trim().replace(/\s+/g, " ");
275
- }
276
- function isSlackAuthoredTextRepresentedInFragments(text, rawFragments) {
277
- const target = normalizeComparableSlackText(text);
278
- const fragments = rawFragments.map(normalizeComparableSlackText).filter(Boolean);
279
- let remainingLength = fragments.reduce((length, fragment) => length + fragment.length + 1, -1);
280
- for (const [start, firstFragment] of fragments.entries()) {
281
- if (remainingLength < target.length) break;
282
- remainingLength -= firstFragment.length + 1;
283
- let offset = 0;
284
- for (let end = start;; end += 1) {
285
- const fragment = fragments[end];
286
- if (fragment === void 0 || !target.startsWith(fragment, offset)) break;
287
- offset += fragment.length;
288
- if (offset === target.length) return true;
289
- if (target[offset] !== " ") break;
290
- offset += 1;
291
- }
292
- }
293
- return false;
294
- }
295
- /** Resolve placement from producer facts, before accessibility text changes the payload text. */
296
- function resolveSlackAuthoredTextPlacement(params) {
297
- const text = normalizeOptionalString(params.text);
298
- if (!text) return "none";
299
- return params.renderedInBlocks || isSlackAuthoredTextRepresentedInFragments(text, params.renderedTextFragments ?? []) || isSlackAuthoredTextRepresentedInFragments(text, params.interactive?.blocks.flatMap((block) => block.type === "text" ? [block.text] : []) ?? []) ? "blocks" : "outside-blocks";
300
- }
301
288
  //#endregion
302
289
  //#region extensions/slack/src/reply-blocks.ts
303
290
  function normalizeSlackReplyPayload(payload) {
@@ -321,27 +308,6 @@ function normalizeSlackReplyPayload(payload) {
321
308
  }
322
309
  };
323
310
  }
324
- function parseSlackReplyBlockSegments(value) {
325
- if (value === void 0) return;
326
- if (!Array.isArray(value)) throw new Error("Slack rendered presentation segments must be an array");
327
- return value.map((raw) => {
328
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("Slack rendered presentation segment must be an object");
329
- const segment = raw;
330
- if (segment.kind === "text" && typeof segment.text === "string" && segment.mrkdwn === false) return {
331
- kind: "text",
332
- text: segment.text,
333
- mrkdwn: false
334
- };
335
- if (segment.kind === "blocks") {
336
- const blocks = parseSlackBlocksInput(segment.blocks);
337
- if (blocks?.length) return {
338
- kind: "blocks",
339
- blocks
340
- };
341
- }
342
- throw new Error("Slack rendered presentation segment is invalid");
343
- });
344
- }
345
311
  /** Project each segment only when the caller is ready to deliver it. */
346
312
  function* iterateSlackReplyDeliveryMessages(params) {
347
313
  let outsideText = params.authoredTextPlacement === "outside-blocks" ? params.text?.trim() ?? "" : "";
@@ -374,35 +340,35 @@ function* iterateSlackReplyDeliveryMessages(params) {
374
340
  function resolveSlackReplyDeliveryMessages(params) {
375
341
  return Array.from(iterateSlackReplyDeliveryMessages(params));
376
342
  }
377
- function resolveSlackReplyRenderPlan(payload, text = payload.text) {
378
- return prepareSlackReply(payload).resolvePreview(text);
343
+ function resolveSlackReplyRenderPlan(payload, text = payload.text, options = {}) {
344
+ return prepareSlackReply(payload, options).resolvePreview(text);
379
345
  }
380
346
  /** One attempt owns its authored compilation; media captions retain a separate delivery policy. */
381
- function prepareSlackReply(payload) {
347
+ function prepareSlackReply(payload, options = {}) {
382
348
  const text = payload.text;
383
- const source = {
384
- ...payload,
385
- text
386
- };
387
349
  let authoredChunks;
388
350
  let structuredContent;
389
351
  let materialized;
390
352
  let unmaterialized;
391
353
  let preview;
392
- const resolveAuthoredTextChunks = () => authoredChunks ??= markdownToSlackMrkdwnChunks(text?.trim() ?? "", SLACK_SECTION_TEXT_MAX);
393
- const hasStructuredContent = () => structuredContent ??= hasSlackReplyStructuredContent(source);
394
- const resolve = (materializeAuthoredText) => materializeAuthoredText ? materialized ??= resolveSlackReplyBlockResolution(source, {
354
+ const resolveAuthoredTextChunks = () => authoredChunks ??= markdownToSlackMrkdwnChunks(text?.trim() ?? "", SLACK_SECTION_TEXT_MAX, options);
355
+ const hasStructuredContent = () => structuredContent ??= hasSlackReplyStructuredContent(payload);
356
+ const resolve = (materializeAuthoredText) => materializeAuthoredText ? materialized ??= resolveSlackReplyBlockResolution(payload, {
357
+ ...options,
395
358
  materializeAuthoredText: true,
396
359
  resolveAuthoredTextChunks
397
- }) : unmaterialized ??= resolveSlackReplyBlockResolution(source);
360
+ }) : unmaterialized ??= resolveSlackReplyBlockResolution(payload, {
361
+ ...options,
362
+ resolveAuthoredTextChunks
363
+ });
398
364
  return {
399
365
  payload,
400
- resolveDelivery: () => resolve(!resolveSendableOutboundReplyParts(source).hasMedia && hasStructuredContent()),
366
+ resolveDelivery: () => resolve(!resolveSendableOutboundReplyParts(payload).hasMedia && hasStructuredContent()),
401
367
  resolvePreview: (override = text) => {
402
368
  if (override !== text) return prepareSlackReply({
403
- ...source,
369
+ ...payload,
404
370
  text: override
405
- }).resolvePreview();
371
+ }, options).resolvePreview();
406
372
  return preview ??= projectSlackReplyRenderPlan(text, resolve(hasStructuredContent()), resolveAuthoredTextChunks);
407
373
  }
408
374
  };
@@ -452,11 +418,52 @@ function readSlackChannelBlocks(payload) {
452
418
  function hasSlackReplyStructuredContent(payload) {
453
419
  return Boolean(readSlackChannelBlocks(payload).length || normalizeMessagePresentation(payload.presentation) || payload.interactive?.blocks.length);
454
420
  }
421
+ function literalSlackComparisonText(text) {
422
+ return /[*_~`]/u.test(text) ? null : escapeSlackMrkdwn(text);
423
+ }
424
+ function renderSlackRichTextComparisonFragments(value) {
425
+ if (!Array.isArray(value)) return [null];
426
+ return value.map((raw) => {
427
+ const section = asOptionalRecord(raw);
428
+ if (section?.type !== "rich_text_section" && section?.type !== "rich_text_preformatted" || !Array.isArray(section.elements)) return null;
429
+ let text = "";
430
+ let style;
431
+ for (const rawElement of section.elements) {
432
+ const element = asOptionalRecord(rawElement);
433
+ if (element?.type !== "text" || typeof element.text !== "string") return null;
434
+ const styles = Object.entries(asOptionalRecord(element.style) ?? {}).filter(([, enabled]) => enabled !== false);
435
+ const nextStyle = styles[0]?.[0] ?? "";
436
+ if (styles.length > 1 || styles.some(([key, enabled]) => enabled !== true || ![
437
+ "bold",
438
+ "italic",
439
+ "strike",
440
+ "code"
441
+ ].includes(key)) || style !== void 0 && nextStyle !== style) return null;
442
+ style = nextStyle;
443
+ text += element.text;
444
+ }
445
+ if (section.type === "rich_text_preformatted") return style || text.includes("```") ? null : "```\n" + escapeSlackMrkdwn(text) + (text.endsWith("\n") ? "" : "\n") + "```";
446
+ if (style === "code") return /[`\r\n]/u.test(text) ? null : "`" + escapeSlackMrkdwn(text) + "`";
447
+ const literal = literalSlackComparisonText(text);
448
+ if (!style || literal === null) return literal;
449
+ if (text.trim() !== text) return null;
450
+ const marker = style === "bold" ? "*" : style === "italic" ? "_" : "~";
451
+ return marker + literal + marker;
452
+ });
453
+ }
455
454
  function renderSlackAuthoredTextFragments(blocks) {
455
+ const readTextObject = (value) => {
456
+ const record = asOptionalRecord(value);
457
+ const text = normalizeOptionalString(record?.text);
458
+ return text === void 0 ? void 0 : record?.type === "mrkdwn" ? text : literalSlackComparisonText(text);
459
+ };
456
460
  return blocks.flatMap((block) => {
457
- if (block.type === "actions") return [];
458
- const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
459
- return text ? [text] : [];
461
+ const record = asOptionalRecord(block);
462
+ if (block.type === "actions" || block.type === "divider") return [];
463
+ if (block.type === "section" || block.type === "context" || block.type === "header") return (block.type === "context" ? Array.isArray(record?.elements) ? record.elements : [] : [record?.text, ...Array.isArray(record?.fields) ? record.fields : []]).map(readTextObject).filter((text) => text !== void 0);
464
+ if (block.type === "rich_text") return renderSlackRichTextComparisonFragments(record?.elements);
465
+ const text = renderSlackBlockFallbackText(block);
466
+ return text ? [/[*_~`]/u.test(text) ? null : text] : [];
460
467
  });
461
468
  }
462
469
  function buildSlackAuthoredTextBlocks(chunks) {
@@ -501,8 +508,7 @@ function appendTextSegment(segments, text) {
501
508
  }
502
509
  segments.push({
503
510
  kind: "text",
504
- text: trimmed,
505
- mrkdwn: false
511
+ text: trimmed
506
512
  });
507
513
  }
508
514
  function appendBlockSegment(segments, blocks, startNew = false) {
@@ -570,37 +576,10 @@ function subtractMirroredSlackControlRows(params) {
570
576
  return false;
571
577
  });
572
578
  }
573
- /**
574
- * Resolve reply content into transport-order segments. Each blocks segment is
575
- * one Slack message; text segments carry complete fallback content between it.
576
- */
577
- function resolveSlackReplyBlockResolution(payload, options = {}) {
579
+ function compileSlackReplyBlockSegments(payload, channelBlocks, presentation) {
578
580
  const segments = [];
579
- const presentation = normalizeMessagePresentation(payload.presentation);
580
581
  const textIsFallback = presentation && payload.presentationTextMode === "fallback";
581
- const authoredText = textIsFallback ? void 0 : payload.text;
582
- const channelBlocks = readSlackChannelBlocks(payload);
583
- let compiledChannelBlocks = channelBlocks;
584
- let authoredTextKnownInBlocks = false;
585
- if (options.materializeAuthoredText) {
586
- const rawTextFragments = renderSlackAuthoredTextFragments(channelBlocks);
587
- const initialPlacement = resolveSlackAuthoredTextPlacement({
588
- text: authoredText,
589
- interactive: payload.interactive,
590
- renderedTextFragments: rawTextFragments
591
- });
592
- authoredTextKnownInBlocks = initialPlacement === "blocks";
593
- const text = normalizeOptionalString(authoredText);
594
- if (text && initialPlacement === "outside-blocks") {
595
- const textBlocks = buildSlackAuthoredTextBlocks(options.resolveAuthoredTextChunks?.() ?? markdownToSlackMrkdwnChunks(text, 3e3));
596
- if (resolveSlackAuthoredTextPlacement({
597
- text: renderSlackAuthoredTextFragments(textBlocks).join(" "),
598
- renderedTextFragments: rawTextFragments
599
- }) !== "blocks") compiledChannelBlocks = [...channelBlocks, ...textBlocks];
600
- authoredTextKnownInBlocks = true;
601
- }
602
- }
603
- if (compiledChannelBlocks.length > 0) appendBlockSegment(segments, compiledChannelBlocks);
582
+ if (channelBlocks.length > 0) appendBlockSegment(segments, channelBlocks);
604
583
  const questionOptionIndices = resolveAskUserQuestionOptionIndices(payload);
605
584
  const presentationBlockOffset = readAllNativeBlocks(segments).length;
606
585
  if (presentation?.title) appendPresentationPart(segments, {
@@ -621,31 +600,47 @@ function resolveSlackReplyBlockResolution(payload, options = {}) {
621
600
  "rich_text"
622
601
  ].includes(block.type) && !("accessory" in block && block.accessory))) {
623
602
  segments.length = 0;
624
- appendBlockSegment(segments, compiledChannelBlocks);
603
+ appendBlockSegment(segments, channelBlocks);
625
604
  appendTextSegment(segments, payload.text);
626
605
  }
627
606
  appendBlockSegment(segments, subtractMirroredSlackControlRows({
628
607
  interactiveBlocks,
629
608
  presentationBlocks: renderedPresentationBlocks
630
609
  }));
631
- const renderedTextFragments = segments.flatMap((segment) => {
632
- if (segment.kind === "text") return [segment.text];
633
- return renderSlackAuthoredTextFragments(segment.blocks);
610
+ return segments;
611
+ }
612
+ /**
613
+ * Resolve reply content into transport-order segments. Each blocks segment is
614
+ * one Slack message; text segments carry complete fallback content between it.
615
+ */
616
+ function resolveSlackReplyBlockResolution(payload, options = {}) {
617
+ const presentation = normalizeMessagePresentation(payload.presentation);
618
+ const authoredText = presentation && payload.presentationTextMode === "fallback" ? void 0 : normalizeOptionalString(payload.text);
619
+ const channelBlocks = readSlackChannelBlocks(payload);
620
+ let segments = compileSlackReplyBlockSegments(payload, channelBlocks, presentation);
621
+ const chunks = authoredText && (segments.length > 0 || options.materializeAuthoredText) ? options.resolveAuthoredTextChunks?.() ?? markdownToSlackMrkdwnChunks(authoredText, 3e3, options) : [];
622
+ let authoredTextPlacement = resolveSlackAuthoredTextPlacement({
623
+ text: authoredText,
624
+ authoredChunks: chunks,
625
+ renderedTextFragments: segments.flatMap((segment) => segment.kind === "text" ? [literalSlackComparisonText(segment.text)] : renderSlackAuthoredTextFragments(segment.blocks))
634
626
  });
635
- const authoredTextPlacement = resolveSlackAuthoredTextPlacement({
627
+ if (authoredTextPlacement === "outside-blocks" && !/[*_~`<[\]\\#>|]/u.test(authoredText ?? "")) authoredTextPlacement = resolveSlackAuthoredTextPlacement({
636
628
  text: authoredText,
637
- interactive: payload.interactive,
638
- renderedTextFragments
629
+ renderedTextFragments: segments.flatMap((segment) => segment.kind === "text" ? [segment.text] : segment.blocks.map((block) => hasSlackNativeDataBlock([block]) ? renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" }) ?? null : null))
639
630
  });
631
+ if (options.materializeAuthoredText && authoredTextPlacement === "outside-blocks") {
632
+ segments = compileSlackReplyBlockSegments(payload, [...channelBlocks, ...buildSlackAuthoredTextBlocks(chunks)], presentation);
633
+ authoredTextPlacement = "blocks";
634
+ }
640
635
  return {
641
- authoredTextPlacement: authoredTextKnownInBlocks ? "blocks" : authoredTextPlacement,
636
+ authoredTextPlacement,
642
637
  segments
643
638
  };
644
639
  }
645
640
  /** Return the single-message native shape when no ordered text fallback is required. */
646
641
  function resolveSlackReplyBlocks(payload) {
647
- const { segments } = resolveSlackReplyBlockResolution(payload);
642
+ const segments = compileSlackReplyBlockSegments(payload, readSlackChannelBlocks(payload), normalizeMessagePresentation(payload.presentation));
648
643
  return segments.length === 1 && segments[0]?.kind === "blocks" ? segments[0].blocks : void 0;
649
644
  }
650
645
  //#endregion
651
- export { prepareSlackReply as a, resolveSlackReplyDeliveryMessages as c, buildSlackInteractiveBlocks as d, buildSlackPresentationBlocks as f, parseSlackReplyBlockSegments as i, resolveSlackReplyRenderPlan as l, iterateSlackReplyDeliveryMessages as n, resolveSlackReplyBlockResolution as o, buildSlackPresentationBlocksIfComplete as p, normalizeSlackReplyPayload as r, resolveSlackReplyBlocks as s, hasSlackReplyStructuredContent as t, resolveSlackAuthoredTextPlacement as u };
646
+ export { resolveSlackReplyBlockResolution as a, resolveSlackReplyRenderPlan as c, resolveSlackAuthoredTextPlacement as d, prepareSlackReply as i, buildSlackInteractiveBlocks as l, iterateSlackReplyDeliveryMessages as n, resolveSlackReplyBlocks as o, normalizeSlackReplyPayload as r, resolveSlackReplyDeliveryMessages as s, hasSlackReplyStructuredContent as t, buildSlackPresentationBlocks as u };
@@ -1,12 +1,11 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-FFE26kOV.mjs";
3
- import { c as collectSlackCursorPages, l as fetchSlackChannelListPage, u as createSlackLookupClient } from "./probe-IiHogLQN.mjs";
2
+ import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-Bx2UZniD.mjs";
3
+ import { n as fetchSlackChannelListPage, r as createSlackLookupClient, t as collectSlackCursorPages } from "./cursor-pages-CATAzbTT.mjs";
4
4
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  //#region extensions/slack/src/resolve-channels.ts
6
6
  var resolve_channels_exports = /* @__PURE__ */ __exportAll({ resolveSlackChannelAllowlist: () => resolveSlackChannelAllowlist });
7
7
  function parseSlackChannelMention(raw) {
8
8
  const trimmed = raw.trim();
9
- if (!trimmed) return {};
10
9
  const mention = trimmed.match(/^<#([A-Z0-9]+)(?:\|([^>]+))?>$/i);
11
10
  if (mention) return {
12
11
  id: mention[1]?.toUpperCase(),
@@ -14,7 +13,7 @@ function parseSlackChannelMention(raw) {
14
13
  };
15
14
  const prefixed = trimmed.replace(/^(slack:|channel:)/i, "");
16
15
  if (/^[CG][A-Z0-9]{8,}$/i.test(prefixed)) return { id: prefixed.toUpperCase() };
17
- const name = prefixed.replace(/^#/, "").trim();
16
+ const name = normalizeLowercaseStringOrEmpty(prefixed.replace(/^#/, ""));
18
17
  return name ? { name } : {};
19
18
  }
20
19
  async function listSlackChannels(client) {
@@ -34,9 +33,7 @@ async function listSlackChannels(client) {
34
33
  });
35
34
  }
36
35
  function resolveByName(name, channels) {
37
- const target = normalizeLowercaseStringOrEmpty(name);
38
- if (!target) return;
39
- const matches = channels.filter((channel) => normalizeLowercaseStringOrEmpty(channel.name) === target);
36
+ const matches = channels.filter((channel) => normalizeLowercaseStringOrEmpty(channel.name) === name);
40
37
  return matches.find((channel) => !channel.archived) ?? matches[0];
41
38
  }
42
39
  async function resolveSlackChannelAllowlist(params) {
@@ -1,18 +1,17 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-FFE26kOV.mjs";
3
- import { c as collectSlackCursorPages, u as createSlackLookupClient } from "./probe-IiHogLQN.mjs";
2
+ import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-Bx2UZniD.mjs";
3
+ import { r as createSlackLookupClient, t as collectSlackCursorPages } from "./cursor-pages-CATAzbTT.mjs";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  //#region extensions/slack/src/resolve-users.ts
6
6
  var resolve_users_exports = /* @__PURE__ */ __exportAll({ resolveSlackUserAllowlist: () => resolveSlackUserAllowlist });
7
7
  function parseSlackUserInput(raw) {
8
8
  const trimmed = raw.trim();
9
- if (!trimmed) return {};
10
9
  const mention = trimmed.match(/^<@([A-Z0-9]+)>$/i);
11
10
  if (mention) return { id: mention[1]?.toUpperCase() };
12
11
  const prefixed = trimmed.replace(/^(slack:|user:)/i, "");
13
12
  if (/^[A-Z][A-Z0-9]+$/i.test(prefixed)) return { id: prefixed.toUpperCase() };
14
13
  if (trimmed.includes("@") && !trimmed.startsWith("@")) return { email: normalizeLowercaseStringOrEmpty(trimmed) };
15
- const name = trimmed.replace(/^@/, "").trim();
14
+ const name = normalizeLowercaseStringOrEmpty(trimmed.replace(/^@/, ""));
16
15
  return name ? { name } : {};
17
16
  }
18
17
  async function listSlackUsers(client) {
@@ -39,17 +38,6 @@ async function listSlackUsers(client) {
39
38
  }).filter((user) => user !== null)
40
39
  });
41
40
  }
42
- function matchesSlackUserName(user, name) {
43
- const target = normalizeLowercaseStringOrEmpty(name);
44
- return [
45
- user.name,
46
- user.displayName,
47
- user.realName
48
- ].some((value) => {
49
- const candidate = normalizeLowercaseStringOrEmpty(value);
50
- return Boolean(candidate) && candidate === target;
51
- });
52
- }
53
41
  function scoreSlackUser(user) {
54
42
  return (user.deleted ? 0 : 3) + (user.isBot || user.isAppUser ? 0 : 2);
55
43
  }
@@ -62,7 +50,11 @@ async function resolveSlackUserAllowlist(params) {
62
50
  const users = entries.some(({ workspace }) => !workspace) ? await listSlackUsers(params.client ?? createSlackLookupClient(params.token)) : [];
63
51
  return entries.map(({ input, workspace, parsed }) => {
64
52
  if (workspace) return workspace;
65
- const matches = users.filter((user) => parsed.id ? user.id === parsed.id : parsed.email ? user.email === parsed.email : parsed.name ? matchesSlackUserName(user, parsed.name) : false);
53
+ const matches = users.filter((user) => parsed.id ? user.id === parsed.id : parsed.email ? user.email === parsed.email : parsed.name ? [
54
+ user.name,
55
+ user.displayName,
56
+ user.realName
57
+ ].some((value) => normalizeLowercaseStringOrEmpty(value) === parsed.name) : false);
66
58
  const match = parsed.id ? matches[0] : matches.toSorted((a, b) => scoreSlackUser(b) - scoreSlackUser(a))[0];
67
59
  if (!parsed.id && !match) return {
68
60
  input,
@@ -0,0 +1,2 @@
1
+ export { r as setSlackRuntime } from "./runtime-JSVZSWAj.mjs";
2
+ import "../runtime-setter-api.js";
@@ -1,4 +1,5 @@
1
- import { d as createSlackReadClient, o as formatSlackError } from "./probe-IiHogLQN.mjs";
1
+ import { m as formatSlackError } from "./probe-DANukR3O.mjs";
2
+ import { i as createSlackReadClient } from "./cursor-pages-CATAzbTT.mjs";
2
3
  import { isRecord, normalizeOptionalString, normalizeTrimmedStringList, sortUniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  //#region extensions/slack/src/scopes.ts
4
5
  function collectScopes(value, into) {
@@ -0,0 +1,2 @@
1
+ export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-uiQtoNlu.mjs";
2
+ import "../secret-contract-api.js";
@@ -1,5 +1,5 @@
1
1
  import { n as hasSlackAccountCredentialsFromConfig } from "./account-configured-zcR9TJJN.mjs";
2
- import { collectConditionalChannelFieldAssignments, collectNestedChannelFieldAssignments, collectSimpleChannelFieldAssignments, createChannelSecretContract, hasOwnProperty } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
2
+ import { collectConditionalChannelFieldAssignments, collectNestedChannelFieldAssignments, collectSimpleChannelFieldAssignments, createChannelSecretContract, hasOwnProperty, isRecord } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
3
3
  //#region extensions/slack/src/secret-contract.ts
4
4
  const channelSecrets = createChannelSecretContract({
5
5
  channelKey: "slack",
@@ -31,7 +31,7 @@ const channelSecrets = createChannelSecretContract({
31
31
  const resolveAccountMode = (account) => resolveMode(account.mode) ?? baseMode;
32
32
  const hasNestedAuthTokenOverride = (account) => {
33
33
  const relay = account.relay;
34
- return relay !== null && typeof relay === "object" && !Array.isArray(relay) && hasOwnProperty(relay, "authToken");
34
+ return isRecord(relay) && hasOwnProperty(relay, "authToken");
35
35
  };
36
36
  for (const [field, mode, label] of [[
37
37
  "appToken",