@openclaw/slack 2026.8.1-beta.2 → 2026.9.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/dist/account-configured-sUohAxZr.js +33 -0
  2. package/dist/account-inspect-CN2hBsim.js +87 -0
  3. package/dist/account-inspect-api.js +1 -1
  4. package/dist/{accounts-CK4AVI2_.js → accounts-Dm_H77gH.js} +12 -11
  5. package/dist/{accounts.runtime-Cb7QwWBz.js → accounts.runtime-DRuEK6mL.js} +1 -1
  6. package/dist/{action-runtime-BkGe7ny_.js → action-runtime-BoSeX09X.js} +76 -83
  7. package/dist/action-runtime.runtime-Dpa16J87.js +2 -0
  8. package/dist/{actions-BTDXwwE3.js → actions-XdQyjG_p.js} +134 -262
  9. package/dist/api.js +14 -14
  10. package/dist/{approval-handler.runtime-CJaNzAq2.js → approval-handler.runtime-DxXfGX_Z.js} +53 -174
  11. package/dist/{channel-D_tovcUL.js → channel-C_vnTgxo.js} +117 -72
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel-type-B9MSdoGN.js → channel-type-j-2lalcC.js} +3 -7
  15. package/dist/{channel.setup-Bch9dYmA.js → channel.setup-aal8tokM.js} +34 -49
  16. package/dist/{config-schema-xto5jFIx.js → config-schema-CN3XZRX5.js} +23 -7
  17. package/dist/configured-state.js +34 -0
  18. package/dist/conversation-binding-route-DFVLUdYF.js +115 -0
  19. package/dist/{directory-config-CNBz8lJa.js → directory-config-DqfQ42OV.js} +1 -1
  20. package/dist/directory-contract-api.js +1 -1
  21. package/dist/{directory-live-CFKUtW9E.js → directory-live-lC6X_Ru-.js} +2 -2
  22. package/dist/{group-policy-c4RP9bjc.js → group-policy-CU1tEGpS.js} +583 -642
  23. package/dist/{message-tool-api-BykQB4AU.js → message-tool-api-CWosHSi5.js} +6 -5
  24. package/dist/message-tool-api.js +1 -1
  25. package/dist/{monitor-1nF1NtqT.js → monitor-DrNCGneD.js} +3 -3
  26. package/dist/{outbound-adapter-S81tsswN.js → outbound-adapter-DkT2vUE9.js} +50 -19
  27. package/dist/{pipeline.runtime-BvYsM5JO.js → pipeline.runtime-CRRng_Nw.js} +440 -451
  28. package/dist/{policy-TapwbeaT.js → policy-BoP6t88v.js} +1 -1
  29. package/dist/{probe-HoEg_WxB.js → probe-4_aHtVT3.js} +2 -21
  30. package/dist/{provider-CDNvBXUi.js → provider-D4nDgxCh.js} +240 -95
  31. package/dist/{relay-source-C9leF11u.js → relay-source-CEmze11m.js} +1 -1
  32. package/dist/{replies-CeOfv82I.js → replies-D9XMM_S0.js} +47 -26
  33. package/dist/{resolve-channels-CNPrxaXY.js → resolve-channels-DSamDgVs.js} +1 -1
  34. package/dist/{resolve-users-Dzomuwnr.js → resolve-users-CIzwbaJR.js} +1 -1
  35. package/dist/runtime-api.js +11 -11
  36. package/dist/{scopes-cYXKkrRD.js → scopes-BBrUzpBH.js} +1 -1
  37. package/dist/security-contract-api.js +1 -1
  38. package/dist/{send-Nor0iBwY.js → send-DtjEnlLh.js} +86 -98
  39. package/dist/{send.runtime-BmgNe6S9.js → send.runtime-DQeNKa2J.js} +1 -1
  40. package/dist/setup-plugin-api.js +1 -1
  41. package/dist/{setup-surface-CbX1-Knh.js → setup-surface-CsBCM4rP.js} +6 -6
  42. package/dist/{shared-zdT5AMp-.js → shared-D9GeeR9K.js} +33 -9
  43. package/dist/{block-text-YtiNkqmx.js → slack-client-kind-hSfjXyUM.js} +17 -2
  44. package/dist/{slash-dispatch.runtime-Bnr9GR1S.js → slash-dispatch.runtime-Chr3YHnT.js} +3 -3
  45. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  46. package/node_modules/@slack/bolt/node_modules/@types/node/child_process.d.ts +0 -1
  47. package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +6 -6
  48. package/node_modules/@slack/bolt/node_modules/@types/node/dns/promises.d.ts +5 -5
  49. package/node_modules/@slack/bolt/node_modules/@types/node/dns.d.ts +5 -5
  50. package/node_modules/@slack/bolt/node_modules/@types/node/fs.d.ts +7 -0
  51. package/node_modules/@slack/bolt/node_modules/@types/node/http.d.ts +30 -0
  52. package/node_modules/@slack/bolt/node_modules/@types/node/http2.d.ts +4 -4
  53. package/node_modules/@slack/bolt/node_modules/@types/node/os.d.ts +30 -30
  54. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  55. package/node_modules/@slack/bolt/node_modules/@types/node/perf_hooks.d.ts +2 -1
  56. package/node_modules/@slack/bolt/node_modules/@types/node/process.d.ts +42 -43
  57. package/node_modules/@slack/bolt/node_modules/@types/node/quic.d.ts +1049 -84
  58. package/node_modules/@slack/bolt/node_modules/@types/node/sqlite.d.ts +14 -1
  59. package/node_modules/@slack/bolt/node_modules/@types/node/stream/iter.d.ts +3 -2
  60. package/node_modules/@slack/bolt/node_modules/@types/node/test.d.ts +61 -0
  61. package/node_modules/@slack/bolt/node_modules/@types/node/v8.d.ts +20 -23
  62. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +2 -0
  63. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
  64. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
  65. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
  66. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +1 -1
  67. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +2 -0
  68. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
  69. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
  70. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
  71. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +1 -1
  72. package/node_modules/@slack/socket-mode/node_modules/@types/node/README.md +1 -1
  73. package/node_modules/@slack/socket-mode/node_modules/@types/node/child_process.d.ts +0 -1
  74. package/node_modules/@slack/socket-mode/node_modules/@types/node/crypto.d.ts +6 -6
  75. package/node_modules/@slack/socket-mode/node_modules/@types/node/dns/promises.d.ts +5 -5
  76. package/node_modules/@slack/socket-mode/node_modules/@types/node/dns.d.ts +5 -5
  77. package/node_modules/@slack/socket-mode/node_modules/@types/node/fs.d.ts +7 -0
  78. package/node_modules/@slack/socket-mode/node_modules/@types/node/http.d.ts +30 -0
  79. package/node_modules/@slack/socket-mode/node_modules/@types/node/http2.d.ts +4 -4
  80. package/node_modules/@slack/socket-mode/node_modules/@types/node/os.d.ts +30 -30
  81. package/node_modules/@slack/socket-mode/node_modules/@types/node/package.json +2 -2
  82. package/node_modules/@slack/socket-mode/node_modules/@types/node/perf_hooks.d.ts +2 -1
  83. package/node_modules/@slack/socket-mode/node_modules/@types/node/process.d.ts +42 -43
  84. package/node_modules/@slack/socket-mode/node_modules/@types/node/quic.d.ts +1049 -84
  85. package/node_modules/@slack/socket-mode/node_modules/@types/node/sqlite.d.ts +14 -1
  86. package/node_modules/@slack/socket-mode/node_modules/@types/node/stream/iter.d.ts +3 -2
  87. package/node_modules/@slack/socket-mode/node_modules/@types/node/test.d.ts +61 -0
  88. package/node_modules/@slack/socket-mode/node_modules/@types/node/v8.d.ts +20 -23
  89. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  90. package/node_modules/@slack/web-api/node_modules/@types/node/child_process.d.ts +0 -1
  91. package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +6 -6
  92. package/node_modules/@slack/web-api/node_modules/@types/node/dns/promises.d.ts +5 -5
  93. package/node_modules/@slack/web-api/node_modules/@types/node/dns.d.ts +5 -5
  94. package/node_modules/@slack/web-api/node_modules/@types/node/fs.d.ts +7 -0
  95. package/node_modules/@slack/web-api/node_modules/@types/node/http.d.ts +30 -0
  96. package/node_modules/@slack/web-api/node_modules/@types/node/http2.d.ts +4 -4
  97. package/node_modules/@slack/web-api/node_modules/@types/node/os.d.ts +30 -30
  98. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  99. package/node_modules/@slack/web-api/node_modules/@types/node/perf_hooks.d.ts +2 -1
  100. package/node_modules/@slack/web-api/node_modules/@types/node/process.d.ts +42 -43
  101. package/node_modules/@slack/web-api/node_modules/@types/node/quic.d.ts +1049 -84
  102. package/node_modules/@slack/web-api/node_modules/@types/node/sqlite.d.ts +14 -1
  103. package/node_modules/@slack/web-api/node_modules/@types/node/stream/iter.d.ts +3 -2
  104. package/node_modules/@slack/web-api/node_modules/@types/node/test.d.ts +61 -0
  105. package/node_modules/@slack/web-api/node_modules/@types/node/v8.d.ts +20 -23
  106. package/node_modules/typebox/build/format/date.d.mts +1 -1
  107. package/node_modules/typebox/build/format/date.mjs +1 -1
  108. package/node_modules/typebox/build/format/date_time.d.mts +2 -2
  109. package/node_modules/typebox/build/format/date_time.mjs +3 -3
  110. package/node_modules/typebox/build/format/email.d.mts +1 -1
  111. package/node_modules/typebox/build/format/email.mjs +2 -2
  112. package/node_modules/typebox/build/format/hostname.mjs +2 -10
  113. package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
  114. package/node_modules/typebox/build/format/idn_email.mjs +3 -3
  115. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
  116. package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
  117. package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
  118. package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
  119. package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
  120. package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
  121. package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
  122. package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
  123. package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
  124. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
  125. package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
  126. package/node_modules/typebox/build/format/idna/index.mjs +2 -0
  127. package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
  128. package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
  129. package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
  130. package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
  131. package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
  132. package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
  133. package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
  134. package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
  135. package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
  136. package/node_modules/typebox/build/format/ipv4.mjs +2 -32
  137. package/node_modules/typebox/build/format/ipv6.mjs +2 -61
  138. package/node_modules/typebox/build/format/iri.d.mts +2 -2
  139. package/node_modules/typebox/build/format/iri.mjs +26 -8
  140. package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
  141. package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
  142. package/node_modules/typebox/build/format/regex.d.mts +1 -2
  143. package/node_modules/typebox/build/format/regex.mjs +2 -6
  144. package/node_modules/typebox/build/format/time.d.mts +2 -2
  145. package/node_modules/typebox/build/format/time.mjs +19 -14
  146. package/node_modules/typebox/build/format/uri.d.mts +1 -1
  147. package/node_modules/typebox/build/format/uri.mjs +3 -130
  148. package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
  149. package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
  150. package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
  151. package/node_modules/typebox/build/format/uri_template.mjs +4 -5
  152. package/node_modules/typebox/build/format/url.d.mts +3 -3
  153. package/node_modules/typebox/build/format/url.mjs +4 -5
  154. package/node_modules/typebox/build/guard/emit.d.mts +3 -1
  155. package/node_modules/typebox/build/guard/emit.mjs +12 -5
  156. package/node_modules/typebox/build/guard/guard.d.mts +8 -2
  157. package/node_modules/typebox/build/guard/guard.mjs +25 -4
  158. package/node_modules/typebox/build/guard/string.d.mts +2 -2
  159. package/node_modules/typebox/build/guard/string.mjs +7 -7
  160. package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
  161. package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
  162. package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
  163. package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
  164. package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
  165. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
  166. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
  167. package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
  168. package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
  169. package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
  170. package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
  171. package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
  172. package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
  173. package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
  174. package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
  175. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
  176. package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
  177. package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
  178. package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
  179. package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
  180. package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
  181. package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
  182. package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
  183. package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
  184. package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
  185. package/node_modules/typebox/build/schema/types/index.mjs +0 -2
  186. package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
  187. package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
  188. package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
  189. package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
  190. package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
  191. package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
  192. package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
  193. package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
  194. package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
  195. package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
  196. package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
  197. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
  198. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
  199. package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
  200. package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
  201. package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
  202. package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
  203. package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
  204. package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
  205. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
  206. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
  207. package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
  208. package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
  209. package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
  210. package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
  211. package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
  212. package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
  213. package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
  214. package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
  215. package/node_modules/typebox/build/type/script/parser.mjs +27 -23
  216. package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
  217. package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
  218. package/node_modules/typebox/package.json +27 -27
  219. package/node_modules/typebox/readme.md +79 -82
  220. package/node_modules/ws/lib/permessage-deflate.js +3 -1
  221. package/node_modules/ws/package.json +1 -1
  222. package/openclaw.plugin.json +43 -1
  223. package/package.json +9 -9
  224. package/dist/account-configured-BwfXBo_F.js +0 -14
  225. package/dist/account-inspect-Drw2gAiN.js +0 -89
  226. package/dist/account-reply-mode-DrUXogvO.js +0 -14
  227. package/dist/action-runtime.runtime-D9I6uc0Q.js +0 -2
  228. package/dist/actions.runtime-DLFyUkvg.js +0 -2
  229. package/dist/runtime-api-Cj9nxBNv.js +0 -10
  230. package/node_modules/p-map/index.d.ts +0 -155
  231. package/node_modules/p-map/index.js +0 -285
  232. package/node_modules/p-map/license +0 -9
  233. package/node_modules/p-map/package.json +0 -57
  234. package/node_modules/p-map/readme.md +0 -190
  235. package/node_modules/typebox/build/format/_idna.d.mts +0 -2
  236. package/node_modules/typebox/build/format/_idna.mjs +0 -246
  237. package/node_modules/typebox/build/format/_puny.d.mts +0 -1
  238. package/node_modules/typebox/build/format/_puny.mjs +0 -77
  239. package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
  240. package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
  241. package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
  242. package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
  243. package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
  244. package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
  245. package/dist/{security-audit-DR097212.js → security-audit-B_yKr7MW.js} +1 -1
@@ -1,26 +1,43 @@
1
- import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-CK4AVI2_.js";
1
+ import { n as isSlackPluginAccountConfigured } from "./account-configured-sUohAxZr.js";
2
+ import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-Dm_H77gH.js";
2
3
  import { a as parseSlackTarget, n as formatSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-BnMD2ZqZ.js";
3
- import { t as isSlackPluginAccountConfigured } from "./account-configured-BwfXBo_F.js";
4
+ import { t as slackContextTargetsMatch } from "./targets-Cx5W_n3W.js";
4
5
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
5
6
  import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringifiedOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
7
  import { normalizeMessageChannel } from "openclaw/plugin-sdk/routing";
7
8
  import { FormatCapabilityProfile, chunkTextForOutbound, markdownToIR, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers } from "openclaw/plugin-sdk/text-chunking";
9
+ import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
8
10
  import { buildChannelKeyCandidates } from "openclaw/plugin-sdk/channel-targets";
9
- import { createNativeApprovalChannelRouteGates, doesApprovalRequestSelectChannelAccount, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
11
+ import { createNativeApprovalChannelRouteGates, doesApprovalRequestSelectChannelAccount, resolveApprovalKind, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
10
12
  import { createChannelApprovalAuth, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
11
13
  import { createChannelExecApprovalProfile, isChannelExecApprovalClientEnabledFromConfig, isChannelExecApprovalTargetRecipient, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
12
14
  import { channelRouteTargetsMatchExact, stringifyRouteThreadId } from "openclaw/plugin-sdk/channel-route";
13
15
  import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
14
- import { normalizeMessagePresentation, reduceLegacyInteractiveReply, renderMessagePresentationChartFallbackText, renderMessagePresentationFallbackText, renderMessagePresentationTableFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
16
+ import { legacyInteractiveReplyToPresentation, normalizeMessagePresentation, renderMessagePresentationChartFallbackText, renderMessagePresentationFallbackText, renderMessagePresentationTableFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
15
17
  import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
16
18
  import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
19
+ import { eastAsianWidthType } from "get-east-asian-width";
17
20
  import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
18
21
  import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
19
- import { eastAsianWidthType } from "get-east-asian-width";
20
22
  import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
21
23
  import { compileAllowlist, resolveCompiledAllowlistMatch } from "openclaw/plugin-sdk/allow-from";
22
24
  import { normalizeHyphenSlug, normalizeStringEntries as normalizeStringEntries$1, normalizeStringEntriesLower } from "openclaw/plugin-sdk/string-normalization-runtime";
23
25
  import { resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
26
+ //#region extensions/slack/src/action-threading.ts
27
+ const SLACK_PRIVATE_ACTION_DELIVERY_RESULT = Symbol("slack.action.delivery-result");
28
+ function resolveSlackAutoThreadId(params) {
29
+ const context = params.toolContext;
30
+ if (!context?.currentChannelId && !context?.currentMessagingTarget) return;
31
+ if (!slackContextTargetsMatch(params.to, context)) return;
32
+ if (!context.currentThreadTs) {
33
+ if (context.sameChannelThreadRequired) throw new Error("Slack thread context is required for same-channel replies from a threaded Slack turn. Set topLevel=true or threadId=null to post at the channel root.");
34
+ return;
35
+ }
36
+ if (context.replyToMode !== "all" && !isSingleUseReplyToMode(context.replyToMode ?? "off")) return;
37
+ if (isSingleUseReplyToMode(context.replyToMode ?? "off") && context.hasRepliedRef?.value) return;
38
+ return context.currentThreadTs;
39
+ }
40
+ //#endregion
24
41
  //#region extensions/slack/src/exec-approvals.ts
25
42
  function normalizeSlackUserLikeId(value) {
26
43
  const upper = value.toUpperCase();
@@ -124,11 +141,6 @@ function isSlackWorkspaceInstallation(accountId) {
124
141
  const DEFAULT_APPROVAL_FORWARDING_MODE = "session";
125
142
  const SLACK_DM_CHANNEL_ID_RE = /^D[A-Z0-9]{8,}$/i;
126
143
  const SLACK_USER_ID_RE = /^[UW][A-Z0-9]{8,}$/i;
127
- function resolveSlackApprovalKind(request) {
128
- const isExec = "command" in request.request;
129
- if (isExec === ("title" in request.request && "description" in request.request)) throw new Error("Slack approval request payload does not identify exactly one owner");
130
- return isExec ? "exec" : "plugin";
131
- }
132
144
  function isSlackApprovalTransportEnabled(params) {
133
145
  return isSlackPluginAccountConfigured(resolveSlackAccount(params));
134
146
  }
@@ -343,7 +355,7 @@ function isSlackAnyNativeApprovalClientEnabled(params) {
343
355
  }
344
356
  function shouldHandleSlackNativeApprovalRequest(params) {
345
357
  if (getSlackInstallationKind(resolveSlackAccount(params).accountId) === "enterprise" && !resolveEnterpriseApprovalTeamId(params.request)) return false;
346
- if ((params.approvalKind ?? resolveSlackApprovalKind(params.request)) === "plugin") return shouldHandleSlackPluginViaNativeClientConfig(params) || shouldHandleSlackPluginViaForwarding(params);
358
+ if (resolveApprovalKind(params.request, params.approvalKind) === "plugin") return shouldHandleSlackPluginViaNativeClientConfig(params) || shouldHandleSlackPluginViaForwarding(params);
347
359
  const turnSourceChannel = normalizeMessageChannel(params.request.request.turnSourceChannel);
348
360
  if (turnSourceChannel && turnSourceChannel !== "slack") return false;
349
361
  if (!doesApprovalRequestSelectChannelAccount({
@@ -426,6 +438,7 @@ const SLACK_PRESENTATION_CAPABILITIES = {
426
438
  //#endregion
427
439
  //#region extensions/slack/src/approval-actions.ts
428
440
  const SLACK_APPROVAL_VALUE_PREFIX = "openclaw:approval:v1:";
441
+ const SLACK_APPROVAL_HEADER_BLOCK_ID = "openclaw_approval_header";
429
442
  function isApprovalDecision(value) {
430
443
  return value === "allow-once" || value === "allow-always" || value === "deny";
431
444
  }
@@ -911,123 +924,474 @@ function renderSlackDataVisualizationMrkdwnFallbackText(value) {
911
924
  return typeof block.title === "string" && block.title.trim() ? escapeSlackMrkdwn(block.title.trim()) : void 0;
912
925
  }
913
926
  //#endregion
914
- //#region extensions/slack/src/question-actions.ts
915
- const SLACK_QUESTION_VALUE_PREFIX = "slq1:";
916
- const QUESTION_RECORD_ID_PATTERN = /^ask_[a-f0-9]{32}$/u;
917
- function encodeSlackQuestionAction(action) {
918
- if (!QUESTION_RECORD_ID_PATTERN.test(action.questionId) || !Number.isInteger(action.optionIndex) || action.optionIndex < 0 || action.optionIndex > 3) return;
919
- const value = `${SLACK_QUESTION_VALUE_PREFIX}${action.questionId}:${action.optionIndex}`;
920
- return value.length <= 2e3 ? value : void 0;
927
+ //#region extensions/slack/src/format.ts
928
+ function escapeSlackMrkdwnSegment(text) {
929
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
921
930
  }
922
- function decodeSlackQuestionAction(value) {
923
- if (typeof value !== "string" || value.length > 2e3) return null;
924
- const match = /^slq1:(ask_[a-f0-9]{32}):([0-3])$/u.exec(value);
925
- return match?.[1] && match[2] ? {
926
- questionId: match[1],
927
- optionIndex: Number(match[2])
928
- } : null;
931
+ const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
932
+ function isAllowedSlackAngleToken(token) {
933
+ if (!token.startsWith("<") || !token.endsWith(">")) return false;
934
+ const inner = token.slice(1, -1);
935
+ return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
929
936
  }
930
- async function resolveSlackQuestionAction(params) {
931
- let result;
932
- try {
933
- result = await (params.resolveQuestion ?? questionGatewayRuntime.resolveOption)({
934
- cfg: params.cfg,
935
- questionId: params.action.questionId,
936
- optionIndex: params.action.optionIndex,
937
- senderId: params.userId,
938
- clientDisplayName: `Slack question (${params.accountId})`
939
- });
940
- } catch {
941
- await params.respond("Could not submit this answer.").catch(() => {});
942
- return;
937
+ function escapeSlackMrkdwnContent(text) {
938
+ if (!text) return "";
939
+ if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
940
+ SLACK_ANGLE_TOKEN_RE.lastIndex = 0;
941
+ const out = [];
942
+ let lastIndex = 0;
943
+ for (let match = SLACK_ANGLE_TOKEN_RE.exec(text); match; match = SLACK_ANGLE_TOKEN_RE.exec(text)) {
944
+ const matchIndex = match.index ?? 0;
945
+ out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex, matchIndex)));
946
+ const token = match[0] ?? "";
947
+ out.push(isAllowedSlackAngleToken(token) ? token : escapeSlackMrkdwnSegment(token));
948
+ lastIndex = matchIndex + token.length;
943
949
  }
944
- await params.respond(result.status === "answered" ? "Answer submitted." : "This question was already answered.").catch(() => {});
945
- }
946
- //#endregion
947
- //#region extensions/slack/src/reply-action-ids.ts
948
- const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
949
- const SLACK_REPLY_LINK_ACTION_ID = "openclaw:reply_link";
950
- const SLACK_SESSION_LINK_ACTION_ID = "openclaw:session_link";
951
- const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
952
- const SLACK_CALLBACK_BUTTON_ACTION_ID = "openclaw:callback_button";
953
- const SLACK_CALLBACK_SELECT_ACTION_ID = "openclaw:callback_select";
954
- const SLACK_APPROVAL_BUTTON_ACTION_ID = "openclaw:approval_button";
955
- const SLACK_APPROVAL_SELECT_ACTION_ID = "openclaw:approval_select";
956
- const SLACK_QUESTION_BUTTON_ACTION_ID = "openclaw:question_button";
957
- const SLACK_QUESTION_FINALIZATION_BLOCKS = Symbol("slackQuestionFinalizationBlocks");
958
- function isSlackQuestionActionId(actionId) {
959
- return actionId === "openclaw:question_button" || actionId.startsWith(`openclaw:question_button:`);
960
- }
961
- /** Read only question control identities from the blocks actually sent to Slack. */
962
- function resolveSlackQuestionActionIds(blocks) {
963
- return (blocks ?? []).flatMap((block) => {
964
- if (block.type !== "actions") return [];
965
- return (block.elements ?? []).flatMap(({ action_id }) => action_id && isSlackQuestionActionId(action_id) ? [action_id] : []);
966
- });
967
- }
968
- function isSlackApprovalActionId(actionId) {
969
- return actionId === "openclaw:approval_button" || actionId === "openclaw:approval_select" || actionId.startsWith(`openclaw:approval_button:`) || actionId.startsWith(`openclaw:approval_select:`);
970
- }
971
- function isSlackCallbackActionId(actionId) {
972
- return actionId === "openclaw:callback_button" || actionId === "openclaw:callback_select" || actionId.startsWith(`openclaw:callback_button:`) || actionId.startsWith(`openclaw:callback_select:`);
950
+ out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex)));
951
+ return out.join("");
973
952
  }
974
- //#endregion
975
- //#region extensions/slack/src/truncate.ts
976
- function truncateSlackText(value, max) {
977
- const trimmed = value.trim();
978
- if (trimmed.length <= max) return trimmed;
979
- if (max <= 1) return sliceUtf16Safe(trimmed, 0, max);
980
- return `${sliceUtf16Safe(trimmed, 0, max - 1)}…`;
953
+ function escapeSlackMrkdwnText(text) {
954
+ if (!text) return "";
955
+ if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
956
+ return text.split("\n").map((line) => {
957
+ if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2))}`;
958
+ return escapeSlackMrkdwnContent(line);
959
+ }).join("\n");
981
960
  }
982
- function countSlackTextUtf8Bytes(value) {
983
- return Buffer.byteLength(value, "utf8");
961
+ function buildSlackLink(link, text) {
962
+ const href = link.href.trim();
963
+ if (!href) return null;
964
+ const trimmedLabel = text.slice(link.start, link.end).trim();
965
+ const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
966
+ if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
967
+ const safeHref = escapeSlackMrkdwnSegment(href);
968
+ return {
969
+ start: link.start,
970
+ end: link.end,
971
+ open: `<${safeHref}|`,
972
+ close: ">"
973
+ };
984
974
  }
985
- /** Truncate Slack text without splitting a code point or exceeding a UTF-8 byte limit. */
986
- function truncateSlackTextByUtf8Bytes(value, maxBytes) {
987
- const trimmed = value.trim();
988
- if (maxBytes <= 0) return "";
989
- if (countSlackTextUtf8Bytes(trimmed) <= maxBytes) return trimmed;
990
- const suffix = "…";
991
- const suffixBytes = countSlackTextUtf8Bytes(suffix);
992
- const prefixBudget = maxBytes >= suffixBytes ? maxBytes - suffixBytes : maxBytes;
993
- let prefix = "";
994
- let prefixBytes = 0;
995
- for (const character of trimmed) {
996
- const characterBytes = countSlackTextUtf8Bytes(character);
997
- if (prefixBytes + characterBytes > prefixBudget) break;
998
- prefix += character;
999
- prefixBytes += characterBytes;
975
+ const SLACK_MRKDWN_WORD_CHARACTER_RE = /[\p{L}\p{M}\p{N}_]/u;
976
+ const SLACK_MRKDWN_PUNCTUATION_RE = /\p{P}/u;
977
+ const SLACK_MRKDWN_SYMBOL_RE = /\p{S}/u;
978
+ const SLACK_MRKDWN_CJK_SCRIPT_RE = /[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u;
979
+ const SLACK_MRKDWN_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
980
+ function getCodePointBefore(text, index) {
981
+ if (index <= 0) return "";
982
+ const lastCodeUnit = text.charCodeAt(index - 1);
983
+ if (lastCodeUnit >= 56320 && lastCodeUnit <= 57343 && index > 1) {
984
+ const previousCodeUnit = text.charCodeAt(index - 2);
985
+ if (previousCodeUnit >= 55296 && previousCodeUnit <= 56319) return text.slice(index - 2, index);
1000
986
  }
1001
- return maxBytes >= suffixBytes ? `${prefix}${suffix}` : prefix;
1002
- }
1003
- //#endregion
1004
- //#region extensions/slack/src/blocks-render.ts
1005
- const SLACK_BUTTON_URL_MAX = 3e3;
1006
- function buildSlackReplyButtonActionId(buttonIndex, choiceIndex) {
1007
- return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
987
+ return text[index - 1] ?? "";
1008
988
  }
1009
- function buildSlackReplyLinkActionId(buttonIndex, choiceIndex) {
1010
- return `${SLACK_REPLY_LINK_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
989
+ function getCodePointAt(text, index) {
990
+ const codePoint = text.codePointAt(index);
991
+ return codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
1011
992
  }
1012
- function buildSlackReplySelectActionId(selectIndex) {
1013
- return `${SLACK_REPLY_SELECT_ACTION_ID}:${String(selectIndex)}`;
993
+ function isSlackCjkPunctuation(character) {
994
+ if (!SLACK_MRKDWN_PUNCTUATION_RE.test(character)) return false;
995
+ if (SLACK_MRKDWN_CJK_SCRIPT_RE.test(character)) return true;
996
+ const codePoint = character.codePointAt(0);
997
+ if (codePoint === void 0) return false;
998
+ const width = eastAsianWidthType(codePoint);
999
+ return width === "fullwidth" || width === "halfwidth" || width === "wide" && !SLACK_MRKDWN_EMOJI_PRESENTATION_RE.test(character);
1014
1000
  }
1015
- function buildSlackApprovalButtonActionId(buttonIndex, choiceIndex) {
1016
- return `${SLACK_APPROVAL_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1001
+ function isUnsafeSlackEmphasisBoundary(character) {
1002
+ if (SLACK_MRKDWN_WORD_CHARACTER_RE.test(character)) return true;
1003
+ const codePoint = character.codePointAt(0);
1004
+ if (codePoint === void 0 || codePoint <= 127) return false;
1005
+ return SLACK_MRKDWN_SYMBOL_RE.test(character) || isSlackCjkPunctuation(character);
1017
1006
  }
1018
- function buildSlackApprovalSelectActionId(selectIndex) {
1019
- return `${SLACK_APPROVAL_SELECT_ACTION_ID}:${String(selectIndex)}`;
1007
+ function makeSlackEmphasisStylesSafe(ir) {
1008
+ const styles = ir.styles.filter((span) => {
1009
+ if (span.style !== "italic" && span.style !== "bold") return true;
1010
+ return !isUnsafeSlackEmphasisBoundary(getCodePointBefore(ir.text, span.start)) && !isUnsafeSlackEmphasisBoundary(getCodePointAt(ir.text, span.end));
1011
+ });
1012
+ return styles.length === ir.styles.length ? ir : {
1013
+ ...ir,
1014
+ styles
1015
+ };
1020
1016
  }
1021
- function buildSlackCallbackButtonActionId(buttonIndex, choiceIndex) {
1022
- return `${SLACK_CALLBACK_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1017
+ const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
1018
+ mechanism: "markdown",
1019
+ constructs: {
1020
+ underline: "strip",
1021
+ spoiler: "fallback",
1022
+ codeLanguage: "fallback",
1023
+ heading: "fallback",
1024
+ bulletList: "fallback",
1025
+ orderedList: "fallback",
1026
+ taskList: "fallback",
1027
+ table: "fallback",
1028
+ image: "fallback"
1029
+ },
1030
+ chunk: {
1031
+ limit: 4e3,
1032
+ unit: "chars",
1033
+ hardCap: 4e4
1034
+ }
1035
+ });
1036
+ const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
1037
+ function tokenizeSlackMrkdwn(text) {
1038
+ const tokens = [];
1039
+ for (let index = 0; index < text.length;) {
1040
+ if (text.startsWith("```", index)) {
1041
+ tokens.push("```");
1042
+ index += 3;
1043
+ continue;
1044
+ }
1045
+ const entity = [
1046
+ "&amp;",
1047
+ "&lt;",
1048
+ "&gt;"
1049
+ ].find((candidate) => text.startsWith(candidate, index));
1050
+ if (entity) {
1051
+ tokens.push(entity);
1052
+ index += entity.length;
1053
+ continue;
1054
+ }
1055
+ if (text[index] === "<") {
1056
+ const end = text.indexOf(">", index + 1);
1057
+ const angleToken = end >= 0 ? text.slice(index, end + 1) : void 0;
1058
+ if (angleToken && !angleToken.includes("\n") && isAllowedSlackAngleToken(angleToken)) {
1059
+ tokens.push(angleToken);
1060
+ index += angleToken.length;
1061
+ continue;
1062
+ }
1063
+ }
1064
+ const codePoint = text.codePointAt(index);
1065
+ if (codePoint === void 0) break;
1066
+ const character = String.fromCodePoint(codePoint);
1067
+ index += character.length;
1068
+ if (character === "\\" && index < text.length) {
1069
+ const escapedCodePoint = text.codePointAt(index);
1070
+ if (escapedCodePoint !== void 0) {
1071
+ const escapedCharacter = String.fromCodePoint(escapedCodePoint);
1072
+ tokens.push(character + escapedCharacter);
1073
+ index += escapedCharacter.length;
1074
+ continue;
1075
+ }
1076
+ }
1077
+ tokens.push(character);
1078
+ }
1079
+ return tokens;
1023
1080
  }
1024
- function buildSlackCallbackSelectActionId(selectIndex) {
1025
- return `${SLACK_CALLBACK_SELECT_ACTION_ID}:${String(selectIndex)}`;
1081
+ function resolveSlackCodeMarkerTransition(active, token) {
1082
+ if (token === "```" && active !== "`") return active === "```" ? void 0 : "```";
1083
+ if (token === "`" && active !== "```") return active === "`" ? void 0 : "`";
1084
+ return null;
1026
1085
  }
1027
- function buildSlackQuestionButtonActionId(buttonIndex, choiceIndex) {
1028
- return `${SLACK_QUESTION_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1086
+ function maskSlackExcludedText(text) {
1087
+ return text.split("\n").map((line) => line.trim() ? `x${" ".repeat(Math.max(0, line.length - 1))}` : " ".repeat(line.length)).join("\n");
1029
1088
  }
1030
- function resolveSlackButtonStyle(style) {
1089
+ function maskSlackExcludedRanges(projection) {
1090
+ let masked = "";
1091
+ let cursor = 0;
1092
+ for (const range of projection.excludedRanges) {
1093
+ masked += projection.text.slice(cursor, range.start);
1094
+ masked += maskSlackExcludedText(projection.text.slice(range.start, range.end));
1095
+ cursor = range.end;
1096
+ }
1097
+ return masked + projection.text.slice(cursor);
1098
+ }
1099
+ function slackProjectionHasRoleHeader(projection) {
1100
+ return Boolean(markdownToIR(maskSlackExcludedRanges(projection), {
1101
+ assistantTranscriptRoleHeaders: true,
1102
+ autolink: false,
1103
+ blockquotePrefix: "",
1104
+ headingStyle: "none",
1105
+ linkify: false,
1106
+ tableMode: "off"
1107
+ }).annotations?.some((annotation) => annotation.type === "assistant_transcript_role"));
1108
+ }
1109
+ function decodeSlackMrkdwnEntities(text) {
1110
+ return text.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">");
1111
+ }
1112
+ function projectSlackAngleToken(token, dateDisplay) {
1113
+ const inner = token.slice(1, -1);
1114
+ if (inner.startsWith("!date^")) {
1115
+ const fallbackSeparator = inner.indexOf("|");
1116
+ const tokenString = (fallbackSeparator === -1 ? inner : inner.slice(0, fallbackSeparator)).split("^")[2] ?? "";
1117
+ const fallback = fallbackSeparator === -1 ? "" : inner.slice(fallbackSeparator + 1);
1118
+ return decodeSlackMrkdwnEntities(dateDisplay === "fallback" ? fallback || tokenString : tokenString || fallback);
1119
+ }
1120
+ const labelSeparator = inner.indexOf("|");
1121
+ if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
1122
+ if (inner.startsWith("@")) return "@";
1123
+ if (inner.startsWith("#")) return "#";
1124
+ if (inner.startsWith("!")) return "!";
1125
+ return decodeSlackMrkdwnEntities(inner);
1126
+ }
1127
+ function appendSlackVisibleProjection(projection, visible, excluded) {
1128
+ if (!visible) return;
1129
+ const start = projection.text.length;
1130
+ projection.text += visible;
1131
+ if (!excluded) return;
1132
+ const previous = projection.excludedRanges.at(-1);
1133
+ if (previous?.end === start) previous.end = projection.text.length;
1134
+ else projection.excludedRanges.push({
1135
+ start,
1136
+ end: projection.text.length
1137
+ });
1138
+ }
1139
+ function projectSlackMrkdwnVisibleText(text, dateDisplay) {
1140
+ const projection = {
1141
+ text: "",
1142
+ excludedRanges: []
1143
+ };
1144
+ let activeMarker;
1145
+ let lineHasVisibleContent = false;
1146
+ for (const token of tokenizeSlackMrkdwn(text)) {
1147
+ const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
1148
+ if (transition !== null) {
1149
+ activeMarker = transition;
1150
+ continue;
1151
+ }
1152
+ let visible = token;
1153
+ if (isAllowedSlackAngleToken(token)) visible = activeMarker ? token : projectSlackAngleToken(token, dateDisplay);
1154
+ else if (token === "&amp;" || token === "&lt;" || token === "&gt;") visible = decodeSlackMrkdwnEntities(token);
1155
+ else if (!activeMarker && (token === "*" || token === "_" || token === "~")) visible = "";
1156
+ else if (!activeMarker && token === ">" && !lineHasVisibleContent) visible = "";
1157
+ else if (token.startsWith("\\") && token.length > 1) visible = token.slice(1);
1158
+ appendSlackVisibleProjection(projection, visible, activeMarker !== void 0);
1159
+ for (const character of visible) if (character === "\n") lineHasVisibleContent = false;
1160
+ else if (character !== " " && character !== " " && character !== "\r") lineHasVisibleContent = true;
1161
+ }
1162
+ return projection;
1163
+ }
1164
+ function protectSlackAssistantTranscriptRoleHeaders(text) {
1165
+ if (text.startsWith(SLACK_ASSISTANT_TRANSCRIPT_PREFIX)) return text;
1166
+ const tokenProjection = projectSlackMrkdwnVisibleText(text, "token");
1167
+ const fallbackProjection = projectSlackMrkdwnVisibleText(text, "fallback");
1168
+ if (!slackProjectionHasRoleHeader(tokenProjection) && !slackProjectionHasRoleHeader(fallbackProjection)) return text;
1169
+ return `${SLACK_ASSISTANT_TRANSCRIPT_PREFIX}${text}`;
1170
+ }
1171
+ function buildSlackRenderOptions() {
1172
+ return {
1173
+ annotationMarkers: { assistant_transcript_role: {
1174
+ open: "`",
1175
+ close: "`",
1176
+ suppressNestedFormatting: true
1177
+ } },
1178
+ styleMarkers: {
1179
+ bold: {
1180
+ open: "*",
1181
+ close: "*"
1182
+ },
1183
+ italic: {
1184
+ open: "_",
1185
+ close: "_"
1186
+ },
1187
+ strikethrough: {
1188
+ open: "~",
1189
+ close: "~"
1190
+ },
1191
+ code: {
1192
+ open: "`",
1193
+ close: "`"
1194
+ },
1195
+ code_block: {
1196
+ open: "```\n",
1197
+ close: "```"
1198
+ }
1199
+ },
1200
+ escapeText: escapeSlackMrkdwnText,
1201
+ buildLink: buildSlackLink
1202
+ };
1203
+ }
1204
+ function markdownToSlackMrkdwn(markdown, options = {}) {
1205
+ return renderMarkdownWithMarkers(makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
1206
+ assistantTranscriptRoleHeaders: true,
1207
+ linkify: false,
1208
+ autolink: false,
1209
+ headingStyle: "rich",
1210
+ blockquotePrefix: "> ",
1211
+ tableMode: options.tableMode
1212
+ })), buildSlackRenderOptions(), SLACK_FORMAT_PROFILE);
1213
+ }
1214
+ function normalizeSlackOutboundText(markdown) {
1215
+ return protectSlackAssistantTranscriptRoleHeaders(markdownToSlackMrkdwn(markdown ?? ""));
1216
+ }
1217
+ /** Chunk already-rendered Slack mrkdwn without splitting entities or code markers. */
1218
+ function chunkSlackMrkdwnText(text, limit) {
1219
+ if (text.length <= limit) return [text];
1220
+ if (!(text.includes("`") || text.includes("&amp;") || text.includes("&lt;") || text.includes("&gt;") || (text.match(/<[^>\n]+>/gu)?.some(isAllowedSlackAngleToken) ?? false) || /\\[\s\S]/u.test(text))) return chunkTextForOutbound(text, limit, { preserveWhitespace: true });
1221
+ const chunks = [];
1222
+ let activeMarker;
1223
+ let content = "";
1224
+ const wrapper = (marker) => marker && limit > marker.length * 2 ? marker : void 0;
1225
+ const capacity = (marker) => limit - (wrapper(marker)?.length ?? 0);
1226
+ const flush = () => {
1227
+ const marker = wrapper(activeMarker);
1228
+ if (content && content !== marker) chunks.push(marker ? `${content}${marker}` : content);
1229
+ content = "";
1230
+ };
1231
+ for (const token of tokenizeSlackMrkdwn(text)) {
1232
+ const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
1233
+ const nextMarker = transition === null ? activeMarker : transition;
1234
+ const sourceMarker = token === "`" || token === "```" ? token : void 0;
1235
+ if (transition !== null && sourceMarker && !wrapper(sourceMarker)) {
1236
+ activeMarker = nextMarker;
1237
+ continue;
1238
+ }
1239
+ if (content && content.length + token.length > capacity(nextMarker)) flush();
1240
+ activeMarker = nextMarker;
1241
+ if (!content && transition === void 0) continue;
1242
+ content ||= transition === null ? wrapper(activeMarker) ?? "" : "";
1243
+ const contentLimit = capacity(activeMarker) - (wrapper(activeMarker)?.length ?? 0);
1244
+ if (token.length > contentLimit) {
1245
+ flush();
1246
+ const marker = wrapper(activeMarker);
1247
+ if (activeMarker && isAllowedSlackAngleToken(token)) {
1248
+ if (marker) chunks.push(...chunkTextForOutbound(token, Math.max(1, Math.floor(contentLimit)), { preserveWhitespace: true }).map((fragment) => `${marker}${fragment}${marker}`));
1249
+ else chunks.push(...chunkTextForOutbound(escapeSlackMrkdwnSegment(token), Math.max(1, Math.floor(limit)), { preserveWhitespace: true }));
1250
+ continue;
1251
+ }
1252
+ chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
1253
+ continue;
1254
+ }
1255
+ content += token;
1256
+ }
1257
+ flush();
1258
+ return chunks;
1259
+ }
1260
+ function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
1261
+ const ir = makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
1262
+ assistantTranscriptRoleHeaders: true,
1263
+ linkify: false,
1264
+ autolink: false,
1265
+ headingStyle: "rich",
1266
+ blockquotePrefix: "> ",
1267
+ tableMode: options.tableMode
1268
+ }));
1269
+ const renderOptions = buildSlackRenderOptions();
1270
+ return renderMarkdownIRChunksWithinLimit({
1271
+ ir,
1272
+ limit,
1273
+ renderChunk: (chunk) => protectSlackAssistantTranscriptRoleHeaders(renderMarkdownWithMarkers(chunk, renderOptions, SLACK_FORMAT_PROFILE)),
1274
+ measureRendered: (rendered) => rendered.length
1275
+ }).map(({ rendered }) => rendered);
1276
+ }
1277
+ //#endregion
1278
+ //#region extensions/slack/src/question-actions.ts
1279
+ const SLACK_QUESTION_VALUE_PREFIX = "slq1:";
1280
+ const QUESTION_RECORD_ID_PATTERN = /^ask_[a-f0-9]{32}$/u;
1281
+ function encodeSlackQuestionAction(action) {
1282
+ if (!QUESTION_RECORD_ID_PATTERN.test(action.questionId) || !Number.isInteger(action.optionIndex) || action.optionIndex < 0 || action.optionIndex > 3) return;
1283
+ const value = `${SLACK_QUESTION_VALUE_PREFIX}${action.questionId}:${action.optionIndex}`;
1284
+ return value.length <= 2e3 ? value : void 0;
1285
+ }
1286
+ function decodeSlackQuestionAction(value) {
1287
+ if (typeof value !== "string" || value.length > 2e3) return null;
1288
+ const match = /^slq1:(ask_[a-f0-9]{32}):([0-3])$/u.exec(value);
1289
+ return match?.[1] && match[2] ? {
1290
+ questionId: match[1],
1291
+ optionIndex: Number(match[2])
1292
+ } : null;
1293
+ }
1294
+ async function resolveSlackQuestionAction(params) {
1295
+ let result;
1296
+ try {
1297
+ result = await (params.resolveQuestion ?? questionGatewayRuntime.resolveOption)({
1298
+ cfg: params.cfg,
1299
+ questionId: params.action.questionId,
1300
+ optionIndex: params.action.optionIndex,
1301
+ senderId: params.userId,
1302
+ clientDisplayName: `Slack question (${params.accountId})`
1303
+ });
1304
+ } catch {
1305
+ await params.respond("Could not submit this answer.").catch(() => {});
1306
+ return;
1307
+ }
1308
+ await params.respond(result.status === "answered" ? "Answer submitted." : "This question was already answered.").catch(() => {});
1309
+ }
1310
+ //#endregion
1311
+ //#region extensions/slack/src/reply-action-ids.ts
1312
+ const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
1313
+ const SLACK_REPLY_LINK_ACTION_ID = "openclaw:reply_link";
1314
+ const SLACK_SESSION_LINK_ACTION_ID = "openclaw:session_link";
1315
+ const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
1316
+ const SLACK_CALLBACK_BUTTON_ACTION_ID = "openclaw:callback_button";
1317
+ const SLACK_CALLBACK_SELECT_ACTION_ID = "openclaw:callback_select";
1318
+ const SLACK_APPROVAL_BUTTON_ACTION_ID = "openclaw:approval_button";
1319
+ const SLACK_APPROVAL_SELECT_ACTION_ID = "openclaw:approval_select";
1320
+ const SLACK_QUESTION_BUTTON_ACTION_ID = "openclaw:question_button";
1321
+ const SLACK_QUESTION_FINALIZATION_BLOCKS = Symbol("slackQuestionFinalizationBlocks");
1322
+ function isSlackQuestionActionId(actionId) {
1323
+ return actionId === "openclaw:question_button" || actionId.startsWith(`openclaw:question_button:`);
1324
+ }
1325
+ /** Read only question control identities from the blocks actually sent to Slack. */
1326
+ function resolveSlackQuestionActionIds(blocks) {
1327
+ return (blocks ?? []).flatMap((block) => {
1328
+ if (block.type !== "actions") return [];
1329
+ return (block.elements ?? []).flatMap(({ action_id }) => action_id && isSlackQuestionActionId(action_id) ? [action_id] : []);
1330
+ });
1331
+ }
1332
+ function isSlackApprovalActionId(actionId) {
1333
+ return actionId === "openclaw:approval_button" || actionId === "openclaw:approval_select" || actionId.startsWith(`openclaw:approval_button:`) || actionId.startsWith(`openclaw:approval_select:`);
1334
+ }
1335
+ function isSlackCallbackActionId(actionId) {
1336
+ return actionId === "openclaw:callback_button" || actionId === "openclaw:callback_select" || actionId.startsWith(`openclaw:callback_button:`) || actionId.startsWith(`openclaw:callback_select:`);
1337
+ }
1338
+ //#endregion
1339
+ //#region extensions/slack/src/truncate.ts
1340
+ function truncateSlackText(value, max) {
1341
+ const trimmed = value.trim();
1342
+ if (trimmed.length <= max) return trimmed;
1343
+ if (max <= 1) return sliceUtf16Safe(trimmed, 0, max);
1344
+ return `${sliceUtf16Safe(trimmed, 0, max - 1)}…`;
1345
+ }
1346
+ function countSlackTextUtf8Bytes(value) {
1347
+ return Buffer.byteLength(value, "utf8");
1348
+ }
1349
+ /** Truncate Slack text without splitting a code point or exceeding a UTF-8 byte limit. */
1350
+ function truncateSlackTextByUtf8Bytes(value, maxBytes) {
1351
+ const trimmed = value.trim();
1352
+ if (maxBytes <= 0) return "";
1353
+ if (countSlackTextUtf8Bytes(trimmed) <= maxBytes) return trimmed;
1354
+ const suffix = "…";
1355
+ const suffixBytes = countSlackTextUtf8Bytes(suffix);
1356
+ const prefixBudget = maxBytes >= suffixBytes ? maxBytes - suffixBytes : maxBytes;
1357
+ let prefix = "";
1358
+ let prefixBytes = 0;
1359
+ for (const character of trimmed) {
1360
+ const characterBytes = countSlackTextUtf8Bytes(character);
1361
+ if (prefixBytes + characterBytes > prefixBudget) break;
1362
+ prefix += character;
1363
+ prefixBytes += characterBytes;
1364
+ }
1365
+ return maxBytes >= suffixBytes ? `${prefix}${suffix}` : prefix;
1366
+ }
1367
+ //#endregion
1368
+ //#region extensions/slack/src/blocks-render.ts
1369
+ const SLACK_BUTTON_URL_MAX = 3e3;
1370
+ function buildSlackReplyButtonActionId(buttonIndex, choiceIndex) {
1371
+ return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1372
+ }
1373
+ function buildSlackReplyLinkActionId(buttonIndex, choiceIndex) {
1374
+ return `${SLACK_REPLY_LINK_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1375
+ }
1376
+ function buildSlackReplySelectActionId(selectIndex) {
1377
+ return `${SLACK_REPLY_SELECT_ACTION_ID}:${String(selectIndex)}`;
1378
+ }
1379
+ function buildSlackApprovalButtonActionId(buttonIndex, choiceIndex) {
1380
+ return `${SLACK_APPROVAL_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1381
+ }
1382
+ function buildSlackApprovalSelectActionId(selectIndex) {
1383
+ return `${SLACK_APPROVAL_SELECT_ACTION_ID}:${String(selectIndex)}`;
1384
+ }
1385
+ function buildSlackCallbackButtonActionId(buttonIndex, choiceIndex) {
1386
+ return `${SLACK_CALLBACK_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1387
+ }
1388
+ function buildSlackCallbackSelectActionId(selectIndex) {
1389
+ return `${SLACK_CALLBACK_SELECT_ACTION_ID}:${String(selectIndex)}`;
1390
+ }
1391
+ function buildSlackQuestionButtonActionId(buttonIndex, choiceIndex) {
1392
+ return `${SLACK_QUESTION_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
1393
+ }
1394
+ function resolveSlackButtonStyle(style) {
1031
1395
  if (style === "primary" || style === "danger") return style;
1032
1396
  if (style === "success") return "primary";
1033
1397
  }
@@ -1132,86 +1496,13 @@ function resolveSlackBlockOffsets(blocks) {
1132
1496
  dataTableCellCharacterCountOffset,
1133
1497
  dataVisualizationCountOffset,
1134
1498
  selectIndexOffset
1135
- };
1136
- }
1137
- /**
1138
- * @deprecated Use buildSlackPresentationBlocks with MessagePresentation.
1139
- */
1140
- function buildSlackInteractiveBlocks(interactive, options = {}) {
1141
- return reduceLegacyInteractiveReply(interactive, {
1142
- blocks: [],
1143
- buttonIndex: options.buttonIndexOffset ?? 0,
1144
- selectIndex: options.selectIndexOffset ?? 0
1145
- }, (state, block) => {
1146
- if (block.type === "text") {
1147
- const trimmed = block.text.trim();
1148
- if (!trimmed) return state;
1149
- state.blocks.push({
1150
- type: "section",
1151
- text: {
1152
- type: "mrkdwn",
1153
- text: truncateSlackText(trimmed, SLACK_SECTION_TEXT_MAX)
1154
- }
1155
- });
1156
- return state;
1157
- }
1158
- if (block.type === "buttons") {
1159
- const elements = block.buttons.flatMap((button, choiceIndex) => {
1160
- const target = resolveSlackButtonTarget(button, choiceIndex);
1161
- if (!target || (target.kind === "link" ? !isWithinSlackLimit(target.url, SLACK_BUTTON_URL_MAX) : !isWithinSlackLimit(target.value, 2e3))) return [];
1162
- const style = resolveSlackButtonStyle(button.style);
1163
- return [{
1164
- type: "button",
1165
- action_id: target.kind === "link" ? buildSlackReplyLinkActionId(state.buttonIndex + 1, choiceIndex) : target.kind === "approval" ? buildSlackApprovalButtonActionId(state.buttonIndex + 1, choiceIndex) : target.kind === "callback" ? buildSlackCallbackButtonActionId(state.buttonIndex + 1, choiceIndex) : target.kind === "question" ? buildSlackQuestionButtonActionId(state.buttonIndex + 1, choiceIndex) : buildSlackReplyButtonActionId(state.buttonIndex + 1, choiceIndex),
1166
- text: {
1167
- type: "plain_text",
1168
- text: truncateSlackText(button.label, 75),
1169
- emoji: true
1170
- },
1171
- ...target.kind === "link" ? { url: target.url } : { value: target.value },
1172
- ...style ? { style } : {}
1173
- }];
1174
- }).slice(0, 25);
1175
- if (elements.length === 0) return state;
1176
- state.blocks.push({
1177
- type: "actions",
1178
- block_id: `openclaw_reply_buttons_${++state.buttonIndex}`,
1179
- elements
1180
- });
1181
- return state;
1182
- }
1183
- const optionsLocal = block.options.flatMap((option) => {
1184
- const target = resolveSlackOptionTarget(option);
1185
- return target ? [{
1186
- label: option.label,
1187
- ...target
1188
- }] : [];
1189
- }).filter(isRenderableSlackOption).slice(0, 100);
1190
- const optionKinds = new Set(optionsLocal.map((option) => option.kind));
1191
- if (optionsLocal.length === 0 || optionKinds.size !== 1) return state;
1192
- state.blocks.push({
1193
- type: "actions",
1194
- block_id: `openclaw_reply_select_${++state.selectIndex}`,
1195
- elements: [{
1196
- type: "static_select",
1197
- action_id: optionsLocal[0]?.kind === "approval" ? buildSlackApprovalSelectActionId(state.selectIndex) : optionsLocal[0]?.kind === "callback" ? buildSlackCallbackSelectActionId(state.selectIndex) : buildSlackReplySelectActionId(state.selectIndex),
1198
- placeholder: {
1199
- type: "plain_text",
1200
- text: truncateSlackText(normalizeOptionalString(block.placeholder) ?? "Choose an option", 75),
1201
- emoji: true
1202
- },
1203
- options: optionsLocal.map((option, _choiceIndex) => ({
1204
- text: {
1205
- type: "plain_text",
1206
- text: truncateSlackText(option.label, 75),
1207
- emoji: true
1208
- },
1209
- value: option.value
1210
- }))
1211
- }]
1212
- });
1213
- return state;
1214
- }).blocks;
1499
+ };
1500
+ }
1501
+ /**
1502
+ * @deprecated Use buildSlackPresentationBlocks with MessagePresentation.
1503
+ */
1504
+ function buildSlackInteractiveBlocks(interactive, options = {}) {
1505
+ return buildSlackPresentationBlocks(interactive ? legacyInteractiveReplyToPresentation(interactive) : void 0, options);
1215
1506
  }
1216
1507
  /** Render portable presentation blocks as Slack Block Kit blocks. */
1217
1508
  function buildSlackPresentationBlocks(presentation, options = {}) {
@@ -1234,19 +1525,18 @@ function buildSlackPresentationBlocks(presentation, options = {}) {
1234
1525
  if (block.type === "text" || block.type === "context") {
1235
1526
  const text = block.text.trim();
1236
1527
  if (!text) continue;
1237
- if (block.type === "context") blocks.push({
1528
+ for (const chunk of chunkSlackMrkdwnText(text, SLACK_SECTION_TEXT_MAX)) blocks.push(block.type === "context" ? {
1238
1529
  type: "context",
1239
1530
  elements: [{
1240
1531
  type: "mrkdwn",
1241
- text: truncateSlackText(text, SLACK_SECTION_TEXT_MAX),
1532
+ text: chunk,
1242
1533
  verbatim: true
1243
1534
  }]
1244
- });
1245
- else blocks.push({
1535
+ } : {
1246
1536
  type: "section",
1247
1537
  text: {
1248
1538
  type: "mrkdwn",
1249
- text: truncateSlackText(text, SLACK_SECTION_TEXT_MAX)
1539
+ text: chunk
1250
1540
  }
1251
1541
  });
1252
1542
  continue;
@@ -1343,10 +1633,7 @@ function canRenderSlackPresentation(presentation, options = {}) {
1343
1633
  if (!canRenderSlackPresentationTables(presentation, options)) return false;
1344
1634
  let dataVisualizationCount = options.dataVisualizationCountOffset ?? 0;
1345
1635
  for (const block of presentation.blocks) {
1346
- if (block.type === "text" || block.type === "context") {
1347
- if (!isWithinSlackLimit(block.text.trim(), 3e3)) return false;
1348
- continue;
1349
- }
1636
+ if (block.type === "text" || block.type === "context") continue;
1350
1637
  if (block.type === "buttons") {
1351
1638
  if (!(block.buttons.length <= 25 && block.buttons.every((button, choiceIndex) => {
1352
1639
  if (!isWithinSlackLimit(button.label, 75)) return false;
@@ -1483,462 +1770,101 @@ function renderSlackRichTextLeaf(element) {
1483
1770
  const range = normalizeOptionalString(element.range);
1484
1771
  return range ? escapeSlackMrkdwn(`<!${range}>`) : "";
1485
1772
  }
1486
- case "emoji": {
1487
- const name = normalizeOptionalString(element.name);
1488
- return name ? `:${name}:` : "";
1489
- }
1490
- case "date": return escapeSlackMrkdwn(normalizeOptionalString(element.fallback) ?? "");
1491
- default: return "";
1492
- }
1493
- }
1494
- function renderSlackRichTextElement(value) {
1495
- const element = asOptionalRecord(value);
1496
- if (!element) return "";
1497
- switch (element.type) {
1498
- case "rich_text_section":
1499
- case "rich_text_preformatted":
1500
- case "rich_text_quote": return renderSlackRichTextElements(element.elements, "");
1501
- case "rich_text_list": return renderSlackRichTextElements(element.elements, "\n");
1502
- default: return renderSlackRichTextLeaf(element);
1503
- }
1504
- }
1505
- function renderSlackRichTextElements(value, separator) {
1506
- if (!Array.isArray(value)) return "";
1507
- return value.map(renderSlackRichTextElement).filter(Boolean).join(separator);
1508
- }
1509
- function readImageText(block) {
1510
- const altText = normalizeOptionalString(block.alt_text);
1511
- return (altText ? escapeSlackMrkdwn(altText) : void 0) ?? readTextObject(block.title);
1512
- }
1513
- function readVideoText(block, options = {}) {
1514
- const altText = normalizeOptionalString(block.alt_text);
1515
- return readTextObject(block.title, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
1516
- }
1517
- function readContextText(block, options = {}) {
1518
- if (!Array.isArray(block.elements)) return;
1519
- const parts = block.elements.map((element) => {
1520
- const record = asOptionalRecord(element);
1521
- const altText = normalizeOptionalString(record?.alt_text);
1522
- return readTextObject(record, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
1523
- }).filter((part) => Boolean(part));
1524
- return parts.length > 0 ? parts.join(" ") : void 0;
1525
- }
1526
- function readControlElementText(value, options = {}) {
1527
- const element = asOptionalRecord(value);
1528
- const type = normalizeOptionalString(element?.type);
1529
- if (type === "button" || type === "workflow_button") return readTextValue(element?.text, options);
1530
- if (type && SLACK_SELECT_ELEMENT_TYPES.has(type)) return readTextObject(element?.placeholder, options);
1531
- }
1532
- function readControlElementsText(values, options = {}) {
1533
- const seen = /* @__PURE__ */ new Set();
1534
- const labels = [];
1535
- for (const value of values) {
1536
- const candidate = readControlElementText(value, options);
1537
- if (!candidate || seen.has(candidate)) continue;
1538
- seen.add(candidate);
1539
- labels.push(candidate);
1540
- }
1541
- return labels.length > 0 ? labels.join("\n") : void 0;
1542
- }
1543
- function readSectionText(block, options = {}) {
1544
- const parts = [readTextObject(block.text, options)];
1545
- if (Array.isArray(block.fields)) parts.push(...block.fields.map((field) => readTextObject(field, options)));
1546
- parts.push(readControlElementText(block.accessory, options));
1547
- const visibleParts = parts.filter((part) => Boolean(part));
1548
- return visibleParts.length > 0 ? visibleParts.join("\n") : void 0;
1549
- }
1550
- function readActionsText(block, options = {}) {
1551
- return Array.isArray(block.elements) ? readControlElementsText(block.elements, options) : void 0;
1552
- }
1553
- /** Read only user-visible text from one Slack block. */
1554
- function renderSlackBlockFallbackText(raw, options = {}) {
1555
- const block = asOptionalRecord(raw);
1556
- if (!block) return;
1557
- switch (block.type) {
1558
- case "rich_text": return normalizeOptionalString(renderSlackRichTextElements(block.elements, "\n"));
1559
- case "header": return readTextObject(block.text, options);
1560
- case "section": return readSectionText(block, options);
1561
- case "image": return readImageText(block) ?? "Shared an image";
1562
- case "video": return readVideoText(block, options) ?? "Shared a video";
1563
- case "file": return "Shared a file";
1564
- case "context": return readContextText(block, options);
1565
- case "actions": return readActionsText(block, options);
1566
- case "data_visualization": return options.nativeDataFormat === "plain" ? renderSlackDataVisualizationFallbackText(block) : renderSlackDataVisualizationMrkdwnFallbackText(block);
1567
- case "data_table": return options.nativeDataFormat === "plain" ? renderSlackDataTableFallbackText(block) : renderSlackDataTableMrkdwnFallbackText(block);
1568
- case "table": return options.nativeDataFormat === "plain" ? renderSlackTableFallbackText(block) : renderSlackTableMrkdwnFallbackText(block);
1569
- default: return;
1570
- }
1571
- }
1572
- function buildSlackBlocksFallbackText(blocks) {
1573
- for (const block of blocks) {
1574
- const text = renderSlackBlockFallbackText(block);
1575
- if (text) return text;
1576
- }
1577
- return "Shared a Block Kit message";
1578
- }
1579
- function buildSlackCompleteBlocksFallbackText(blocks) {
1580
- return blocks.map((block) => renderSlackBlockFallbackText(block)).filter(Boolean).join("\n\n").trim() || buildSlackBlocksFallbackText(blocks);
1581
- }
1582
- //#endregion
1583
- //#region extensions/slack/src/format.ts
1584
- function escapeSlackMrkdwnSegment(text) {
1585
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1586
- }
1587
- const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
1588
- function isAllowedSlackAngleToken(token) {
1589
- if (!token.startsWith("<") || !token.endsWith(">")) return false;
1590
- const inner = token.slice(1, -1);
1591
- return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
1592
- }
1593
- function escapeSlackMrkdwnContent(text) {
1594
- if (!text) return "";
1595
- if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
1596
- SLACK_ANGLE_TOKEN_RE.lastIndex = 0;
1597
- const out = [];
1598
- let lastIndex = 0;
1599
- for (let match = SLACK_ANGLE_TOKEN_RE.exec(text); match; match = SLACK_ANGLE_TOKEN_RE.exec(text)) {
1600
- const matchIndex = match.index ?? 0;
1601
- out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex, matchIndex)));
1602
- const token = match[0] ?? "";
1603
- out.push(isAllowedSlackAngleToken(token) ? token : escapeSlackMrkdwnSegment(token));
1604
- lastIndex = matchIndex + token.length;
1605
- }
1606
- out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex)));
1607
- return out.join("");
1608
- }
1609
- function escapeSlackMrkdwnText(text) {
1610
- if (!text) return "";
1611
- if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
1612
- return text.split("\n").map((line) => {
1613
- if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2))}`;
1614
- return escapeSlackMrkdwnContent(line);
1615
- }).join("\n");
1616
- }
1617
- function buildSlackLink(link, text) {
1618
- const href = link.href.trim();
1619
- if (!href) return null;
1620
- const trimmedLabel = text.slice(link.start, link.end).trim();
1621
- const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
1622
- if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
1623
- const safeHref = escapeSlackMrkdwnSegment(href);
1624
- return {
1625
- start: link.start,
1626
- end: link.end,
1627
- open: `<${safeHref}|`,
1628
- close: ">"
1629
- };
1630
- }
1631
- const SLACK_MRKDWN_WORD_CHARACTER_RE = /[\p{L}\p{M}\p{N}_]/u;
1632
- const SLACK_MRKDWN_PUNCTUATION_RE = /\p{P}/u;
1633
- const SLACK_MRKDWN_SYMBOL_RE = /\p{S}/u;
1634
- const SLACK_MRKDWN_CJK_SCRIPT_RE = /[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u;
1635
- const SLACK_MRKDWN_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
1636
- function getCodePointBefore(text, index) {
1637
- if (index <= 0) return "";
1638
- const lastCodeUnit = text.charCodeAt(index - 1);
1639
- if (lastCodeUnit >= 56320 && lastCodeUnit <= 57343 && index > 1) {
1640
- const previousCodeUnit = text.charCodeAt(index - 2);
1641
- if (previousCodeUnit >= 55296 && previousCodeUnit <= 56319) return text.slice(index - 2, index);
1642
- }
1643
- return text[index - 1] ?? "";
1644
- }
1645
- function getCodePointAt(text, index) {
1646
- const codePoint = text.codePointAt(index);
1647
- return codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
1648
- }
1649
- function isSlackCjkPunctuation(character) {
1650
- if (!SLACK_MRKDWN_PUNCTUATION_RE.test(character)) return false;
1651
- if (SLACK_MRKDWN_CJK_SCRIPT_RE.test(character)) return true;
1652
- const codePoint = character.codePointAt(0);
1653
- if (codePoint === void 0) return false;
1654
- const width = eastAsianWidthType(codePoint);
1655
- return width === "fullwidth" || width === "halfwidth" || width === "wide" && !SLACK_MRKDWN_EMOJI_PRESENTATION_RE.test(character);
1656
- }
1657
- function isUnsafeSlackEmphasisBoundary(character) {
1658
- if (SLACK_MRKDWN_WORD_CHARACTER_RE.test(character)) return true;
1659
- const codePoint = character.codePointAt(0);
1660
- if (codePoint === void 0 || codePoint <= 127) return false;
1661
- return SLACK_MRKDWN_SYMBOL_RE.test(character) || isSlackCjkPunctuation(character);
1662
- }
1663
- function makeSlackEmphasisStylesSafe(ir) {
1664
- const styles = ir.styles.filter((span) => {
1665
- if (span.style !== "italic" && span.style !== "bold") return true;
1666
- return !isUnsafeSlackEmphasisBoundary(getCodePointBefore(ir.text, span.start)) && !isUnsafeSlackEmphasisBoundary(getCodePointAt(ir.text, span.end));
1667
- });
1668
- return styles.length === ir.styles.length ? ir : {
1669
- ...ir,
1670
- styles
1671
- };
1672
- }
1673
- const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
1674
- mechanism: "markdown",
1675
- constructs: {
1676
- underline: "strip",
1677
- spoiler: "fallback",
1678
- codeLanguage: "fallback",
1679
- heading: "fallback",
1680
- bulletList: "fallback",
1681
- orderedList: "fallback",
1682
- taskList: "fallback",
1683
- table: "fallback",
1684
- image: "fallback"
1685
- },
1686
- chunk: {
1687
- limit: 4e3,
1688
- unit: "chars",
1689
- hardCap: 4e4
1690
- }
1691
- });
1692
- const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
1693
- function tokenizeSlackMrkdwn(text) {
1694
- const tokens = [];
1695
- for (let index = 0; index < text.length;) {
1696
- if (text.startsWith("```", index)) {
1697
- tokens.push("```");
1698
- index += 3;
1699
- continue;
1700
- }
1701
- const entity = [
1702
- "&amp;",
1703
- "&lt;",
1704
- "&gt;"
1705
- ].find((candidate) => text.startsWith(candidate, index));
1706
- if (entity) {
1707
- tokens.push(entity);
1708
- index += entity.length;
1709
- continue;
1710
- }
1711
- if (text[index] === "<") {
1712
- const end = text.indexOf(">", index + 1);
1713
- const angleToken = end >= 0 ? text.slice(index, end + 1) : void 0;
1714
- if (angleToken && !angleToken.includes("\n") && isAllowedSlackAngleToken(angleToken)) {
1715
- tokens.push(angleToken);
1716
- index += angleToken.length;
1717
- continue;
1718
- }
1719
- }
1720
- const codePoint = text.codePointAt(index);
1721
- if (codePoint === void 0) break;
1722
- const character = String.fromCodePoint(codePoint);
1723
- index += character.length;
1724
- if (character === "\\" && index < text.length) {
1725
- const escapedCodePoint = text.codePointAt(index);
1726
- if (escapedCodePoint !== void 0) {
1727
- const escapedCharacter = String.fromCodePoint(escapedCodePoint);
1728
- tokens.push(character + escapedCharacter);
1729
- index += escapedCharacter.length;
1730
- continue;
1731
- }
1773
+ case "emoji": {
1774
+ const name = normalizeOptionalString(element.name);
1775
+ return name ? `:${name}:` : "";
1732
1776
  }
1733
- tokens.push(character);
1777
+ case "date": return escapeSlackMrkdwn(normalizeOptionalString(element.fallback) ?? "");
1778
+ default: return "";
1734
1779
  }
1735
- return tokens;
1736
- }
1737
- function resolveSlackCodeMarkerTransition(active, token) {
1738
- if (token === "```" && active !== "`") return active === "```" ? void 0 : "```";
1739
- if (token === "`" && active !== "```") return active === "`" ? void 0 : "`";
1740
- return null;
1741
1780
  }
1742
- function maskSlackExcludedText(text) {
1743
- return text.split("\n").map((line) => line.trim() ? `x${" ".repeat(Math.max(0, line.length - 1))}` : " ".repeat(line.length)).join("\n");
1744
- }
1745
- function maskSlackExcludedRanges(projection) {
1746
- let masked = "";
1747
- let cursor = 0;
1748
- for (const range of projection.excludedRanges) {
1749
- masked += projection.text.slice(cursor, range.start);
1750
- masked += maskSlackExcludedText(projection.text.slice(range.start, range.end));
1751
- cursor = range.end;
1781
+ function renderSlackRichTextElement(value) {
1782
+ const element = asOptionalRecord(value);
1783
+ if (!element) return "";
1784
+ switch (element.type) {
1785
+ case "rich_text_section":
1786
+ case "rich_text_preformatted":
1787
+ case "rich_text_quote": return renderSlackRichTextElements(element.elements, "");
1788
+ case "rich_text_list": return renderSlackRichTextElements(element.elements, "\n");
1789
+ default: return renderSlackRichTextLeaf(element);
1752
1790
  }
1753
- return masked + projection.text.slice(cursor);
1754
1791
  }
1755
- function slackProjectionHasRoleHeader(projection) {
1756
- return Boolean(markdownToIR(maskSlackExcludedRanges(projection), {
1757
- assistantTranscriptRoleHeaders: true,
1758
- autolink: false,
1759
- blockquotePrefix: "",
1760
- headingStyle: "none",
1761
- linkify: false,
1762
- tableMode: "off"
1763
- }).annotations?.some((annotation) => annotation.type === "assistant_transcript_role"));
1764
- }
1765
- function decodeSlackMrkdwnEntities(text) {
1766
- return text.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">");
1792
+ function renderSlackRichTextElements(value, separator) {
1793
+ if (!Array.isArray(value)) return "";
1794
+ return value.map(renderSlackRichTextElement).filter(Boolean).join(separator);
1767
1795
  }
1768
- function projectSlackAngleToken(token, dateDisplay) {
1769
- const inner = token.slice(1, -1);
1770
- if (inner.startsWith("!date^")) {
1771
- const fallbackSeparator = inner.indexOf("|");
1772
- const tokenString = (fallbackSeparator === -1 ? inner : inner.slice(0, fallbackSeparator)).split("^")[2] ?? "";
1773
- const fallback = fallbackSeparator === -1 ? "" : inner.slice(fallbackSeparator + 1);
1774
- return decodeSlackMrkdwnEntities(dateDisplay === "fallback" ? fallback || tokenString : tokenString || fallback);
1775
- }
1776
- const labelSeparator = inner.indexOf("|");
1777
- if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
1778
- if (inner.startsWith("@")) return "@";
1779
- if (inner.startsWith("#")) return "#";
1780
- if (inner.startsWith("!")) return "!";
1781
- return decodeSlackMrkdwnEntities(inner);
1796
+ function readImageText(block) {
1797
+ const altText = normalizeOptionalString(block.alt_text);
1798
+ return (altText ? escapeSlackMrkdwn(altText) : void 0) ?? readTextObject(block.title);
1782
1799
  }
1783
- function appendSlackVisibleProjection(projection, visible, excluded) {
1784
- if (!visible) return;
1785
- const start = projection.text.length;
1786
- projection.text += visible;
1787
- if (!excluded) return;
1788
- const previous = projection.excludedRanges.at(-1);
1789
- if (previous?.end === start) previous.end = projection.text.length;
1790
- else projection.excludedRanges.push({
1791
- start,
1792
- end: projection.text.length
1793
- });
1800
+ function readVideoText(block, options = {}) {
1801
+ const altText = normalizeOptionalString(block.alt_text);
1802
+ return readTextObject(block.title, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
1794
1803
  }
1795
- function projectSlackMrkdwnVisibleText(text, dateDisplay) {
1796
- const projection = {
1797
- text: "",
1798
- excludedRanges: []
1799
- };
1800
- let activeMarker;
1801
- let lineHasVisibleContent = false;
1802
- for (const token of tokenizeSlackMrkdwn(text)) {
1803
- const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
1804
- if (transition !== null) {
1805
- activeMarker = transition;
1806
- continue;
1807
- }
1808
- let visible = token;
1809
- if (isAllowedSlackAngleToken(token)) visible = activeMarker ? token : projectSlackAngleToken(token, dateDisplay);
1810
- else if (token === "&amp;" || token === "&lt;" || token === "&gt;") visible = decodeSlackMrkdwnEntities(token);
1811
- else if (!activeMarker && (token === "*" || token === "_" || token === "~")) visible = "";
1812
- else if (!activeMarker && token === ">" && !lineHasVisibleContent) visible = "";
1813
- else if (token.startsWith("\\") && token.length > 1) visible = token.slice(1);
1814
- appendSlackVisibleProjection(projection, visible, activeMarker !== void 0);
1815
- for (const character of visible) if (character === "\n") lineHasVisibleContent = false;
1816
- else if (character !== " " && character !== " " && character !== "\r") lineHasVisibleContent = true;
1817
- }
1818
- return projection;
1804
+ function readContextText(block, options = {}) {
1805
+ if (!Array.isArray(block.elements)) return;
1806
+ const parts = block.elements.map((element) => {
1807
+ const record = asOptionalRecord(element);
1808
+ const altText = normalizeOptionalString(record?.alt_text);
1809
+ return readTextObject(record, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
1810
+ }).filter((part) => Boolean(part));
1811
+ return parts.length > 0 ? parts.join(" ") : void 0;
1819
1812
  }
1820
- function protectSlackAssistantTranscriptRoleHeaders(text) {
1821
- if (text.startsWith(SLACK_ASSISTANT_TRANSCRIPT_PREFIX)) return text;
1822
- const tokenProjection = projectSlackMrkdwnVisibleText(text, "token");
1823
- const fallbackProjection = projectSlackMrkdwnVisibleText(text, "fallback");
1824
- if (!slackProjectionHasRoleHeader(tokenProjection) && !slackProjectionHasRoleHeader(fallbackProjection)) return text;
1825
- return `${SLACK_ASSISTANT_TRANSCRIPT_PREFIX}${text}`;
1813
+ function readControlElementText(value, options = {}) {
1814
+ const element = asOptionalRecord(value);
1815
+ const type = normalizeOptionalString(element?.type);
1816
+ if (type === "button" || type === "workflow_button") return readTextValue(element?.text, options);
1817
+ if (type && SLACK_SELECT_ELEMENT_TYPES.has(type)) return readTextObject(element?.placeholder, options);
1826
1818
  }
1827
- function hardSliceSlackToken(token, limit) {
1828
- const chunks = [];
1829
- let chunk = "";
1830
- for (const character of token) {
1831
- if (chunk && chunk.length + character.length > limit) {
1832
- chunks.push(chunk);
1833
- chunk = "";
1834
- }
1835
- chunk += character;
1819
+ function readControlElementsText(values, options = {}) {
1820
+ const seen = /* @__PURE__ */ new Set();
1821
+ const labels = [];
1822
+ for (const value of values) {
1823
+ const candidate = readControlElementText(value, options);
1824
+ if (!candidate || seen.has(candidate)) continue;
1825
+ seen.add(candidate);
1826
+ labels.push(candidate);
1836
1827
  }
1837
- if (chunk) chunks.push(chunk);
1838
- return chunks;
1828
+ return labels.length > 0 ? labels.join("\n") : void 0;
1839
1829
  }
1840
- function buildSlackRenderOptions() {
1841
- return {
1842
- annotationMarkers: { assistant_transcript_role: {
1843
- open: "`",
1844
- close: "`",
1845
- suppressNestedFormatting: true
1846
- } },
1847
- styleMarkers: {
1848
- bold: {
1849
- open: "*",
1850
- close: "*"
1851
- },
1852
- italic: {
1853
- open: "_",
1854
- close: "_"
1855
- },
1856
- strikethrough: {
1857
- open: "~",
1858
- close: "~"
1859
- },
1860
- code: {
1861
- open: "`",
1862
- close: "`"
1863
- },
1864
- code_block: {
1865
- open: "```\n",
1866
- close: "```"
1867
- }
1868
- },
1869
- escapeText: escapeSlackMrkdwnText,
1870
- buildLink: buildSlackLink
1871
- };
1830
+ function readSectionText(block, options = {}) {
1831
+ const parts = [readTextObject(block.text, options)];
1832
+ if (Array.isArray(block.fields)) parts.push(...block.fields.map((field) => readTextObject(field, options)));
1833
+ parts.push(readControlElementText(block.accessory, options));
1834
+ const visibleParts = parts.filter((part) => Boolean(part));
1835
+ return visibleParts.length > 0 ? visibleParts.join("\n") : void 0;
1872
1836
  }
1873
- function markdownToSlackMrkdwn(markdown, options = {}) {
1874
- return renderMarkdownWithMarkers(makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
1875
- assistantTranscriptRoleHeaders: true,
1876
- linkify: false,
1877
- autolink: false,
1878
- headingStyle: "rich",
1879
- blockquotePrefix: "> ",
1880
- tableMode: options.tableMode
1881
- })), buildSlackRenderOptions(), SLACK_FORMAT_PROFILE);
1837
+ function readActionsText(block, options = {}) {
1838
+ return Array.isArray(block.elements) ? readControlElementsText(block.elements, options) : void 0;
1882
1839
  }
1883
- function normalizeSlackOutboundText(markdown) {
1884
- return protectSlackAssistantTranscriptRoleHeaders(markdownToSlackMrkdwn(markdown ?? ""));
1840
+ /** Read only user-visible text from one Slack block. */
1841
+ function renderSlackBlockFallbackText(raw, options = {}) {
1842
+ const block = asOptionalRecord(raw);
1843
+ if (!block) return;
1844
+ switch (block.type) {
1845
+ case "rich_text": return normalizeOptionalString(renderSlackRichTextElements(block.elements, "\n"));
1846
+ case "header": return readTextObject(block.text, options);
1847
+ case "section": return readSectionText(block, options);
1848
+ case "image": return readImageText(block) ?? "Shared an image";
1849
+ case "video": return readVideoText(block, options) ?? "Shared a video";
1850
+ case "file": return "Shared a file";
1851
+ case "context": return readContextText(block, options);
1852
+ case "actions": return readActionsText(block, options);
1853
+ case "data_visualization": return options.nativeDataFormat === "plain" ? renderSlackDataVisualizationFallbackText(block) : renderSlackDataVisualizationMrkdwnFallbackText(block);
1854
+ case "data_table": return options.nativeDataFormat === "plain" ? renderSlackDataTableFallbackText(block) : renderSlackDataTableMrkdwnFallbackText(block);
1855
+ case "table": return options.nativeDataFormat === "plain" ? renderSlackTableFallbackText(block) : renderSlackTableMrkdwnFallbackText(block);
1856
+ default: return;
1857
+ }
1885
1858
  }
1886
- /** Chunk already-rendered Slack mrkdwn without splitting entities or code markers. */
1887
- function chunkSlackMrkdwnText(text, limit) {
1888
- if (text.length <= limit) return [text];
1889
- if (!(text.includes("`") || text.includes("&amp;") || text.includes("&lt;") || text.includes("&gt;") || (text.match(/<[^>\n]+>/gu)?.some(isAllowedSlackAngleToken) ?? false) || /\\[\s\S]/u.test(text))) return chunkTextForOutbound(text, limit);
1890
- const chunks = [];
1891
- let activeMarker;
1892
- let content = "";
1893
- const wrapper = () => activeMarker && limit > activeMarker.length * 2 ? activeMarker : void 0;
1894
- const capacity = () => limit - (wrapper()?.length ?? 0) * 2;
1895
- const flush = () => {
1896
- if (!content) return;
1897
- const marker = wrapper();
1898
- chunks.push(marker ? `${marker}${content}${marker}` : content);
1899
- content = "";
1900
- };
1901
- for (const token of tokenizeSlackMrkdwn(text)) {
1902
- const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
1903
- if (transition !== null) {
1904
- flush();
1905
- activeMarker = transition;
1906
- continue;
1907
- }
1908
- const contentLimit = capacity();
1909
- if (token.length > contentLimit) {
1910
- flush();
1911
- const marker = wrapper();
1912
- if (activeMarker && isAllowedSlackAngleToken(token)) {
1913
- if (marker) chunks.push(...hardSliceSlackToken(token, contentLimit).map((fragment) => `${marker}${fragment}${marker}`));
1914
- else chunks.push(...hardSliceSlackToken(escapeSlackMrkdwnSegment(token), limit));
1915
- continue;
1916
- }
1917
- chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
1918
- continue;
1919
- }
1920
- if (content && content.length + token.length > contentLimit) flush();
1921
- content += token;
1859
+ function buildSlackBlocksFallbackText(blocks) {
1860
+ for (const block of blocks) {
1861
+ const text = renderSlackBlockFallbackText(block);
1862
+ if (text) return text;
1922
1863
  }
1923
- flush();
1924
- return chunks;
1864
+ return "Shared a Block Kit message";
1925
1865
  }
1926
- function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
1927
- const ir = makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
1928
- assistantTranscriptRoleHeaders: true,
1929
- linkify: false,
1930
- autolink: false,
1931
- headingStyle: "rich",
1932
- blockquotePrefix: "> ",
1933
- tableMode: options.tableMode
1934
- }));
1935
- const renderOptions = buildSlackRenderOptions();
1936
- return renderMarkdownIRChunksWithinLimit({
1937
- ir,
1938
- limit,
1939
- renderChunk: (chunk) => protectSlackAssistantTranscriptRoleHeaders(renderMarkdownWithMarkers(chunk, renderOptions, SLACK_FORMAT_PROFILE)),
1940
- measureRendered: (rendered) => rendered.length
1941
- }).map(({ rendered }) => rendered);
1866
+ function buildSlackCompleteBlocksFallbackText(blocks) {
1867
+ return blocks.map((block) => renderSlackBlockFallbackText(block)).filter(Boolean).join("\n\n").trim() || buildSlackBlocksFallbackText(blocks);
1942
1868
  }
1943
1869
  //#endregion
1944
1870
  //#region extensions/slack/src/native-data-blocks.ts
@@ -2264,6 +2190,7 @@ function appendPresentationPart(segments, presentation) {
2264
2190
  const SLACK_BUTTON_CONTROL_ACTION_IDS = [
2265
2191
  SLACK_APPROVAL_BUTTON_ACTION_ID,
2266
2192
  SLACK_CALLBACK_BUTTON_ACTION_ID,
2193
+ SLACK_QUESTION_BUTTON_ACTION_ID,
2267
2194
  SLACK_REPLY_BUTTON_ACTION_ID,
2268
2195
  SLACK_REPLY_LINK_ACTION_ID
2269
2196
  ];
@@ -2473,6 +2400,20 @@ function resolveSlackUserAllowListForTeam(params) {
2473
2400
  });
2474
2401
  }
2475
2402
  //#endregion
2403
+ //#region extensions/slack/src/monitor/workspace-routing.ts
2404
+ function resolveSlackEnterpriseMainDmSessionKey(params) {
2405
+ const accountId = encodeURIComponent(params.accountId).toLowerCase();
2406
+ const teamId = encodeURIComponent(params.eventScope.teamId).toLowerCase();
2407
+ return `${params.baseSessionKey}:account:${accountId}:team:${teamId}`;
2408
+ }
2409
+ function qualifySlackRoutePeerId(params) {
2410
+ if (!params.eventScope) return params.id;
2411
+ return `team:${encodeURIComponent(params.eventScope.teamId)}:${params.kind}:${encodeURIComponent(params.id)}`;
2412
+ }
2413
+ function qualifySlackConversationId(conversationId, eventScope) {
2414
+ return eventScope ? `team:${encodeURIComponent(eventScope.teamId)}:${conversationId}` : conversationId;
2415
+ }
2416
+ //#endregion
2476
2417
  //#region extensions/slack/src/group-policy.ts
2477
2418
  function buildSlackChannelIdCandidates(channelId, teamId, options) {
2478
2419
  const trimmedId = channelId?.trim();
@@ -2524,4 +2465,4 @@ function resolveSlackGroupToolPolicy(params) {
2524
2465
  });
2525
2466
  }
2526
2467
  //#endregion
2527
- export { isSlackCallbackActionId as $, chunkSlackMrkdwnText as A, normalizeSlackApproverId as At, SLACK_TEXT_LIMIT as B, buildSlackNativeDataAccessibilityText as C, isSlackWorkspaceInstallation as Ct, isSlackInvalidBlocksResponse as D, getSlackExecApprovalApprovers as Dt, isSlackInvalidBlocksError as E, isSlackApprovalAuthorizedSender as Et, renderSlackBlockFallbackText as F, truncateSlackText as G, buildSlackPresentationBlocks as H, resolveSlackAuthoredTextPlacement as I, SLACK_REPLY_BUTTON_ACTION_ID as J, truncateSlackTextByUtf8Bytes as K, SLACK_EDIT_TEXT_MAX_BYTES as L, normalizeSlackOutboundText as M, shouldSuppressLocalSlackExecApprovalPrompt as Mt, buildSlackBlocksFallbackText as N, isSlackNativeResponseUrlRejection as O, isSlackExecApprovalAuthorizedSender as Ot, buildSlackCompleteBlocksFallbackText as P, isSlackApprovalActionId as Q, SLACK_MESSAGE_TEXT_HARD_LIMIT as R, appendSlackNativeDataPlainTextFallback as S, getSlackInstallationKind as St, hasSlackNativeDataBlock as T, getSlackApprovalApprovers as Tt, canRenderSlackPresentation as U, buildSlackInteractiveBlocks as V, countSlackTextUtf8Bytes as W, SLACK_REPLY_SELECT_ACTION_ID as X, SLACK_REPLY_LINK_ACTION_ID as Y, SLACK_SESSION_LINK_ACTION_ID as Z, resolveSlackReplyBlocks as _, resolveSlackFallbackOriginTarget as _t, allowListMatches as a, escapeSlackMrkdwn as at, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as b, shouldHandleSlackPluginViaForwardingSession as bt, normalizeSlackAllowOwnerEntry as c, SLACK_MAX_BLOCKS as ct, resolveSlackUserAllowListForTeam as d, hasSlackPluginApprovers as dt, isSlackQuestionActionId as et, resolveSlackUserAllowed as f, isSlackAnyNativeApprovalClientEnabled as ft, resolveSlackReplyBlockResolution as g, resolveSessionSlackOriginTarget as gt, parseSlackReplyBlockSegments as h, resolveEnterpriseApprovalTeamId as ht, resolveSlackGroupToolPolicy as i, renderSlackMessagePresentationFallbackText as it, markdownToSlackMrkdwnChunks as j, resolveSlackExecApprovalTarget as jt, stripSlackNativeDataBlocks as k, isSlackExecApprovalClientEnabled as kt, normalizeSlackSlug as l, parseSlackBlocksInput as lt, hasSlackReplyStructuredContent as m, normalizeSlackOriginTarget as mt, buildSlackChannelPolicyScope as n, decodeSlackQuestionAction as nt, normalizeAllowList as o, decodeSlackApprovalAction as ot, assertSlackDetachedTargetAllowed as p, normalizeSlackForwardTarget as pt, SLACK_QUESTION_FINALIZATION_BLOCKS as q, resolveSlackGroupRequireMention as r, resolveSlackQuestionAction as rt, normalizeAllowListLower as s, SLACK_PRESENTATION_CAPABILITIES as st, buildSlackChannelIdCandidates as t, resolveSlackQuestionActionIds as tt, resolveSlackAllowListMatch as u, validateSlackBlocksArray as ut, resolveSlackReplyDeliveryMessages as v, resolveTurnSourceSlackOriginTarget as vt, createSlackNativeDataBaseTextConsumer as w, registerSlackInstallationState as wt, appendSlackNativeDataFallbackText as x, slackTargetsMatch as xt, resolveSlackReplyRenderPlan as y, shouldHandleSlackNativeApprovalRequest as yt, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as z };
2468
+ export { isSlackCallbackActionId as $, isSlackInvalidBlocksResponse as A, getSlackApprovalApprovers as At, SLACK_TEXT_LIMIT as B, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as C, resolveTurnSourceSlackOriginTarget as Ct, createSlackNativeDataBaseTextConsumer as D, getSlackInstallationKind as Dt, buildSlackNativeDataAccessibilityText as E, slackTargetsMatch as Et, renderSlackBlockFallbackText as F, normalizeSlackApproverId as Ft, truncateSlackText as G, buildSlackPresentationBlocks as H, resolveSlackAuthoredTextPlacement as I, resolveSlackExecApprovalTarget as It, SLACK_REPLY_BUTTON_ACTION_ID as J, truncateSlackTextByUtf8Bytes as K, SLACK_EDIT_TEXT_MAX_BYTES as L, shouldSuppressLocalSlackExecApprovalPrompt as Lt, stripSlackNativeDataBlocks as M, getSlackExecApprovalApprovers as Mt, buildSlackBlocksFallbackText as N, isSlackExecApprovalAuthorizedSender as Nt, hasSlackNativeDataBlock as O, isSlackWorkspaceInstallation as Ot, buildSlackCompleteBlocksFallbackText as P, isSlackExecApprovalClientEnabled as Pt, isSlackApprovalActionId as Q, SLACK_MESSAGE_TEXT_HARD_LIMIT as R, SLACK_PRIVATE_ACTION_DELIVERY_RESULT as Rt, resolveSlackReplyRenderPlan as S, resolveSlackFallbackOriginTarget as St, appendSlackNativeDataPlainTextFallback as T, shouldHandleSlackPluginViaForwardingSession as Tt, canRenderSlackPresentation as U, buildSlackInteractiveBlocks as V, countSlackTextUtf8Bytes as W, SLACK_REPLY_SELECT_ACTION_ID as X, SLACK_REPLY_LINK_ACTION_ID as Y, SLACK_SESSION_LINK_ACTION_ID as Z, hasSlackReplyStructuredContent as _, isSlackAnyNativeApprovalClientEnabled as _t, qualifySlackConversationId as a, markdownToSlackMrkdwnChunks as at, resolveSlackReplyBlocks as b, resolveEnterpriseApprovalTeamId as bt, allowListMatches as c, escapeSlackMrkdwn as ct, normalizeSlackAllowOwnerEntry as d, SLACK_PRESENTATION_CAPABILITIES as dt, isSlackQuestionActionId as et, normalizeSlackSlug as f, SLACK_SECTION_TEXT_MAX as ft, assertSlackDetachedTargetAllowed as g, hasSlackPluginApprovers as gt, resolveSlackUserAllowed as h, validateSlackBlocksArray as ht, resolveSlackGroupToolPolicy as i, chunkSlackMrkdwnText as it, isSlackNativeResponseUrlRejection as j, isSlackApprovalAuthorizedSender as jt, isSlackInvalidBlocksError as k, registerSlackInstallationState as kt, normalizeAllowList as l, SLACK_APPROVAL_HEADER_BLOCK_ID as lt, resolveSlackUserAllowListForTeam as m, parseSlackBlocksInput as mt, buildSlackChannelPolicyScope as n, decodeSlackQuestionAction as nt, qualifySlackRoutePeerId as o, normalizeSlackOutboundText as ot, resolveSlackAllowListMatch as p, SLACK_MAX_BLOCKS as pt, SLACK_QUESTION_FINALIZATION_BLOCKS as q, resolveSlackGroupRequireMention as r, resolveSlackQuestionAction as rt, resolveSlackEnterpriseMainDmSessionKey as s, renderSlackMessagePresentationFallbackText as st, buildSlackChannelIdCandidates as t, resolveSlackQuestionActionIds as tt, normalizeAllowListLower as u, decodeSlackApprovalAction as ut, parseSlackReplyBlockSegments as v, normalizeSlackForwardTarget as vt, appendSlackNativeDataFallbackText as w, shouldHandleSlackNativeApprovalRequest as wt, resolveSlackReplyDeliveryMessages as x, resolveSessionSlackOriginTarget as xt, resolveSlackReplyBlockResolution as y, normalizeSlackOriginTarget as yt, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as z, resolveSlackAutoThreadId as zt };