@openclaw/slack 2026.10.10-beta.5 → 2026.11.5-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 (284) hide show
  1. package/dist/.setup/{account-configured-zcR9TJJN.mjs → account-configured-35y0-Hso.mjs} +1 -2
  2. package/dist/.setup/{account-inspect-CmkKiSb9.mjs → account-inspect-DgQgj0wk.mjs} +13 -11
  3. package/dist/.setup/{accounts-msihSF3-.mjs → accounts-EaPP0fFY.mjs} +16 -11
  4. package/dist/.setup/{action-runtime-ChRfnnBu.mjs → action-runtime-CK9QZgQl.mjs} +39 -47
  5. package/dist/.setup/action-runtime.runtime-CpZktret.mjs +1 -0
  6. package/dist/.setup/{actions-By7tvpvv.mjs → actions-s3CcFO45.mjs} +98 -93
  7. package/dist/.setup/{approval-handler.runtime-D8ArtDQt.mjs → approval-handler.runtime-Ch7BecYK.mjs} +27 -32
  8. package/dist/.setup/{approval-message-updates-DT7XBPbV.mjs → approval-message-updates-CqcRoa28.mjs} +2 -3
  9. package/dist/.setup/{channel-6YzXl_63.mjs → channel-CAvo_WNZ.mjs} +573 -352
  10. package/dist/.setup/{channel-meta-C443t-lI.mjs → channel-meta-C5vsCo3a.mjs} +1 -2
  11. package/dist/.setup/{channel-type-BEFP2ORi.mjs → channel-type-9Lw6yLf2.mjs} +6 -11
  12. package/dist/.setup/{channel.setup-u6QQdbTa.mjs → channel.setup-BlgXNuCJ.mjs} +19 -23
  13. package/dist/.setup/{config-schema-DNnh6bWU.mjs → config-schema-Bx1tCZB0.mjs} +5 -11
  14. package/dist/.setup/cursor-pages-jVn3Vkfi.mjs +309 -0
  15. package/dist/.setup/{directory-config-Cjj0N8R0.mjs → directory-config-CGvKYg9F.mjs} +5 -6
  16. package/dist/.setup/{directory-live-BIKD-5B_.mjs → directory-live-DNdw97LA.mjs} +6 -7
  17. package/dist/.setup/{doctor-contract-Cd4-VzIM.mjs → doctor-contract-BB2KJ9Ni.mjs} +44 -58
  18. package/dist/.setup/{message-tool-api-BS5ekEA_.mjs → message-tool-api-B38BpEaE.mjs} +7 -8
  19. package/dist/.setup/{monitor-BFilOuM_.mjs → monitor-BD86SotB.mjs} +3416 -3750
  20. package/dist/.setup/{outbound-adapter-9dbnYtL1.mjs → outbound-adapter-BH6iPWBj.mjs} +32 -39
  21. package/dist/.setup/paths-CQZI_5WY.mjs +7 -0
  22. package/dist/.setup/{pipeline.runtime-BG5swHnj.mjs → pipeline.runtime-C4ELxaRU.mjs} +444 -590
  23. package/dist/.setup/{policy-yhn48xf5.mjs → policy-C6_DdlSf.mjs} +3 -6
  24. package/dist/.setup/{session-status-Dv8wNBEt.mjs → probe-B_Ax1vS1.mjs} +1015 -678
  25. package/dist/.setup/question-delivery-D3qAIwuv.mjs +38 -0
  26. package/dist/.setup/{relay-source-oY9SbDiX.mjs → relay-source-a8jodKuO.mjs} +12 -6
  27. package/dist/.setup/{replies-CJwjTqDr.mjs → replies-Bq7n0gfM.mjs} +37 -24
  28. package/dist/.setup/{reply-blocks-Ca-raz2z.mjs → reply-blocks-DyYYRrP_.mjs} +202 -210
  29. package/dist/.setup/{resolve-channels-DRRhElwz.mjs → resolve-channels-CF2JME9q.mjs} +6 -10
  30. package/dist/.setup/{resolve-users-Cz8e17ky.mjs → resolve-users-DDcCAjH1.mjs} +10 -19
  31. package/dist/.setup/{rolldown-runtime-B4FMCO8f.mjs → rolldown-runtime-nwUcYXjP.mjs} +1 -2
  32. package/dist/.setup/{runtime-JSVZSWAj.mjs → runtime-C6HKn7Av.mjs} +1 -2
  33. package/dist/.setup/runtime-setter-api-DrXr965r.mjs +2 -0
  34. package/dist/.setup/{scopes-DfQVi8Jw.mjs → scopes-CzHC_dwV.mjs} +3 -3
  35. package/dist/.setup/{secret-contract-B-Qm6aQQ.mjs → secret-contract-CqVqR7MP.mjs} +5 -4
  36. package/dist/.setup/{secret-contract-api-DB6CMdgc.mjs → secret-contract-api-DaCXZ47j.mjs} +1 -1
  37. package/dist/.setup/{security-audit-DFGiFLqd.mjs → security-audit-C3hXCfDt.mjs} +2 -3
  38. package/dist/.setup/{send-C-8wY0lK.mjs → send-WJZ73VSf.mjs} +306 -349
  39. package/dist/.setup/{send-results-eeOu_HYm.mjs → send-results-Bm6V1ekL.mjs} +4 -6
  40. package/dist/.setup/setup-plugin-api-DJXIB8CF.mjs +2 -0
  41. package/dist/.setup/{setup-surface-9WVQgYCT.mjs → setup-surface-uIqP2B0Y.mjs} +6 -8
  42. package/dist/.setup/{slash-dispatch.runtime-v5kQqJPh.mjs → slash-dispatch.runtime-Cwuwv7FL.mjs} +2 -2
  43. package/dist/.setup/{target-parsing-FFE26kOV.mjs → target-parsing-DwYAP3ts.mjs} +2 -4
  44. package/dist/.setup/{targets-C6LZQL1Q.mjs → targets-eeOxA_b_.mjs} +2 -3
  45. package/dist/.setup/{thread-ts-Cvt7WD6B.mjs → thread-ts-47Au2-Yn.mjs} +1 -2
  46. package/dist/.source-module-urls/c5ffd0957b234c7c12090e7de4eca2482ef339b8561e078da55b734211b0ba58.json +1 -0
  47. package/dist/account-inspect-api.js +2 -3
  48. package/dist/api.js +17 -18
  49. package/dist/channel-config-api.js +1 -1
  50. package/dist/channel-entry.js +1 -2
  51. package/dist/channel-plugin-api.js +1 -1
  52. package/dist/configured-state.js +2 -3
  53. package/dist/directory-contract-api.js +1 -1
  54. package/dist/doctor-contract-api.js +1 -1
  55. package/dist/index.js +1 -8
  56. package/dist/message-tool-api.js +1 -1
  57. package/dist/runtime-api.js +11 -13
  58. package/dist/runtime-setter-api.js +1 -1
  59. package/dist/secret-contract-api.js +1 -1
  60. package/dist/security-contract-api.js +1 -1
  61. package/dist/setup-entry.js +4 -5
  62. package/dist/setup-plugin-api.js +1 -1
  63. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  64. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  65. package/node_modules/@slack/bolt/node_modules/@types/node/util.d.ts +6 -3
  66. package/node_modules/@slack/bolt/node_modules/content-disposition/README.md +105 -35
  67. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.d.ts +72 -0
  68. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js +388 -0
  69. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js.map +1 -0
  70. package/node_modules/@slack/bolt/node_modules/content-disposition/package.json +31 -19
  71. package/node_modules/@slack/bolt/node_modules/content-type/README.md +34 -57
  72. package/node_modules/@slack/bolt/node_modules/content-type/package.json +35 -25
  73. package/node_modules/@slack/bolt/node_modules/express/Readme.md +15 -9
  74. package/node_modules/@slack/bolt/node_modules/express/lib/application.js +2 -2
  75. package/node_modules/@slack/bolt/node_modules/express/lib/request.js +32 -19
  76. package/node_modules/@slack/bolt/node_modules/express/lib/response.js +27 -30
  77. package/node_modules/@slack/bolt/node_modules/express/package.json +10 -10
  78. package/node_modules/@slack/bolt/node_modules/qs/.github/THREAT_MODEL.md +4 -2
  79. package/node_modules/@slack/bolt/node_modules/qs/CHANGELOG.md +38 -14
  80. package/node_modules/@slack/bolt/node_modules/qs/README.md +31 -3
  81. package/node_modules/@slack/bolt/node_modules/qs/dist/qs.js +20 -20
  82. package/node_modules/@slack/bolt/node_modules/qs/lib/parse.js +94 -4
  83. package/node_modules/@slack/bolt/node_modules/qs/lib/stringify.js +4 -4
  84. package/node_modules/@slack/bolt/node_modules/qs/lib/utils.js +130 -6
  85. package/node_modules/@slack/bolt/node_modules/qs/package.json +4 -4
  86. package/node_modules/@slack/bolt/node_modules/qs/test/parse.js +174 -0
  87. package/node_modules/@slack/bolt/node_modules/qs/test/stringify.js +263 -33
  88. package/node_modules/@slack/bolt/node_modules/qs/test/utils.js +184 -0
  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/package.json +2 -2
  91. package/node_modules/@slack/web-api/node_modules/@types/node/util.d.ts +6 -3
  92. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  93. package/node_modules/typebox/build/format/duration.mjs +2 -2
  94. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  95. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  96. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  97. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  98. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  99. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  100. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  101. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  102. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  103. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  104. package/node_modules/typebox/build/schema/build.mjs +1 -0
  105. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  106. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  107. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  108. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  109. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  110. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  111. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  112. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  113. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  114. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  115. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  116. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  117. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  118. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  119. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  120. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  121. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  122. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  123. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  124. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  125. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  126. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  127. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  128. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  129. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  130. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  131. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  132. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  133. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  134. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  135. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  136. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  137. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  138. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  139. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  140. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  141. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  142. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  143. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  144. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  145. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  146. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  147. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  148. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  149. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  150. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  151. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  152. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  153. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  154. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  155. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  156. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  157. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  158. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  159. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  160. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  161. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  162. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  163. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  164. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  165. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  166. package/node_modules/typebox/package.json +1 -1
  167. package/node_modules/typebox/readme.md +1 -1
  168. package/node_modules/undici/README.md +25 -3
  169. package/node_modules/undici/docs/docs/api/CacheStore.md +24 -9
  170. package/node_modules/undici/docs/docs/api/Client.md +11 -6
  171. package/node_modules/undici/docs/docs/api/Dispatcher.md +3 -0
  172. package/node_modules/undici/docs/docs/api/Errors.md +76 -1
  173. package/node_modules/undici/docs/docs/api/H2CClient.md +3 -2
  174. package/node_modules/undici/docs/docs/api/Interceptors.md +28 -8
  175. package/node_modules/undici/docs/docs/api/RedirectHandler.md +13 -10
  176. package/node_modules/undici/docs/docs/index.md +12 -12
  177. package/node_modules/undici/docs/docs/type-map.json +66 -66
  178. package/node_modules/undici/lib/cache/memory-cache-store.js +48 -13
  179. package/node_modules/undici/lib/cache/sqlite-cache-store.js +83 -5
  180. package/node_modules/undici/lib/core/connect.js +10 -4
  181. package/node_modules/undici/lib/core/constants.js +12 -1
  182. package/node_modules/undici/lib/core/errors.js +38 -1
  183. package/node_modules/undici/lib/core/request.js +16 -1
  184. package/node_modules/undici/lib/core/symbols.js +2 -0
  185. package/node_modules/undici/lib/core/util.js +26 -1
  186. package/node_modules/undici/lib/dispatcher/agent.js +6 -2
  187. package/node_modules/undici/lib/dispatcher/client-h1.js +116 -80
  188. package/node_modules/undici/lib/dispatcher/client-h2.js +124 -17
  189. package/node_modules/undici/lib/dispatcher/client.js +4 -1
  190. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +3 -2
  191. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +20 -3
  192. package/node_modules/undici/lib/dispatcher/parser-h1.js +1064 -0
  193. package/node_modules/undici/lib/dispatcher/pool-base.js +85 -31
  194. package/node_modules/undici/lib/dispatcher/pool.js +11 -8
  195. package/node_modules/undici/lib/dispatcher/proxy-agent.js +18 -8
  196. package/node_modules/undici/lib/dispatcher/retry-agent.js +10 -0
  197. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +15 -5
  198. package/node_modules/undici/lib/handler/cache-handler.js +153 -15
  199. package/node_modules/undici/lib/handler/deduplication-handler.js +112 -51
  200. package/node_modules/undici/lib/handler/redirect-handler.js +28 -8
  201. package/node_modules/undici/lib/handler/retry-handler.js +44 -11
  202. package/node_modules/undici/lib/interceptor/cache.js +11 -3
  203. package/node_modules/undici/lib/interceptor/decompress.js +22 -9
  204. package/node_modules/undici/lib/interceptor/dns.js +11 -0
  205. package/node_modules/undici/lib/interceptor/response-error.js +72 -28
  206. package/node_modules/undici/lib/milo/LICENSE.md +7 -0
  207. package/node_modules/undici/lib/milo/no-simd.js +1002 -0
  208. package/node_modules/undici/lib/milo/simd.js +1002 -0
  209. package/node_modules/undici/lib/mock/mock-agent.js +11 -0
  210. package/node_modules/undici/lib/mock/snapshot-recorder.js +3 -2
  211. package/node_modules/undici/lib/mock/snapshot-utils.js +3 -2
  212. package/node_modules/undici/lib/util/cache.js +11 -5
  213. package/node_modules/undici/lib/web/cookies/util.js +19 -2
  214. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +69 -15
  215. package/node_modules/undici/lib/web/eventsource/eventsource.js +25 -2
  216. package/node_modules/undici/lib/web/fetch/body.js +47 -38
  217. package/node_modules/undici/lib/web/fetch/formdata-parser.js +12 -4
  218. package/node_modules/undici/lib/web/fetch/headers.js +2 -2
  219. package/node_modules/undici/lib/web/fetch/index.js +8 -4
  220. package/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +5 -5
  221. package/node_modules/undici/lib/web/websocket/receiver.js +25 -4
  222. package/node_modules/undici/package.json +9 -7
  223. package/node_modules/undici/types/api.d.ts +1 -1
  224. package/node_modules/undici/types/cache-interceptor.d.ts +10 -0
  225. package/node_modules/undici/types/client.d.ts +10 -4
  226. package/node_modules/undici/types/errors.d.ts +16 -1
  227. package/node_modules/undici/types/h2c-client.d.ts +1 -1
  228. package/node_modules/undici/types/interceptors.d.ts +6 -1
  229. package/node_modules/undici/types/utility.d.ts +4 -4
  230. package/node_modules/zod/package.json +1 -1
  231. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  232. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  233. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  234. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  235. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  236. package/node_modules/zod/src/v4/core/util.ts +13 -0
  237. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  238. package/node_modules/zod/v4/core/compile.cjs +8 -0
  239. package/node_modules/zod/v4/core/compile.js +8 -0
  240. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  241. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  242. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  243. package/node_modules/zod/v4/core/schemas.js +30 -0
  244. package/node_modules/zod/v4/core/util.cjs +15 -0
  245. package/node_modules/zod/v4/core/util.d.cts +2 -0
  246. package/node_modules/zod/v4/core/util.d.ts +2 -0
  247. package/node_modules/zod/v4/core/util.js +14 -0
  248. package/node_modules/zod/v4/core/versions.cjs +1 -1
  249. package/node_modules/zod/v4/core/versions.js +1 -1
  250. package/openclaw.plugin.json +6 -30
  251. package/package.json +7 -7
  252. package/dist/.setup/action-runtime.runtime-Ck_j1YTn.mjs +0 -1
  253. package/dist/.setup/http-C9sM-FXe.mjs +0 -2
  254. package/dist/.setup/plugin-routes-D4qozHVn.mjs +0 -22
  255. package/dist/.setup/probe-IiHogLQN.mjs +0 -694
  256. package/dist/.setup/registry-DizWcnNp.mjs +0 -36
  257. package/dist/.setup/runtime-setter-api-Cx_PV-xu.mjs +0 -2
  258. package/dist/.setup/setup-plugin-api-B18kDKtr.mjs +0 -2
  259. package/dist/.setup/shared-DpHCoKy2.mjs +0 -259
  260. package/dist/.source-module-urls/562d694877afe9d9dcbb3b32a8883c16974738f2aa892c48d45572cdc9a62529.json +0 -1
  261. package/dist/http-routes-api.js +0 -1
  262. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/LICENSE +0 -22
  263. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +0 -71
  264. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +0 -52
  265. package/node_modules/@slack/bolt/node_modules/content-disposition/index.js +0 -536
  266. package/node_modules/@slack/bolt/node_modules/content-type/HISTORY.md +0 -29
  267. package/node_modules/@slack/bolt/node_modules/content-type/index.js +0 -225
  268. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +0 -22
  269. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +0 -71
  270. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +0 -46
  271. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +0 -176
  272. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +0 -1
  273. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +0 -52
  274. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/LICENSE +0 -22
  275. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +0 -71
  276. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +0 -46
  277. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +0 -176
  278. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +0 -1
  279. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +0 -52
  280. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  281. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
  282. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.d.ts +0 -0
  283. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js +0 -0
  284. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js.map +0 -0
@@ -1,31 +1,37 @@
1
- import { r as isSlackPluginAccountConfigured } from "./account-configured-zcR9TJJN.mjs";
2
- import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, i as listSlackAccountIds, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-msihSF3-.mjs";
3
- import { a as parseSlackTarget, n as formatSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-FFE26kOV.mjs";
4
- import { t as slackContextTargetsMatch } from "./targets-C6LZQL1Q.mjs";
5
- import { A as resolveSlackAllowListMatch, j as resolveSlackUserAllowListForTeam, o as formatSlackError } from "./probe-IiHogLQN.mjs";
6
- import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
1
+ import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.mjs";
2
+ import { r as isSlackPluginAccountConfigured } from "./account-configured-35y0-Hso.mjs";
3
+ import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, i as listSlackAccountIds, m as formatSlackBotTokenIdentityWarning, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-EaPP0fFY.mjs";
4
+ import { a as parseSlackTarget, n as formatSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-DwYAP3ts.mjs";
5
+ import { t as slackContextTargetsMatch } from "./targets-eeOxA_b_.mjs";
6
+ import { _ as createSlackProbeDispatcher, i as createSlackReadClient } from "./cursor-pages-jVn3Vkfi.mjs";
7
7
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
8
- import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringifiedOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
+ import { asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringifiedOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { normalizeMessageChannel, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
10
10
  import { defaultRuntime, logVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
11
11
  import { FormatCapabilityProfile, chunkTextForOutbound, markdownToIR, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers } from "openclaw/plugin-sdk/text-chunking";
12
- import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
12
+ import { runChannelProbe, sliceUtf16Safe, truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
13
13
  import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
14
14
  import { buildChannelKeyCandidates } from "openclaw/plugin-sdk/channel-targets";
15
15
  import { createNativeApprovalChannelRouteGatesAsync, doesApprovalRequestSelectChannelAccountAsync, resolveApprovalKind, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
16
16
  import { createChannelApprovalAuth, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
17
- import { normalizeHyphenSlug, normalizeStringEntriesLower } from "openclaw/plugin-sdk/string-normalization-runtime";
17
+ import { normalizeHyphenSlug, normalizeStringEntriesLower, truncateWithMarker } from "openclaw/plugin-sdk/string-normalization-runtime";
18
18
  import { createChannelExecApprovalProfileAsync, isChannelExecApprovalClientEnabledFromConfig, isChannelExecApprovalTargetRecipient, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
19
+ import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
20
+ import { compileAllowlist, resolveCompiledAllowlistMatch } from "openclaw/plugin-sdk/allow-from";
21
+ import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
19
22
  import { channelRouteTargetsMatchExact, stringifyRouteThreadId } from "openclaw/plugin-sdk/channel-route";
20
23
  import { normalizeMessagePresentation, renderMessagePresentationChartFallbackText, renderMessagePresentationFallbackText, renderMessagePresentationTableFallbackText } from "openclaw/plugin-sdk/interactive-runtime";
21
- import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
22
24
  import { eastAsianWidthType } from "get-east-asian-width";
23
25
  import { resolveIntegerOption } from "openclaw/plugin-sdk/number-runtime";
26
+ import { isStringArray } from "openclaw/plugin-sdk/collection-input-runtime";
27
+ import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
24
28
  import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
25
29
  import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
26
30
  import { inspectRuntimeConversationBindingRoute, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRouteAsync } from "openclaw/plugin-sdk/conversation-binding-runtime";
31
+ import { redactSensitiveText } from "openclaw/plugin-sdk/logging-core";
27
32
  import { resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
28
- //#region extensions/slack/src/action-threading.ts
33
+ import { defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
34
+ // extensions/slack/src/action-threading.ts
29
35
  const SLACK_PRIVATE_ACTION_DELIVERY_RESULT = Symbol("slack.action.delivery-result");
30
36
  function resolveSlackAutoThreadId(params) {
31
37
  const context = params.toolContext;
@@ -39,8 +45,17 @@ function resolveSlackAutoThreadId(params) {
39
45
  if (isSingleUseReplyToMode(context.replyToMode ?? "off") && context.hasRepliedRef?.value) return;
40
46
  return context.currentThreadTs;
41
47
  }
42
- //#endregion
43
- //#region extensions/slack/src/approval-plugin-policy.ts
48
+ function resolveSlackThreadTsFromContext(explicitThreadTs, targetChannel, context, opts) {
49
+ if (explicitThreadTs) return explicitThreadTs;
50
+ if (opts?.suppressImplicitThread) return;
51
+ const threadTs = resolveSlackAutoThreadId({
52
+ to: targetChannel,
53
+ toolContext: context
54
+ });
55
+ if (isSingleUseReplyToMode(context?.replyToMode ?? "off") && !context?.hasRepliedRef) return;
56
+ return threadTs;
57
+ }
58
+ // extensions/slack/src/approval-plugin-policy.ts
44
59
  /** Returns undefined only when Slack plugin approvals retain legacy account authorization. */
45
60
  function resolvePluginApprovalSlackApprovers(cfg, request) {
46
61
  const policy = cfg.approvals?.plugin?.slack;
@@ -57,8 +72,7 @@ function resolvePluginApprovalSlackApprovers(cfg, request) {
57
72
  }
58
73
  return plugin?.approvers ?? policy.approvers;
59
74
  }
60
- //#endregion
61
- //#region extensions/slack/src/exec-approvals.ts
75
+ // extensions/slack/src/exec-approvals.ts
62
76
  function normalizeSlackUserLikeId(value) {
63
77
  const upper = value.toUpperCase();
64
78
  return /^[UW][A-Z0-9]+$/.test(upper) ? upper : void 0;
@@ -105,8 +119,7 @@ const isSlackExecApprovalClientEnabled = slackExecApprovalProfile.isClientEnable
105
119
  const isSlackExecApprovalAuthorizedSender = slackExecApprovalProfile.isAuthorizedSender;
106
120
  const resolveSlackExecApprovalTarget = slackExecApprovalProfile.resolveTarget;
107
121
  const shouldSuppressLocalSlackExecApprovalPrompt = slackExecApprovalProfile.shouldSuppressLocalPrompt;
108
- //#endregion
109
- //#region extensions/slack/src/installation-identity-state.ts
122
+ // extensions/slack/src/installation-identity-state.ts
110
123
  const slackInstallationStates = resolveGlobalMap(Symbol.for("openclaw.slack.installation-identities"), "close-and-restart");
111
124
  function registerSlackInstallationState(accountId, kind, teamId) {
112
125
  const normalizedAccountId = normalizeAccountId(accountId);
@@ -139,8 +152,104 @@ function getSlackInstallationTeamId(accountId) {
139
152
  function isSlackWorkspaceInstallation(accountId) {
140
153
  return getSlackInstallationKind(accountId) === "workspace";
141
154
  }
142
- //#endregion
143
- //#region extensions/slack/src/approval-auth.ts
155
+ // extensions/slack/src/monitor/allow-list.ts
156
+ const SLACK_SLUG_CACHE_MAX = 512;
157
+ const SLACK_STABLE_USER_ID_RE = /^[ubw][a-z0-9]+$/;
158
+ const slackSlugCache = /* @__PURE__ */ new Map();
159
+ function normalizeSlackSlug(raw) {
160
+ const key = raw ?? "";
161
+ const cached = slackSlugCache.get(key);
162
+ if (cached !== void 0) return cached;
163
+ const normalized = normalizeHyphenSlug(raw);
164
+ slackSlugCache.set(key, normalized);
165
+ pruneMapToMaxSize(slackSlugCache, SLACK_SLUG_CACHE_MAX);
166
+ return normalized;
167
+ }
168
+ function normalizeSlackAllowOwnerEntry(entry) {
169
+ const trimmed = normalizeOptionalLowercaseString(entry);
170
+ if (!trimmed || trimmed === "*") return;
171
+ try {
172
+ const target = parseSlackTarget(trimmed);
173
+ if (target?.kind === "user" && target.teamId) return target.id.toLowerCase();
174
+ } catch {
175
+ return;
176
+ }
177
+ const withoutPrefix = trimmed.replace(/^(slack:|user:)/, "");
178
+ return SLACK_STABLE_USER_ID_RE.test(withoutPrefix) ? withoutPrefix : void 0;
179
+ }
180
+ function resolveSlackAllowListMatch(params) {
181
+ const compiledAllowList = compileAllowlist(params.allowList);
182
+ const teamId = normalizeOptionalLowercaseString(params.teamId);
183
+ const id = normalizeOptionalLowercaseString(params.id);
184
+ const name = normalizeOptionalLowercaseString(params.name);
185
+ const slug = normalizeSlackSlug(name);
186
+ const scopedCandidates = [{
187
+ value: teamId && id ? `team:${teamId}:user:${id}` : void 0,
188
+ source: "workspace-id"
189
+ }];
190
+ const unscopedCandidates = [
191
+ {
192
+ value: id,
193
+ source: "id"
194
+ },
195
+ {
196
+ value: id ? `slack:${id}` : void 0,
197
+ source: "prefixed-id"
198
+ },
199
+ {
200
+ value: id ? `user:${id}` : void 0,
201
+ source: "prefixed-user"
202
+ },
203
+ ...params.allowNameMatching === true ? [
204
+ {
205
+ value: name,
206
+ source: "name"
207
+ },
208
+ {
209
+ value: name ? `slack:${name}` : void 0,
210
+ source: "prefixed-name"
211
+ },
212
+ {
213
+ value: slug,
214
+ source: "slug"
215
+ }
216
+ ] : []
217
+ ];
218
+ return resolveCompiledAllowlistMatch({
219
+ compiledAllowlist: compiledAllowList,
220
+ candidates: [...scopedCandidates, ...unscopedCandidates]
221
+ });
222
+ }
223
+ function allowListMatches(params) {
224
+ return resolveSlackAllowListMatch(params).allowed;
225
+ }
226
+ function resolveSlackUserAllowed(params) {
227
+ const allowList = normalizeStringEntriesLower(params.allowList);
228
+ if (allowList.length === 0) return true;
229
+ return allowListMatches({
230
+ allowList,
231
+ teamId: params.teamId,
232
+ id: params.userId,
233
+ name: params.userName,
234
+ allowNameMatching: params.allowNameMatching
235
+ });
236
+ }
237
+ function resolveSlackUserAllowListForTeam(params) {
238
+ const allowList = normalizeStringEntriesLower(params.allowList);
239
+ const teamId = normalizeOptionalLowercaseString(params.teamId);
240
+ return allowList.flatMap((entry) => {
241
+ if (entry === "*") return [entry];
242
+ if (!entry.startsWith("team:")) return [entry];
243
+ try {
244
+ const target = parseSlackTarget(entry);
245
+ if (target?.kind === "user" && target.teamId?.toLowerCase() === teamId) return [entry];
246
+ return params.preserveUnmatchedScopedEntries ? [entry] : [];
247
+ } catch {
248
+ return params.preserveUnmatchedScopedEntries ? [entry] : [];
249
+ }
250
+ });
251
+ }
252
+ // extensions/slack/src/approval-auth.ts
144
253
  function resolveSlackApprovalInputs(params) {
145
254
  const account = resolveSlackAccount(params).config;
146
255
  return {
@@ -207,8 +316,7 @@ function getSlackApprovalApproversForTeam(params) {
207
316
  function resolveSlackApprovalTeamId(params) {
208
317
  return getSlackInstallationTeamId(resolveSlackAccount(params).accountId) ?? resolveSlackApprovalOriginTeamId(params.request);
209
318
  }
210
- //#endregion
211
- //#region extensions/slack/src/approval-native-gates.ts
319
+ // extensions/slack/src/approval-native-gates.ts
212
320
  function isSlackPluginApprovalRequest(request) {
213
321
  return resolveApprovalKind(request) === "plugin";
214
322
  }
@@ -419,209 +527,456 @@ async function shouldHandleSlackNativeApprovalRequest(params) {
419
527
  approvalKind: "exec"
420
528
  });
421
529
  }
422
- //#endregion
423
- //#region extensions/slack/src/blocks-input.ts
424
- const SLACK_MAX_BLOCKS = 50;
425
- function parseBlocksJson(raw) {
426
- try {
427
- return JSON.parse(raw);
428
- } catch {
429
- throw new Error("blocks must be valid JSON");
430
- }
431
- }
432
- function validateSlackBlocksArray(raw) {
433
- if (!Array.isArray(raw)) throw new Error("blocks must be an array");
434
- if (raw.length === 0) throw new Error("blocks must contain at least one block");
435
- if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
436
- for (const block of raw) {
437
- if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
438
- const type = block.type;
439
- if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
440
- }
441
- return raw;
442
- }
443
- function parseSlackBlocksInput(raw) {
444
- if (raw == null) return;
445
- return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
446
- }
447
- const SLACK_BUTTON_VALUE_MAX = 2e3;
448
- const SLACK_SECTION_TEXT_MAX = 3e3;
449
- const SLACK_PRESENTATION_CAPABILITIES = {
450
- supported: true,
451
- buttons: true,
452
- selects: true,
453
- context: true,
454
- divider: true,
455
- charts: true,
456
- tables: true,
457
- limits: {
458
- actions: {
459
- maxActionsPerRow: 25,
460
- maxValueBytes: SLACK_BUTTON_VALUE_MAX,
461
- supportsStyles: true
462
- },
463
- selects: {
464
- maxOptions: 100,
465
- maxValueBytes: 150
466
- },
467
- text: {
468
- encoding: "characters",
469
- markdownDialect: "slack-mrkdwn",
470
- supportsEdit: true
471
- }
472
- }
473
- };
474
- //#endregion
475
- //#region extensions/slack/src/approval-actions.ts
476
- const SLACK_APPROVAL_VALUE_PREFIX = "openclaw:approval:v1:";
477
- const SLACK_APPROVAL_HEADER_BLOCK_ID = "openclaw_approval_header";
478
- function isApprovalDecision(value) {
479
- return value === "allow-once" || value === "allow-always" || value === "deny";
480
- }
481
- /** Encode portable approval facts without exposing a slash command to Slack callbacks. */
482
- function encodeSlackApprovalAction(action) {
483
- const encode = (approvalId) => `${SLACK_APPROVAL_VALUE_PREFIX}${JSON.stringify({
484
- approvalId,
485
- approvalKind: action.approvalKind,
486
- decision: action.decision
487
- })}`;
488
- const exact = encode(action.approvalId);
489
- return exact.length <= 2e3 ? exact : encode(buildApprovalResolutionRef({
490
- approvalId: action.approvalId,
491
- approvalKind: action.approvalKind
492
- }));
493
- }
494
- /** Decode only the exact Slack-owned approval envelope. Malformed callbacks fail closed. */
495
- function decodeSlackApprovalAction(value) {
496
- if (typeof value !== "string" || !value.startsWith(SLACK_APPROVAL_VALUE_PREFIX)) return null;
497
- try {
498
- const decoded = JSON.parse(value.slice(21));
499
- if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return null;
500
- const record = decoded;
501
- if (Object.keys(record).length !== 3 || typeof record.approvalId !== "string" || record.approvalId.length === 0 || record.approvalKind !== "exec" && record.approvalKind !== "plugin" && record.approvalKind !== "system-agent" || !isApprovalDecision(record.decision)) return null;
502
- return {
503
- type: "approval",
504
- approvalId: record.approvalId,
505
- approvalKind: record.approvalKind,
506
- decision: record.decision
507
- };
508
- } catch {
509
- return null;
510
- }
511
- }
512
- //#endregion
513
- //#region extensions/slack/src/monitor/mrkdwn.ts
530
+ // extensions/slack/src/monitor/mrkdwn.ts
514
531
  function escapeSlackMrkdwn(value) {
515
532
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
516
533
  }
517
- //#endregion
518
- //#region extensions/slack/src/presentation-fallback.ts
519
- const SLACK_UNCOPYABLE_COMMAND_WARNING = "not copyable: contains backtick";
520
- function escapeSlackPresentationChartBlock(block) {
521
- const escaped = {
522
- ...block,
523
- title: escapeSlackMrkdwn(block.title)
524
- };
525
- if (escaped.chartType === "pie") escaped.segments = escaped.segments.map((segment) => ({
526
- ...segment,
527
- label: escapeSlackMrkdwn(segment.label)
528
- }));
529
- else {
530
- escaped.categories = escaped.categories.map(escapeSlackMrkdwn);
531
- escaped.series = escaped.series.map((series) => ({
532
- ...series,
533
- name: escapeSlackMrkdwn(series.name)
534
- }));
535
- if (escaped.xLabel) escaped.xLabel = escapeSlackMrkdwn(escaped.xLabel);
536
- if (escaped.yLabel) escaped.yLabel = escapeSlackMrkdwn(escaped.yLabel);
534
+ // extensions/slack/src/format.ts
535
+ const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
536
+ function isAllowedSlackAngleToken(token) {
537
+ const inner = token.slice(1, -1);
538
+ return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
539
+ }
540
+ function escapeSlackMrkdwnContent(text, mentions) {
541
+ if (mentions === "escape") return escapeSlackMrkdwn(text);
542
+ if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
543
+ const out = [];
544
+ let lastIndex = 0;
545
+ for (const match of text.matchAll(SLACK_ANGLE_TOKEN_RE)) {
546
+ const matchIndex = match.index;
547
+ out.push(escapeSlackMrkdwn(text.slice(lastIndex, matchIndex)));
548
+ const token = match[0];
549
+ const escapeControl = mentions === "escape-controls" && /^<[@#!]/u.test(token);
550
+ out.push(isAllowedSlackAngleToken(token) && !escapeControl ? token : escapeSlackMrkdwn(token));
551
+ lastIndex = matchIndex + token.length;
537
552
  }
538
- return escaped;
553
+ out.push(escapeSlackMrkdwn(text.slice(lastIndex)));
554
+ return out.join("");
555
+ }
556
+ function escapeSlackMrkdwnText(text, mentions) {
557
+ if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
558
+ return text.split("\n").map((line) => {
559
+ if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2), mentions)}`;
560
+ return escapeSlackMrkdwnContent(line, mentions);
561
+ }).join("\n");
539
562
  }
540
- function escapeSlackPresentationTableBlock(block) {
563
+ function buildSlackLink(link, text) {
564
+ const href = link.href.trim();
565
+ if (!href || /^[@#!]/u.test(href)) return null;
566
+ const trimmedLabel = text.slice(link.start, link.end).trim();
567
+ const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
568
+ if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
569
+ const safeHref = escapeSlackMrkdwn(href);
541
570
  return {
542
- ...block,
543
- caption: escapeSlackMrkdwn(block.caption),
544
- headers: block.headers.map(escapeSlackMrkdwn),
545
- rows: block.rows.map((row) => row.map((cell) => typeof cell === "string" ? escapeSlackMrkdwn(cell) : cell))
571
+ start: link.start,
572
+ end: link.end,
573
+ open: `<${safeHref}|`,
574
+ close: ">"
546
575
  };
547
576
  }
548
- function escapeSlackPresentationFallbackBlock(block) {
549
- if (block.type === "chart") return escapeSlackPresentationChartBlock(block);
550
- if (block.type === "table") return escapeSlackPresentationTableBlock(block);
551
- if (block.type === "buttons") return {
552
- ...block,
553
- buttons: block.buttons.map((button) => {
554
- const commandAction = button.action?.type === "command" ? button.action : void 0;
555
- const label = commandAction?.command.includes("`") ? `${button.label} [${SLACK_UNCOPYABLE_COMMAND_WARNING}]` : button.label;
556
- return {
557
- ...button,
558
- label: escapeSlackMrkdwn(label),
559
- ...button.value ? { value: escapeSlackMrkdwn(button.value) } : {},
560
- ...button.url ? { url: escapeSlackMrkdwn(button.url) } : {},
561
- ...button.webApp ? { webApp: { url: escapeSlackMrkdwn(button.webApp.url) } } : {},
562
- ...button.web_app ? { web_app: { url: escapeSlackMrkdwn(button.web_app.url) } } : {},
563
- ...commandAction ? { action: {
564
- ...commandAction,
565
- command: commandAction.command.replaceAll("`", "[backtick]")
566
- } } : {}
567
- };
568
- })
569
- };
570
- if (block.type === "select") return {
571
- ...block,
572
- ...block.placeholder ? { placeholder: escapeSlackMrkdwn(block.placeholder) } : {},
573
- options: block.options.map((option) => ({
574
- ...option,
575
- label: escapeSlackMrkdwn(option.label)
576
- }))
577
- };
578
- return block;
577
+ const SLACK_MRKDWN_WORD_CHARACTER_RE = /[\p{L}\p{M}\p{N}_]/u;
578
+ const SLACK_MRKDWN_PUNCTUATION_RE = /\p{P}/u;
579
+ const SLACK_MRKDWN_SYMBOL_RE = /\p{S}/u;
580
+ const SLACK_MRKDWN_CJK_SCRIPT_RE = /[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u;
581
+ const SLACK_MRKDWN_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
582
+ function getCodePointBefore(text, index) {
583
+ if (index <= 0) return "";
584
+ const lastCodeUnit = text.charCodeAt(index - 1);
585
+ if (lastCodeUnit >= 56320 && lastCodeUnit <= 57343 && index > 1) {
586
+ const previousCodeUnit = text.charCodeAt(index - 2);
587
+ if (previousCodeUnit >= 55296 && previousCodeUnit <= 56319) return text.slice(index - 2, index);
588
+ }
589
+ return text[index - 1] ?? "";
579
590
  }
580
- function renderSlackMessagePresentationChartFallbackText(block) {
581
- return renderMessagePresentationChartFallbackText(escapeSlackPresentationChartBlock(block));
591
+ function getCodePointAt(text, index) {
592
+ const codePoint = text.codePointAt(index);
593
+ return codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
582
594
  }
583
- function renderSlackMessagePresentationTableFallbackText(block) {
584
- return renderMessagePresentationTableFallbackText(escapeSlackPresentationTableBlock(block));
595
+ function isSlackCjkPunctuation(character) {
596
+ if (!SLACK_MRKDWN_PUNCTUATION_RE.test(character)) return false;
597
+ if (SLACK_MRKDWN_CJK_SCRIPT_RE.test(character)) return true;
598
+ const codePoint = character.codePointAt(0);
599
+ if (codePoint === void 0) return false;
600
+ const width = eastAsianWidthType(codePoint);
601
+ return width === "fullwidth" || width === "halfwidth" || width === "wide" && !SLACK_MRKDWN_EMOJI_PRESENTATION_RE.test(character);
585
602
  }
586
- function renderSlackMessagePresentationFallbackText(params) {
587
- if (!params.presentation) return renderMessagePresentationFallbackText(params);
588
- const presentation = {
589
- ...params.presentation,
590
- ...params.presentation.title ? { title: escapeSlackMrkdwn(params.presentation.title) } : {},
591
- blocks: params.presentation.blocks.map(escapeSlackPresentationFallbackBlock)
592
- };
593
- return renderMessagePresentationFallbackText({
594
- ...params,
595
- presentation
596
- });
603
+ function isUnsafeSlackEmphasisBoundary(character) {
604
+ if (SLACK_MRKDWN_WORD_CHARACTER_RE.test(character)) return true;
605
+ const codePoint = character.codePointAt(0);
606
+ if (codePoint === void 0 || codePoint <= 127) return false;
607
+ return SLACK_MRKDWN_SYMBOL_RE.test(character) || isSlackCjkPunctuation(character);
597
608
  }
598
- //#endregion
599
- //#region extensions/slack/src/rich-text.ts
600
- const RICH_TEXT_CONTAINER_TYPES = /* @__PURE__ */ new Set([
601
- "rich_text_section",
602
- "rich_text_preformatted",
603
- "rich_text_quote",
604
- "rich_text_list"
605
- ]);
606
- function renderSlackRichText(value, mode, separator = "") {
607
- if (!Array.isArray(value)) return "";
608
- const table = mode === "table";
609
- const read = table ? readNonBlankString : normalizeOptionalString;
610
- const literal = table ? (text) => text : escapeSlackMrkdwn;
611
- const reference = mode === "escaped" ? escapeSlackMrkdwn : (text) => text;
612
- const formatReference = (raw, prefix, suffix) => {
613
- const text = read(raw);
614
- return text ? reference(`${prefix}${text}${suffix}`) : "";
609
+ function makeSlackEmphasisStylesSafe(ir) {
610
+ const styles = ir.styles.filter((span) => {
611
+ if (span.style !== "italic" && span.style !== "bold") return true;
612
+ return !isUnsafeSlackEmphasisBoundary(getCodePointBefore(ir.text, span.start)) && !isUnsafeSlackEmphasisBoundary(getCodePointAt(ir.text, span.end));
613
+ });
614
+ return styles.length === ir.styles.length ? ir : {
615
+ ...ir,
616
+ styles
615
617
  };
616
- return value.map((rawElement) => {
617
- const element = asOptionalRecord(rawElement);
618
- if (!element) return "";
619
- if (Array.isArray(element.elements) && (table || RICH_TEXT_CONTAINER_TYPES.has(element.type))) return renderSlackRichText(element.elements, mode, element.type === "rich_text_list" ? "\n" : "");
620
- if (element.type === "text" && typeof element.text === "string") return literal(element.text);
621
- if (table) {
622
- const text = readNonBlankString(element.text);
623
- if (text) return text;
624
- }
618
+ }
619
+ const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
620
+ mechanism: "markdown",
621
+ constructs: {
622
+ underline: "strip",
623
+ spoiler: "fallback",
624
+ codeLanguage: "fallback",
625
+ heading: "fallback",
626
+ bulletList: "fallback",
627
+ orderedList: "fallback",
628
+ taskList: "fallback",
629
+ table: "fallback",
630
+ image: "fallback"
631
+ },
632
+ chunk: {
633
+ limit: 4e3,
634
+ unit: "chars",
635
+ hardCap: 4e4
636
+ }
637
+ });
638
+ const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
639
+ function tokenizeSlackMrkdwn(text, graphemes) {
640
+ const tokens = [];
641
+ for (let index = 0; index < text.length;) {
642
+ if (text.startsWith("```", index)) {
643
+ tokens.push("```");
644
+ index += 3;
645
+ continue;
646
+ }
647
+ const entity = text[index] === "&" ? [
648
+ "&amp;",
649
+ "&lt;",
650
+ "&gt;"
651
+ ].find((candidate) => text.startsWith(candidate, index)) : void 0;
652
+ if (entity) {
653
+ tokens.push(entity);
654
+ index += entity.length;
655
+ continue;
656
+ }
657
+ if (text[index] === "<") {
658
+ const end = text.indexOf(">", index + 1);
659
+ const angleToken = end >= 0 ? text.slice(index, end + 1) : void 0;
660
+ if (angleToken && !angleToken.includes("\n") && isAllowedSlackAngleToken(angleToken)) {
661
+ tokens.push(angleToken);
662
+ index += angleToken.length;
663
+ continue;
664
+ }
665
+ }
666
+ const codePoint = text.codePointAt(index);
667
+ if (codePoint === void 0) break;
668
+ const grapheme = graphemes?.containing(index + (codePoint > 65535 ? 1 : 0));
669
+ const character = grapheme && text.slice(index, grapheme.index + grapheme.segment.length).match(/^[^`*_~<>&]+/u)?.[0] || String.fromCodePoint(codePoint);
670
+ index += character.length;
671
+ tokens.push(character);
672
+ }
673
+ return tokens;
674
+ }
675
+ function resolveSlackCodeMarkerTransition(active, token) {
676
+ if ((token === "`" || token === "```") && (active === void 0 || active === token)) return active === token ? void 0 : token;
677
+ return null;
678
+ }
679
+ function maskSlackExcludedText(text) {
680
+ return text.split("\n").map((line) => line.trim() ? `x${" ".repeat(Math.max(0, line.length - 1))}` : " ".repeat(line.length)).join("\n");
681
+ }
682
+ function maskSlackExcludedRanges(projection) {
683
+ let masked = "";
684
+ let cursor = 0;
685
+ for (const range of projection.excludedRanges) {
686
+ masked += projection.text.slice(cursor, range.start);
687
+ masked += maskSlackExcludedText(projection.text.slice(range.start, range.end));
688
+ cursor = range.end;
689
+ }
690
+ return masked + projection.text.slice(cursor);
691
+ }
692
+ function slackProjectionHasRoleHeader(projection) {
693
+ return Boolean(markdownToIR(maskSlackExcludedRanges(projection), {
694
+ assistantTranscriptRoleHeaders: true,
695
+ autolink: false,
696
+ blockquotePrefix: "",
697
+ headingStyle: "none",
698
+ linkify: false,
699
+ tableMode: "off"
700
+ }).annotations?.some((annotation) => annotation.type === "assistant_transcript_role"));
701
+ }
702
+ function decodeSlackMrkdwnEntities(text) {
703
+ return text.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">");
704
+ }
705
+ function projectSlackAngleToken(token, dateDisplay) {
706
+ const inner = token.slice(1, -1);
707
+ if (inner.startsWith("!date^")) {
708
+ const fallbackSeparator = inner.indexOf("|");
709
+ const tokenString = (fallbackSeparator === -1 ? inner : inner.slice(0, fallbackSeparator)).split("^")[2] ?? "";
710
+ const fallback = fallbackSeparator === -1 ? "" : inner.slice(fallbackSeparator + 1);
711
+ return decodeSlackMrkdwnEntities(dateDisplay === "fallback" ? fallback || tokenString : tokenString || fallback);
712
+ }
713
+ const labelSeparator = inner.indexOf("|");
714
+ if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
715
+ const prefix = inner.charAt(0);
716
+ if (prefix === "@" || prefix === "#" || prefix === "!") return prefix;
717
+ return decodeSlackMrkdwnEntities(inner);
718
+ }
719
+ function appendSlackVisibleProjection(projection, visible, excluded) {
720
+ if (!visible) return;
721
+ const start = projection.text.length;
722
+ projection.text += visible;
723
+ if (!excluded) return;
724
+ const previous = projection.excludedRanges.at(-1);
725
+ if (previous?.end === start) previous.end = projection.text.length;
726
+ else projection.excludedRanges.push({
727
+ start,
728
+ end: projection.text.length
729
+ });
730
+ }
731
+ function projectSlackMrkdwnVisibleText(text, dateDisplay) {
732
+ const projection = {
733
+ text: "",
734
+ excludedRanges: []
735
+ };
736
+ let activeMarker;
737
+ let lineHasVisibleContent = false;
738
+ for (const token of tokenizeSlackMrkdwn(text)) {
739
+ const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
740
+ if (transition !== null) {
741
+ activeMarker = transition;
742
+ continue;
743
+ }
744
+ let visible = token;
745
+ if (isAllowedSlackAngleToken(token)) visible = activeMarker ? token : projectSlackAngleToken(token, dateDisplay);
746
+ else if (token === "&amp;" || token === "&lt;" || token === "&gt;") visible = decodeSlackMrkdwnEntities(token);
747
+ else if (!activeMarker && (token === "*" || token === "_" || token === "~")) visible = "";
748
+ else if (!activeMarker && token === ">" && !lineHasVisibleContent) visible = "";
749
+ appendSlackVisibleProjection(projection, visible, activeMarker !== void 0);
750
+ for (const character of visible) if (character === "\n") lineHasVisibleContent = false;
751
+ else if (character !== " " && character !== " " && character !== "\r") lineHasVisibleContent = true;
752
+ }
753
+ return projection;
754
+ }
755
+ function protectSlackAssistantTranscriptRoleHeaders(text) {
756
+ if (text.startsWith(SLACK_ASSISTANT_TRANSCRIPT_PREFIX)) return text;
757
+ if (!slackProjectionHasRoleHeader(projectSlackMrkdwnVisibleText(text, "token")) && (!text.includes("<!date^") || !slackProjectionHasRoleHeader(projectSlackMrkdwnVisibleText(text, "fallback")))) return text;
758
+ return `${SLACK_ASSISTANT_TRANSCRIPT_PREFIX}${text}`;
759
+ }
760
+ function buildSlackRenderOptions({ enclosingStyle, mentions } = {}) {
761
+ return {
762
+ annotationMarkers: { assistant_transcript_role: {
763
+ open: "`",
764
+ close: "`",
765
+ suppressNestedFormatting: true
766
+ } },
767
+ styleMarkers: {
768
+ ...enclosingStyle !== "bold" ? { bold: {
769
+ open: "*",
770
+ close: "*"
771
+ } } : {},
772
+ ...enclosingStyle !== "italic" ? { italic: {
773
+ open: "_",
774
+ close: "_"
775
+ } } : {},
776
+ strikethrough: {
777
+ open: "~",
778
+ close: "~"
779
+ },
780
+ code: {
781
+ open: "`",
782
+ close: "`"
783
+ },
784
+ code_block: {
785
+ open: "```\n",
786
+ close: "```"
787
+ }
788
+ },
789
+ escapeText: (text) => escapeSlackMrkdwnText(text, mentions),
790
+ buildLink: buildSlackLink
791
+ };
792
+ }
793
+ function prepareSlackMarkdownIR(markdown, options) {
794
+ return makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
795
+ assistantTranscriptRoleHeaders: true,
796
+ linkify: false,
797
+ autolink: false,
798
+ headingStyle: "rich",
799
+ blockquotePrefix: "> ",
800
+ tableMode: options.tableMode
801
+ }));
802
+ }
803
+ function normalizeSlackOutboundText(markdown, options = {}) {
804
+ const ir = prepareSlackMarkdownIR(markdown, options);
805
+ return protectSlackAssistantTranscriptRoleHeaders(renderMarkdownWithMarkers(ir, buildSlackRenderOptions(options), SLACK_FORMAT_PROFILE));
806
+ }
807
+ /** Chunk already-rendered Slack mrkdwn without splitting entities or code markers. */
808
+ function chunkSlackMrkdwnText(text, limit) {
809
+ if (text.length <= limit) return [text];
810
+ if (!(text.includes("`") || text.includes("&amp;") || text.includes("&lt;") || text.includes("&gt;") || (text.match(/<[^>\n]+>/gu)?.some(isAllowedSlackAngleToken) ?? false))) return chunkTextForOutbound(text, limit, { preserveWhitespace: true });
811
+ const chunks = [];
812
+ let activeMarker;
813
+ let content = "";
814
+ const wrapper = (marker) => marker && limit > marker.length * 2 ? marker : void 0;
815
+ const capacity = (marker) => limit - (wrapper(marker)?.length ?? 0);
816
+ const flush = () => {
817
+ const marker = wrapper(activeMarker);
818
+ if (content && content !== marker) chunks.push(marker ? `${content}${marker}` : content);
819
+ content = "";
820
+ };
821
+ for (const token of tokenizeSlackMrkdwn(text, new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(text))) {
822
+ const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
823
+ const nextMarker = transition === null ? activeMarker : transition;
824
+ const sourceMarker = token === "`" || token === "```" ? token : void 0;
825
+ if (transition !== null && sourceMarker && !wrapper(sourceMarker)) {
826
+ activeMarker = nextMarker;
827
+ continue;
828
+ }
829
+ if (content && content.length + token.length > capacity(nextMarker)) flush();
830
+ activeMarker = nextMarker;
831
+ if (!content && transition === void 0) continue;
832
+ content ||= transition === null ? wrapper(activeMarker) ?? "" : "";
833
+ const contentLimit = capacity(activeMarker) - (wrapper(activeMarker)?.length ?? 0);
834
+ if (token.length > contentLimit) {
835
+ flush();
836
+ const marker = wrapper(activeMarker);
837
+ if (activeMarker) {
838
+ const fragments = chunkTextForOutbound(marker ? token : escapeSlackMrkdwn(token), Math.max(1, Math.floor(marker ? contentLimit : limit)), { preserveWhitespace: true });
839
+ chunks.push(...marker ? fragments.map((fragment) => `${marker}${fragment}${marker}`) : fragments);
840
+ continue;
841
+ }
842
+ chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
843
+ continue;
844
+ }
845
+ content += token;
846
+ }
847
+ flush();
848
+ return chunks;
849
+ }
850
+ function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
851
+ const ir = prepareSlackMarkdownIR(markdown, options);
852
+ const renderOptions = buildSlackRenderOptions();
853
+ const normalizedLimit = limit === Number.POSITIVE_INFINITY ? limit : resolveIntegerOption(limit, 1, { min: 1 });
854
+ return renderMarkdownIRChunksWithinLimit({
855
+ ir,
856
+ limit: normalizedLimit,
857
+ renderChunk: (chunk) => {
858
+ const rendered = renderMarkdownWithMarkers(chunk, renderOptions, SLACK_FORMAT_PROFILE);
859
+ return rendered.length > normalizedLimit ? rendered : protectSlackAssistantTranscriptRoleHeaders(rendered);
860
+ },
861
+ measureRendered: (rendered) => rendered.length
862
+ }).map(({ rendered }) => rendered.length > normalizedLimit ? protectSlackAssistantTranscriptRoleHeaders(rendered) : rendered);
863
+ }
864
+ // extensions/slack/src/limits.ts
865
+ const SLACK_TEXT_LIMIT = 8e3;
866
+ const SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT = 4e3;
867
+ const SLACK_EDIT_TEXT_MAX_BYTES = 4e3;
868
+ const SLACK_MESSAGE_TEXT_HARD_LIMIT = 4e4;
869
+ // extensions/slack/src/presentation-fallback.ts
870
+ const SLACK_UNCOPYABLE_COMMAND_WARNING = "not copyable: contains backtick";
871
+ function escapeSlackPresentationFallbackBlock(block) {
872
+ if (block.type === "chart") return {
873
+ type: "text",
874
+ text: renderSlackMessagePresentationChartFallbackText(block)
875
+ };
876
+ if (block.type === "table") return {
877
+ type: "text",
878
+ text: renderSlackMessagePresentationTableFallbackText(block)
879
+ };
880
+ if (block.type === "buttons") return {
881
+ ...block,
882
+ buttons: block.buttons.map((button) => {
883
+ const commandAction = button.action?.type === "command" ? button.action : void 0;
884
+ const label = commandAction?.command.includes("`") ? `${button.label} [${SLACK_UNCOPYABLE_COMMAND_WARNING}]` : button.label;
885
+ return {
886
+ ...button,
887
+ label: escapeSlackMrkdwn(label),
888
+ ...button.value ? { value: escapeSlackMrkdwn(button.value) } : {},
889
+ ...button.url ? { url: escapeSlackMrkdwn(button.url) } : {},
890
+ ...button.webApp ? { webApp: { url: escapeSlackMrkdwn(button.webApp.url) } } : {},
891
+ ...button.web_app ? { web_app: { url: escapeSlackMrkdwn(button.web_app.url) } } : {},
892
+ ...commandAction ? { action: {
893
+ ...commandAction,
894
+ command: commandAction.command.replaceAll("`", "[backtick]")
895
+ } } : {}
896
+ };
897
+ })
898
+ };
899
+ if (block.type === "select") return {
900
+ ...block,
901
+ ...block.placeholder ? { placeholder: escapeSlackMrkdwn(block.placeholder) } : {},
902
+ options: block.options.map((option) => ({
903
+ ...option,
904
+ label: escapeSlackMrkdwn(option.label)
905
+ }))
906
+ };
907
+ return block;
908
+ }
909
+ function renderSlackMessagePresentationChartFallbackText(block) {
910
+ return escapeSlackMrkdwn(renderMessagePresentationChartFallbackText(block));
911
+ }
912
+ function renderSlackMessagePresentationTableFallbackText(block) {
913
+ return escapeSlackMrkdwn(renderMessagePresentationTableFallbackText(block));
914
+ }
915
+ function renderSlackMessagePresentationFallbackText(params) {
916
+ if (!params.presentation) return renderMessagePresentationFallbackText(params);
917
+ const presentation = {
918
+ ...params.presentation,
919
+ ...params.presentation.title ? { title: escapeSlackMrkdwn(params.presentation.title) } : {},
920
+ blocks: params.presentation.blocks.map(escapeSlackPresentationFallbackBlock)
921
+ };
922
+ return renderMessagePresentationFallbackText({
923
+ ...params,
924
+ presentation
925
+ });
926
+ }
927
+ const SLACK_BUTTON_VALUE_MAX = 2e3;
928
+ const SLACK_SECTION_TEXT_MAX = 3e3;
929
+ const SLACK_PRESENTATION_CAPABILITIES = {
930
+ supported: true,
931
+ buttons: true,
932
+ selects: true,
933
+ context: true,
934
+ divider: true,
935
+ charts: true,
936
+ tables: true,
937
+ limits: {
938
+ actions: {
939
+ maxActionsPerRow: 25,
940
+ maxValueBytes: SLACK_BUTTON_VALUE_MAX,
941
+ supportsStyles: true
942
+ },
943
+ selects: {
944
+ maxOptions: 100,
945
+ maxValueBytes: 150
946
+ },
947
+ text: {
948
+ encoding: "characters",
949
+ markdownDialect: "slack-mrkdwn",
950
+ supportsEdit: true
951
+ }
952
+ }
953
+ };
954
+ // extensions/slack/src/rich-text.ts
955
+ const RICH_TEXT_CONTAINER_TYPES = /* @__PURE__ */ new Set([
956
+ "rich_text_section",
957
+ "rich_text_preformatted",
958
+ "rich_text_quote",
959
+ "rich_text_list"
960
+ ]);
961
+ function renderSlackRichText(value, mode, separator = "") {
962
+ if (!Array.isArray(value)) return "";
963
+ const table = mode === "table";
964
+ const read = table ? readNonBlankString : normalizeOptionalString;
965
+ const literal = table ? (text) => text : escapeSlackMrkdwn;
966
+ const reference = mode === "escaped" ? escapeSlackMrkdwn : (text) => text;
967
+ const formatReference = (raw, prefix, suffix) => {
968
+ const text = read(raw);
969
+ return text ? reference(`${prefix}${text}${suffix}`) : "";
970
+ };
971
+ return value.map((rawElement) => {
972
+ const element = asOptionalRecord(rawElement);
973
+ if (!element) return "";
974
+ if (Array.isArray(element.elements) && (table || RICH_TEXT_CONTAINER_TYPES.has(element.type))) return renderSlackRichText(element.elements, mode, element.type === "rich_text_list" ? "\n" : "");
975
+ if (element.type === "text" && typeof element.text === "string") return literal(element.text);
976
+ if (table) {
977
+ const text = readNonBlankString(element.text);
978
+ if (text) return text;
979
+ }
625
980
  switch (element.type) {
626
981
  case "link": return literal(read(element.text) ?? read(element.url) ?? "");
627
982
  case "user": return formatReference(element.user_id, "<@", ">");
@@ -643,8 +998,7 @@ function renderSlackRichText(value, mode, separator = "") {
643
998
  }
644
999
  }).filter(Boolean).join(separator);
645
1000
  }
646
- //#endregion
647
- //#region extensions/slack/src/data-table.ts
1001
+ // extensions/slack/src/data-table.ts
648
1002
  const SLACK_DATA_TABLE_COLUMNS_MAX = 20;
649
1003
  const SLACK_DATA_TABLE_ROWS_MAX = 100;
650
1004
  const SLACK_DATA_TABLE_AGGREGATE_CELL_CHARACTERS_MAX = 1e4;
@@ -719,13 +1073,13 @@ function countSlackDataTableBlocksCellCharacters(blocks) {
719
1073
  function buildSlackDataTableBlock(block, options = {}) {
720
1074
  const cellCharacterCountOffset = options.cellCharacterCountOffset ?? 0;
721
1075
  if (!Number.isSafeInteger(cellCharacterCountOffset) || cellCharacterCountOffset < 0) return;
722
- if (typeof block.caption !== "string" || block.caption.trim().length === 0 || !Array.isArray(block.headers) || block.headers.length < 1 || block.headers.length > SLACK_DATA_TABLE_COLUMNS_MAX || !Array.isArray(block.rows) || block.rows.length < 1 || block.rows.length > SLACK_DATA_TABLE_ROWS_MAX || new Set(block.headers).size !== block.headers.length || !block.headers.every((header) => typeof header === "string" && header.trim().length > 0) || block.rowHeaderColumnIndex !== void 0 && (!Number.isInteger(block.rowHeaderColumnIndex) || block.rowHeaderColumnIndex < 0 || block.rowHeaderColumnIndex >= block.headers.length)) return;
1076
+ if (block.caption.trim().length === 0 || block.headers.length < 1 || block.headers.length > SLACK_DATA_TABLE_COLUMNS_MAX || block.rows.length < 1 || block.rows.length > SLACK_DATA_TABLE_ROWS_MAX || new Set(block.headers).size !== block.headers.length || !block.headers.every((header) => header.trim().length > 0) || block.rowHeaderColumnIndex !== void 0 && (!Number.isInteger(block.rowHeaderColumnIndex) || block.rowHeaderColumnIndex < 0 || block.rowHeaderColumnIndex >= block.headers.length)) return;
723
1077
  const rows = [Array.from(block.headers, (text) => ({
724
1078
  type: "raw_text",
725
1079
  text
726
1080
  }))];
727
1081
  for (const row of block.rows) {
728
- if (!Array.isArray(row) || row.length !== block.headers.length) return;
1082
+ if (row.length !== block.headers.length) return;
729
1083
  const cells = [];
730
1084
  for (const cell of row) {
731
1085
  if (typeof cell === "number") {
@@ -737,7 +1091,7 @@ function buildSlackDataTableBlock(block, options = {}) {
737
1091
  });
738
1092
  continue;
739
1093
  }
740
- if (typeof cell !== "string" || cell.trim().length === 0) return;
1094
+ if (cell.trim().length === 0) return;
741
1095
  cells.push({
742
1096
  type: "raw_text",
743
1097
  text: cell
@@ -784,8 +1138,7 @@ function renderSlackDataTableCompactPlainTextFallback(value) {
784
1138
  ...table.rows.map((row) => row.map(escapeCompactFallbackCell).join(" "))
785
1139
  ].join("\n"));
786
1140
  }
787
- //#endregion
788
- //#region extensions/slack/src/data-visualization.ts
1141
+ // extensions/slack/src/data-visualization.ts
789
1142
  const SLACK_CHART_TITLE_MAX = 50;
790
1143
  const SLACK_CHART_LABEL_MAX = 20;
791
1144
  const SLACK_CHART_AXIS_LABEL_MAX = 50;
@@ -796,7 +1149,7 @@ function hasSlackDataVisualizationBlock(blocks) {
796
1149
  return blocks?.some((block) => asOptionalRecord(block)?.type === "data_visualization") ?? false;
797
1150
  }
798
1151
  function isStringWithin(value, maxLength) {
799
- return typeof value === "string" && value.trim().length > 0 && Array.from(value).length <= maxLength;
1152
+ return value.trim().length > 0 && Array.from(value).length <= maxLength;
800
1153
  }
801
1154
  function hasUniqueStrings(values) {
802
1155
  return new Set(values).size === values.length;
@@ -810,7 +1163,7 @@ function buildSlackDataVisualizationBlock(block) {
810
1163
  title: block.title,
811
1164
  chart: {
812
1165
  type: "pie",
813
- segments: block.segments.map((segment) => ({ ...segment }))
1166
+ segments: block.segments
814
1167
  }
815
1168
  };
816
1169
  }
@@ -828,7 +1181,7 @@ function buildSlackDataVisualizationBlock(block) {
828
1181
  }))
829
1182
  })),
830
1183
  axis_config: {
831
- categories: [...block.categories],
1184
+ categories: block.categories,
832
1185
  ...block.xLabel ? { x_label: block.xLabel } : {},
833
1186
  ...block.yLabel ? { y_label: block.yLabel } : {}
834
1187
  }
@@ -862,373 +1215,178 @@ function parseSlackDataVisualizationBlock(block) {
862
1215
  if (chart.type !== "bar" && chart.type !== "area" && chart.type !== "line") return;
863
1216
  const axisConfig = asOptionalRecord(chart.axis_config);
864
1217
  const categories = axisConfig?.categories;
865
- if (!Array.isArray(categories) || !categories.every((category) => typeof category === "string")) return;
1218
+ if (!isStringArray(categories)) return;
866
1219
  if (!Array.isArray(chart.series)) return;
867
1220
  const series = chart.series.map((rawSeries) => {
868
1221
  const seriesRecord = asOptionalRecord(rawSeries);
869
- if (typeof seriesRecord?.name !== "string" || !Array.isArray(seriesRecord.data)) return;
870
- const data = seriesRecord.data.map(readSlackChartDatum);
871
- if (data.some((datum) => !datum) || data.length !== categories.length) return;
872
- const dataByLabel = new Map(data.map((datum) => [datum.label, datum.value]));
873
- if (dataByLabel.size !== data.length || categories.some((category) => !dataByLabel.has(category))) return;
874
- return {
875
- name: seriesRecord.name,
876
- values: categories.map((category) => dataByLabel.get(category))
877
- };
878
- });
879
- if (series.some((entry) => !entry)) return;
880
- return {
881
- type: "chart",
882
- chartType: chart.type,
883
- title,
884
- categories,
885
- series,
886
- xLabel: axisConfig?.x_label,
887
- yLabel: axisConfig?.y_label
888
- };
889
- }
890
- /** Extract an accessible summary, escaping mrkdwn control tokens when requested. */
891
- function renderSlackDataVisualizationFallbackText(value, mrkdwnSafe = false) {
892
- const block = asOptionalRecord(value);
893
- if (block?.type !== "data_visualization") return;
894
- const parsed = normalizeMessagePresentation({ blocks: [parseSlackDataVisualizationBlock(block)] })?.blocks[0];
895
- if (parsed?.type === "chart") return mrkdwnSafe ? renderSlackMessagePresentationChartFallbackText(parsed) : renderMessagePresentationChartFallbackText(parsed);
896
- const title = typeof block.title === "string" ? block.title.trim() : "";
897
- return title ? mrkdwnSafe ? escapeSlackMrkdwn(title) : title : void 0;
898
- }
899
- //#endregion
900
- //#region extensions/slack/src/format.ts
901
- const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
902
- function isAllowedSlackAngleToken(token) {
903
- const inner = token.slice(1, -1);
904
- return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
905
- }
906
- function escapeSlackMrkdwnContent(text, mentions) {
907
- if (mentions === "escape") return escapeSlackMrkdwn(text);
908
- if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
909
- const out = [];
910
- let lastIndex = 0;
911
- for (const match of text.matchAll(SLACK_ANGLE_TOKEN_RE)) {
912
- const matchIndex = match.index;
913
- out.push(escapeSlackMrkdwn(text.slice(lastIndex, matchIndex)));
914
- const token = match[0];
915
- const escapeControl = mentions === "escape-controls" && /^<[@#!]/u.test(token);
916
- out.push(isAllowedSlackAngleToken(token) && !escapeControl ? token : escapeSlackMrkdwn(token));
917
- lastIndex = matchIndex + token.length;
918
- }
919
- out.push(escapeSlackMrkdwn(text.slice(lastIndex)));
920
- return out.join("");
921
- }
922
- function escapeSlackMrkdwnText(text, mentions) {
923
- if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
924
- return text.split("\n").map((line) => {
925
- if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2), mentions)}`;
926
- return escapeSlackMrkdwnContent(line, mentions);
927
- }).join("\n");
928
- }
929
- function buildSlackLink(link, text) {
930
- const href = link.href.trim();
931
- if (!href || /^[@#!]/u.test(href)) return null;
932
- const trimmedLabel = text.slice(link.start, link.end).trim();
933
- const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
934
- if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
935
- const safeHref = escapeSlackMrkdwn(href);
1222
+ if (typeof seriesRecord?.name !== "string" || !Array.isArray(seriesRecord.data)) return;
1223
+ const data = seriesRecord.data.map(readSlackChartDatum);
1224
+ if (data.some((datum) => !datum) || data.length !== categories.length) return;
1225
+ const dataByLabel = new Map(data.map((datum) => [datum.label, datum.value]));
1226
+ if (dataByLabel.size !== data.length || categories.some((category) => !dataByLabel.has(category))) return;
1227
+ return {
1228
+ name: seriesRecord.name,
1229
+ values: categories.map((category) => dataByLabel.get(category))
1230
+ };
1231
+ });
1232
+ if (series.some((entry) => !entry)) return;
936
1233
  return {
937
- start: link.start,
938
- end: link.end,
939
- open: `<${safeHref}|`,
940
- close: ">"
1234
+ type: "chart",
1235
+ chartType: chart.type,
1236
+ title,
1237
+ categories,
1238
+ series,
1239
+ xLabel: axisConfig?.x_label,
1240
+ yLabel: axisConfig?.y_label
941
1241
  };
942
1242
  }
943
- const SLACK_MRKDWN_WORD_CHARACTER_RE = /[\p{L}\p{M}\p{N}_]/u;
944
- const SLACK_MRKDWN_PUNCTUATION_RE = /\p{P}/u;
945
- const SLACK_MRKDWN_SYMBOL_RE = /\p{S}/u;
946
- const SLACK_MRKDWN_CJK_SCRIPT_RE = /[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u;
947
- const SLACK_MRKDWN_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
948
- function getCodePointBefore(text, index) {
949
- if (index <= 0) return "";
950
- const lastCodeUnit = text.charCodeAt(index - 1);
951
- if (lastCodeUnit >= 56320 && lastCodeUnit <= 57343 && index > 1) {
952
- const previousCodeUnit = text.charCodeAt(index - 2);
953
- if (previousCodeUnit >= 55296 && previousCodeUnit <= 56319) return text.slice(index - 2, index);
954
- }
955
- return text[index - 1] ?? "";
956
- }
957
- function getCodePointAt(text, index) {
958
- const codePoint = text.codePointAt(index);
959
- return codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
960
- }
961
- function isSlackCjkPunctuation(character) {
962
- if (!SLACK_MRKDWN_PUNCTUATION_RE.test(character)) return false;
963
- if (SLACK_MRKDWN_CJK_SCRIPT_RE.test(character)) return true;
964
- const codePoint = character.codePointAt(0);
965
- if (codePoint === void 0) return false;
966
- const width = eastAsianWidthType(codePoint);
967
- return width === "fullwidth" || width === "halfwidth" || width === "wide" && !SLACK_MRKDWN_EMOJI_PRESENTATION_RE.test(character);
1243
+ /** Extract an accessible summary, escaping mrkdwn control tokens when requested. */
1244
+ function renderSlackDataVisualizationFallbackText(value, mrkdwnSafe = false) {
1245
+ const block = asOptionalRecord(value);
1246
+ if (block?.type !== "data_visualization") return;
1247
+ const parsed = normalizeMessagePresentation({ blocks: [parseSlackDataVisualizationBlock(block)] })?.blocks[0];
1248
+ if (parsed?.type === "chart") return mrkdwnSafe ? renderSlackMessagePresentationChartFallbackText(parsed) : renderMessagePresentationChartFallbackText(parsed);
1249
+ const title = typeof block.title === "string" ? block.title.trim() : "";
1250
+ return title ? mrkdwnSafe ? escapeSlackMrkdwn(title) : title : void 0;
968
1251
  }
969
- function isUnsafeSlackEmphasisBoundary(character) {
970
- if (SLACK_MRKDWN_WORD_CHARACTER_RE.test(character)) return true;
971
- const codePoint = character.codePointAt(0);
972
- if (codePoint === void 0 || codePoint <= 127) return false;
973
- return SLACK_MRKDWN_SYMBOL_RE.test(character) || isSlackCjkPunctuation(character);
1252
+ // extensions/slack/src/blocks-fallback.ts
1253
+ const SLACK_SELECT_ELEMENT_TYPES = /* @__PURE__ */ new Set([
1254
+ "static_select",
1255
+ "multi_static_select",
1256
+ "external_select",
1257
+ "multi_external_select",
1258
+ "users_select",
1259
+ "multi_users_select",
1260
+ "conversations_select",
1261
+ "multi_conversations_select",
1262
+ "channels_select",
1263
+ "multi_channels_select"
1264
+ ]);
1265
+ function readTextObject(value, options = {}) {
1266
+ const record = asOptionalRecord(value);
1267
+ const text = normalizeOptionalString(record?.text);
1268
+ if (!text) return;
1269
+ return record?.type === "plain_text" && options.nativeDataFormat !== "plain" ? escapeSlackMrkdwn(text) : text;
974
1270
  }
975
- function makeSlackEmphasisStylesSafe(ir) {
976
- const styles = ir.styles.filter((span) => {
977
- if (span.style !== "italic" && span.style !== "bold") return true;
978
- return !isUnsafeSlackEmphasisBoundary(getCodePointBefore(ir.text, span.start)) && !isUnsafeSlackEmphasisBoundary(getCodePointAt(ir.text, span.end));
979
- });
980
- return styles.length === ir.styles.length ? ir : {
981
- ...ir,
982
- styles
983
- };
1271
+ function readAltText(value) {
1272
+ const text = normalizeOptionalString(value);
1273
+ return text ? escapeSlackMrkdwn(text) : void 0;
984
1274
  }
985
- const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
986
- mechanism: "markdown",
987
- constructs: {
988
- underline: "strip",
989
- spoiler: "fallback",
990
- codeLanguage: "fallback",
991
- heading: "fallback",
992
- bulletList: "fallback",
993
- orderedList: "fallback",
994
- taskList: "fallback",
995
- table: "fallback",
996
- image: "fallback"
997
- },
998
- chunk: {
999
- limit: 4e3,
1000
- unit: "chars",
1001
- hardCap: 4e4
1275
+ function readControlElementText(value, options = {}) {
1276
+ const element = asOptionalRecord(value);
1277
+ const type = normalizeOptionalString(element?.type);
1278
+ if (type === "button" || type === "workflow_button") return normalizeOptionalString(element?.text) ?? readTextObject(element?.text, options);
1279
+ if (type && (SLACK_SELECT_ELEMENT_TYPES.has(type) || type === "overflow")) {
1280
+ if (!options.includeSelectOptions) return readTextObject(element?.placeholder, options);
1281
+ const choices = Array.isArray(element?.options) ? element.options : [];
1282
+ return [readTextObject(element?.placeholder, options), ...choices.map((choice) => readTextObject(asOptionalRecord(choice)?.text, options))].filter(Boolean).join("\n");
1002
1283
  }
1003
- });
1004
- const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
1005
- function tokenizeSlackMrkdwn(text, graphemes) {
1006
- const tokens = [];
1007
- for (let index = 0; index < text.length;) {
1008
- if (text.startsWith("```", index)) {
1009
- tokens.push("```");
1010
- index += 3;
1011
- continue;
1012
- }
1013
- const entity = text[index] === "&" ? [
1014
- "&amp;",
1015
- "&lt;",
1016
- "&gt;"
1017
- ].find((candidate) => text.startsWith(candidate, index)) : void 0;
1018
- if (entity) {
1019
- tokens.push(entity);
1020
- index += entity.length;
1021
- continue;
1284
+ }
1285
+ /** Read only user-visible text from one Slack block. */
1286
+ function renderSlackBlockFallbackText(raw, options = {}) {
1287
+ const block = asOptionalRecord(raw);
1288
+ if (!block) return;
1289
+ switch (block.type) {
1290
+ case "rich_text": return normalizeOptionalString(renderSlackRichText(block.elements, options.nativeReferenceFormat === "plain" ? "native-reference" : "escaped", "\n"));
1291
+ case "header": return readTextObject(block.text, options);
1292
+ case "section":
1293
+ case "context": {
1294
+ const context = block.type === "context";
1295
+ return (context ? (Array.isArray(block.elements) ? block.elements : []).map((element) => {
1296
+ const record = asOptionalRecord(element);
1297
+ return readTextObject(record, options) ?? readAltText(record?.alt_text);
1298
+ }) : [
1299
+ readTextObject(block.text, options),
1300
+ ...Array.isArray(block.fields) ? block.fields.map((field) => readTextObject(field, options)) : [],
1301
+ readControlElementText(block.accessory, options)
1302
+ ]).filter(Boolean).join(context ? " " : "\n") || void 0;
1022
1303
  }
1023
- if (text[index] === "<") {
1024
- const end = text.indexOf(">", index + 1);
1025
- const angleToken = end >= 0 ? text.slice(index, end + 1) : void 0;
1026
- if (angleToken && !angleToken.includes("\n") && isAllowedSlackAngleToken(angleToken)) {
1027
- tokens.push(angleToken);
1028
- index += angleToken.length;
1029
- continue;
1030
- }
1304
+ case "image": return readAltText(block.alt_text) ?? readTextObject(block.title) ?? "Shared an image";
1305
+ case "video": return readTextObject(block.title, options) ?? readAltText(block.alt_text) ?? "Shared a video";
1306
+ case "file": return "Shared a file";
1307
+ case "actions": {
1308
+ if (!Array.isArray(block.elements)) return;
1309
+ const labels = block.elements.map((value) => readControlElementText(value, options)).filter(Boolean);
1310
+ return [...new Set(labels)].join("\n") || void 0;
1031
1311
  }
1032
- const codePoint = text.codePointAt(index);
1033
- if (codePoint === void 0) break;
1034
- const grapheme = graphemes?.containing(index + (codePoint > 65535 ? 1 : 0));
1035
- const character = grapheme && text.slice(index, grapheme.index + grapheme.segment.length).match(/^[^`*_~<>&]+/u)?.[0] || String.fromCodePoint(codePoint);
1036
- index += character.length;
1037
- tokens.push(character);
1312
+ case "data_visualization": return renderSlackDataVisualizationFallbackText(block, options.nativeDataFormat !== "plain");
1313
+ case "data_table": return renderSlackDataTableFallbackText(block, options.nativeDataFormat !== "plain");
1314
+ case "table": return renderSlackTableFallbackText(block, options.nativeDataFormat !== "plain");
1315
+ default: return;
1038
1316
  }
1039
- return tokens;
1040
- }
1041
- function resolveSlackCodeMarkerTransition(active, token) {
1042
- if ((token === "`" || token === "```") && (active === void 0 || active === token)) return active === token ? void 0 : token;
1043
- return null;
1044
1317
  }
1045
- function maskSlackExcludedText(text) {
1046
- return text.split("\n").map((line) => line.trim() ? `x${" ".repeat(Math.max(0, line.length - 1))}` : " ".repeat(line.length)).join("\n");
1047
- }
1048
- function maskSlackExcludedRanges(projection) {
1049
- let masked = "";
1050
- let cursor = 0;
1051
- for (const range of projection.excludedRanges) {
1052
- masked += projection.text.slice(cursor, range.start);
1053
- masked += maskSlackExcludedText(projection.text.slice(range.start, range.end));
1054
- cursor = range.end;
1318
+ function buildSlackBlocksFallbackText(blocks) {
1319
+ for (const block of blocks) {
1320
+ const text = renderSlackBlockFallbackText(block);
1321
+ if (text) return text;
1055
1322
  }
1056
- return masked + projection.text.slice(cursor);
1057
- }
1058
- function slackProjectionHasRoleHeader(projection) {
1059
- return Boolean(markdownToIR(maskSlackExcludedRanges(projection), {
1060
- assistantTranscriptRoleHeaders: true,
1061
- autolink: false,
1062
- blockquotePrefix: "",
1063
- headingStyle: "none",
1064
- linkify: false,
1065
- tableMode: "off"
1066
- }).annotations?.some((annotation) => annotation.type === "assistant_transcript_role"));
1323
+ return "Shared a Block Kit message";
1067
1324
  }
1068
- function decodeSlackMrkdwnEntities(text) {
1069
- return text.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">");
1325
+ function buildSlackCompleteBlocksFallbackText(blocks, options = {}) {
1326
+ return blocks.map((block) => renderSlackBlockFallbackText(block, options)).filter(Boolean).join("\n\n").trim() || buildSlackBlocksFallbackText(blocks);
1070
1327
  }
1071
- function projectSlackAngleToken(token, dateDisplay) {
1072
- const inner = token.slice(1, -1);
1073
- if (inner.startsWith("!date^")) {
1074
- const fallbackSeparator = inner.indexOf("|");
1075
- const tokenString = (fallbackSeparator === -1 ? inner : inner.slice(0, fallbackSeparator)).split("^")[2] ?? "";
1076
- const fallback = fallbackSeparator === -1 ? "" : inner.slice(fallbackSeparator + 1);
1077
- return decodeSlackMrkdwnEntities(dateDisplay === "fallback" ? fallback || tokenString : tokenString || fallback);
1328
+ // extensions/slack/src/blocks-input.ts
1329
+ const SLACK_MAX_BLOCKS = 50;
1330
+ function parseBlocksJson(raw) {
1331
+ try {
1332
+ return JSON.parse(raw);
1333
+ } catch {
1334
+ throw new Error("blocks must be valid JSON");
1078
1335
  }
1079
- const labelSeparator = inner.indexOf("|");
1080
- if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
1081
- const prefix = inner.charAt(0);
1082
- if (prefix === "@" || prefix === "#" || prefix === "!") return prefix;
1083
- return decodeSlackMrkdwnEntities(inner);
1084
- }
1085
- function appendSlackVisibleProjection(projection, visible, excluded) {
1086
- if (!visible) return;
1087
- const start = projection.text.length;
1088
- projection.text += visible;
1089
- if (!excluded) return;
1090
- const previous = projection.excludedRanges.at(-1);
1091
- if (previous?.end === start) previous.end = projection.text.length;
1092
- else projection.excludedRanges.push({
1093
- start,
1094
- end: projection.text.length
1095
- });
1096
1336
  }
1097
- function projectSlackMrkdwnVisibleText(text, dateDisplay) {
1098
- const projection = {
1099
- text: "",
1100
- excludedRanges: []
1101
- };
1102
- let activeMarker;
1103
- let lineHasVisibleContent = false;
1104
- for (const token of tokenizeSlackMrkdwn(text)) {
1105
- const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
1106
- if (transition !== null) {
1107
- activeMarker = transition;
1108
- continue;
1109
- }
1110
- let visible = token;
1111
- if (isAllowedSlackAngleToken(token)) visible = activeMarker ? token : projectSlackAngleToken(token, dateDisplay);
1112
- else if (token === "&amp;" || token === "&lt;" || token === "&gt;") visible = decodeSlackMrkdwnEntities(token);
1113
- else if (!activeMarker && (token === "*" || token === "_" || token === "~")) visible = "";
1114
- else if (!activeMarker && token === ">" && !lineHasVisibleContent) visible = "";
1115
- appendSlackVisibleProjection(projection, visible, activeMarker !== void 0);
1116
- for (const character of visible) if (character === "\n") lineHasVisibleContent = false;
1117
- else if (character !== " " && character !== " " && character !== "\r") lineHasVisibleContent = true;
1337
+ function validateSlackBlocksArray(raw) {
1338
+ if (!Array.isArray(raw)) throw new Error("blocks must be an array");
1339
+ if (raw.length === 0) throw new Error("blocks must contain at least one block");
1340
+ if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
1341
+ for (const block of raw) {
1342
+ if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
1343
+ const type = block.type;
1344
+ if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
1118
1345
  }
1119
- return projection;
1346
+ return raw;
1120
1347
  }
1121
- function protectSlackAssistantTranscriptRoleHeaders(text) {
1122
- if (text.startsWith(SLACK_ASSISTANT_TRANSCRIPT_PREFIX)) return text;
1123
- if (!slackProjectionHasRoleHeader(projectSlackMrkdwnVisibleText(text, "token")) && (!text.includes("<!date^") || !slackProjectionHasRoleHeader(projectSlackMrkdwnVisibleText(text, "fallback")))) return text;
1124
- return `${SLACK_ASSISTANT_TRANSCRIPT_PREFIX}${text}`;
1348
+ function parseSlackBlocksInput(raw) {
1349
+ if (raw == null) return;
1350
+ return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
1125
1351
  }
1126
- function buildSlackRenderOptions({ enclosingStyle, mentions } = {}) {
1127
- return {
1128
- annotationMarkers: { assistant_transcript_role: {
1129
- open: "`",
1130
- close: "`",
1131
- suppressNestedFormatting: true
1132
- } },
1133
- styleMarkers: {
1134
- ...enclosingStyle !== "bold" ? { bold: {
1135
- open: "*",
1136
- close: "*"
1137
- } } : {},
1138
- ...enclosingStyle !== "italic" ? { italic: {
1139
- open: "_",
1140
- close: "_"
1141
- } } : {},
1142
- strikethrough: {
1143
- open: "~",
1144
- close: "~"
1145
- },
1146
- code: {
1147
- open: "`",
1148
- close: "`"
1149
- },
1150
- code_block: {
1151
- open: "```\n",
1152
- close: "```"
1153
- }
1154
- },
1155
- escapeText: (text) => escapeSlackMrkdwnText(text, mentions),
1156
- buildLink: buildSlackLink
1157
- };
1352
+ // extensions/slack/src/approval-actions.ts
1353
+ const SLACK_APPROVAL_VALUE_PREFIX = "openclaw:approval:v1:";
1354
+ const SLACK_APPROVAL_HEADER_BLOCK_ID = "openclaw_approval_header";
1355
+ function isApprovalDecision(value) {
1356
+ return value === "allow-once" || value === "allow-always" || value === "deny";
1158
1357
  }
1159
- function prepareSlackMarkdownIR(markdown, options) {
1160
- return makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
1161
- assistantTranscriptRoleHeaders: true,
1162
- linkify: false,
1163
- autolink: false,
1164
- headingStyle: "rich",
1165
- blockquotePrefix: "> ",
1166
- tableMode: options.tableMode
1358
+ /** Encode portable approval facts without exposing a slash command to Slack callbacks. */
1359
+ function encodeSlackApprovalAction(action) {
1360
+ const encode = (approvalId) => `${SLACK_APPROVAL_VALUE_PREFIX}${JSON.stringify({
1361
+ approvalId,
1362
+ approvalKind: action.approvalKind,
1363
+ decision: action.decision
1364
+ })}`;
1365
+ const exact = encode(action.approvalId);
1366
+ return exact.length <= 2e3 ? exact : encode(buildApprovalResolutionRef({
1367
+ approvalId: action.approvalId,
1368
+ approvalKind: action.approvalKind
1167
1369
  }));
1168
1370
  }
1169
- function normalizeSlackOutboundText(markdown, options = {}) {
1170
- const ir = prepareSlackMarkdownIR(markdown, options);
1171
- return protectSlackAssistantTranscriptRoleHeaders(renderMarkdownWithMarkers(ir, buildSlackRenderOptions(options), SLACK_FORMAT_PROFILE));
1172
- }
1173
- /** Chunk already-rendered Slack mrkdwn without splitting entities or code markers. */
1174
- function chunkSlackMrkdwnText(text, limit) {
1175
- if (text.length <= limit) return [text];
1176
- if (!(text.includes("`") || text.includes("&amp;") || text.includes("&lt;") || text.includes("&gt;") || (text.match(/<[^>\n]+>/gu)?.some(isAllowedSlackAngleToken) ?? false))) return chunkTextForOutbound(text, limit, { preserveWhitespace: true });
1177
- const chunks = [];
1178
- let activeMarker;
1179
- let content = "";
1180
- const wrapper = (marker) => marker && limit > marker.length * 2 ? marker : void 0;
1181
- const capacity = (marker) => limit - (wrapper(marker)?.length ?? 0);
1182
- const flush = () => {
1183
- const marker = wrapper(activeMarker);
1184
- if (content && content !== marker) chunks.push(marker ? `${content}${marker}` : content);
1185
- content = "";
1186
- };
1187
- for (const token of tokenizeSlackMrkdwn(text, new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(text))) {
1188
- const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
1189
- const nextMarker = transition === null ? activeMarker : transition;
1190
- const sourceMarker = token === "`" || token === "```" ? token : void 0;
1191
- if (transition !== null && sourceMarker && !wrapper(sourceMarker)) {
1192
- activeMarker = nextMarker;
1193
- continue;
1194
- }
1195
- if (content && content.length + token.length > capacity(nextMarker)) flush();
1196
- activeMarker = nextMarker;
1197
- if (!content && transition === void 0) continue;
1198
- content ||= transition === null ? wrapper(activeMarker) ?? "" : "";
1199
- const contentLimit = capacity(activeMarker) - (wrapper(activeMarker)?.length ?? 0);
1200
- if (token.length > contentLimit) {
1201
- flush();
1202
- const marker = wrapper(activeMarker);
1203
- if (activeMarker) {
1204
- const fragments = chunkTextForOutbound(marker ? token : escapeSlackMrkdwn(token), Math.max(1, Math.floor(marker ? contentLimit : limit)), { preserveWhitespace: true });
1205
- chunks.push(...marker ? fragments.map((fragment) => `${marker}${fragment}${marker}`) : fragments);
1206
- continue;
1207
- }
1208
- chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
1209
- continue;
1210
- }
1211
- content += token;
1371
+ /** Decode only the exact Slack-owned approval envelope. Malformed callbacks fail closed. */
1372
+ function decodeSlackApprovalAction(value) {
1373
+ if (typeof value !== "string" || !value.startsWith(SLACK_APPROVAL_VALUE_PREFIX)) return null;
1374
+ try {
1375
+ const decoded = JSON.parse(value.slice(21));
1376
+ if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return null;
1377
+ const record = decoded;
1378
+ if (Object.keys(record).length !== 3 || typeof record.approvalId !== "string" || record.approvalId.length === 0 || record.approvalKind !== "exec" && record.approvalKind !== "plugin" && record.approvalKind !== "system-agent" || !isApprovalDecision(record.decision)) return null;
1379
+ return {
1380
+ type: "approval",
1381
+ approvalId: record.approvalId,
1382
+ approvalKind: record.approvalKind,
1383
+ decision: record.decision
1384
+ };
1385
+ } catch {
1386
+ return null;
1212
1387
  }
1213
- flush();
1214
- return chunks;
1215
- }
1216
- function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
1217
- const ir = prepareSlackMarkdownIR(markdown, options);
1218
- const renderOptions = buildSlackRenderOptions();
1219
- const normalizedLimit = limit === Number.POSITIVE_INFINITY ? limit : resolveIntegerOption(limit, 1, { min: 1 });
1220
- return renderMarkdownIRChunksWithinLimit({
1221
- ir,
1222
- limit: normalizedLimit,
1223
- renderChunk: (chunk) => {
1224
- const rendered = renderMarkdownWithMarkers(chunk, renderOptions, SLACK_FORMAT_PROFILE);
1225
- return rendered.length > normalizedLimit ? rendered : protectSlackAssistantTranscriptRoleHeaders(rendered);
1226
- },
1227
- measureRendered: (rendered) => rendered.length
1228
- }).map(({ rendered }) => rendered.length > normalizedLimit ? protectSlackAssistantTranscriptRoleHeaders(rendered) : rendered);
1229
1388
  }
1230
- //#endregion
1231
- //#region extensions/slack/src/question-actions.ts
1389
+ // extensions/slack/src/question-actions.ts
1232
1390
  const SLACK_QUESTION_VALUE_PREFIX = "slq1:";
1233
1391
  const QUESTION_RECORD_ID_PATTERN = /^ask_[a-f0-9]{32}$/u;
1234
1392
  function encodeSlackQuestionAction(action) {
@@ -1246,7 +1404,7 @@ function decodeSlackQuestionAction(value) {
1246
1404
  async function resolveSlackQuestionAction(params) {
1247
1405
  let result;
1248
1406
  try {
1249
- result = await (params.resolveQuestion ?? questionGatewayRuntime.resolveOption)({
1407
+ result = await questionGatewayRuntime.resolveOption({
1250
1408
  cfg: params.cfg,
1251
1409
  questionId: params.action.questionId,
1252
1410
  optionIndex: params.action.optionIndex,
@@ -1259,8 +1417,7 @@ async function resolveSlackQuestionAction(params) {
1259
1417
  }
1260
1418
  await params.respond(result.status === "answered" ? "Answer submitted." : "This question was already answered.").catch(() => {});
1261
1419
  }
1262
- //#endregion
1263
- //#region extensions/slack/src/reply-action-ids.ts
1420
+ // extensions/slack/src/reply-action-ids.ts
1264
1421
  const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
1265
1422
  const SLACK_REPLY_LINK_ACTION_ID = "openclaw:reply_link";
1266
1423
  const SLACK_SESSION_LINK_ACTION_ID = "openclaw:session_link";
@@ -1284,20 +1441,26 @@ function createSlackActionIdMatcher(...prefixes) {
1284
1441
  const isSlackQuestionActionId = createSlackActionIdMatcher(SLACK_BUTTON_ACTION_IDS.question);
1285
1442
  const isSlackApprovalActionId = createSlackActionIdMatcher(SLACK_BUTTON_ACTION_IDS.approval, SLACK_SELECT_ACTION_IDS.approval);
1286
1443
  const isSlackCallbackActionId = createSlackActionIdMatcher(SLACK_BUTTON_ACTION_IDS.callback, SLACK_SELECT_ACTION_IDS.callback);
1444
+ function isSlackQuestionActionForQuestion(action, questionId) {
1445
+ return Boolean(action.action_id && isSlackQuestionActionId(action.action_id) && decodeSlackQuestionAction(action.value)?.questionId === questionId);
1446
+ }
1287
1447
  /** Read only question control identities from the blocks actually sent to Slack. */
1288
- function resolveSlackQuestionActionIds(blocks) {
1448
+ function resolveSlackQuestionActionIds(blocks, questionId) {
1289
1449
  return (blocks ?? []).flatMap((block) => {
1290
1450
  if (block.type !== "actions") return [];
1291
- return (block.elements ?? []).flatMap(({ action_id }) => action_id && isSlackQuestionActionId(action_id) ? [action_id] : []);
1451
+ return (block.elements ?? []).flatMap((element) => element.action_id && (questionId ? isSlackQuestionActionForQuestion(element, questionId) : isSlackQuestionActionId(element.action_id)) ? [element.action_id] : []);
1292
1452
  });
1293
1453
  }
1294
- //#endregion
1295
- //#region extensions/slack/src/truncate.ts
1454
+ // extensions/slack/src/truncate.ts
1296
1455
  function truncateSlackText(value, max, whitespace = "trim") {
1297
1456
  const text = whitespace === "preserve" ? value : value.trim();
1298
1457
  if (text.length <= max) return text;
1299
1458
  if (max <= 1) return sliceUtf16Safe(text, 0, max);
1300
- return `${sliceUtf16Safe(text, 0, max - 1)}…`;
1459
+ return truncateWithMarker(text, max, {
1460
+ marker: "…",
1461
+ reserve: 1,
1462
+ trimEnd: false
1463
+ });
1301
1464
  }
1302
1465
  function countSlackTextUtf8Bytes(value) {
1303
1466
  return Buffer.byteLength(value, "utf8");
@@ -1310,102 +1473,10 @@ function truncateSlackTextByUtf8Bytes(value, maxBytes) {
1310
1473
  const suffix = "…";
1311
1474
  const suffixBytes = countSlackTextUtf8Bytes(suffix);
1312
1475
  const prefixBudget = maxBytes >= suffixBytes ? maxBytes - suffixBytes : maxBytes;
1313
- let prefix = "";
1314
- let prefixBytes = 0;
1315
- for (const character of trimmed) {
1316
- const characterBytes = countSlackTextUtf8Bytes(character);
1317
- if (prefixBytes + characterBytes > prefixBudget) break;
1318
- prefix += character;
1319
- prefixBytes += characterBytes;
1320
- }
1476
+ const prefix = truncateUtf8Prefix(trimmed, prefixBudget);
1321
1477
  return maxBytes >= suffixBytes ? `${prefix}${suffix}` : prefix;
1322
1478
  }
1323
- //#endregion
1324
- //#region extensions/slack/src/limits.ts
1325
- const SLACK_TEXT_LIMIT = 8e3;
1326
- const SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT = 4e3;
1327
- const SLACK_EDIT_TEXT_MAX_BYTES = 4e3;
1328
- const SLACK_MESSAGE_TEXT_HARD_LIMIT = 4e4;
1329
- //#endregion
1330
- //#region extensions/slack/src/blocks-fallback.ts
1331
- const SLACK_SELECT_ELEMENT_TYPES = /* @__PURE__ */ new Set([
1332
- "static_select",
1333
- "multi_static_select",
1334
- "external_select",
1335
- "multi_external_select",
1336
- "users_select",
1337
- "multi_users_select",
1338
- "conversations_select",
1339
- "multi_conversations_select",
1340
- "channels_select",
1341
- "multi_channels_select"
1342
- ]);
1343
- function readTextObject(value, options = {}) {
1344
- const record = asOptionalRecord(value);
1345
- const text = normalizeOptionalString(record?.text);
1346
- if (!text) return;
1347
- return record?.type === "plain_text" && options.nativeDataFormat !== "plain" ? escapeSlackMrkdwn(text) : text;
1348
- }
1349
- function readAltText(value) {
1350
- const text = normalizeOptionalString(value);
1351
- return text ? escapeSlackMrkdwn(text) : void 0;
1352
- }
1353
- function readControlElementText(value, options = {}) {
1354
- const element = asOptionalRecord(value);
1355
- const type = normalizeOptionalString(element?.type);
1356
- if (type === "button" || type === "workflow_button") return normalizeOptionalString(element?.text) ?? readTextObject(element?.text, options);
1357
- if (type && (SLACK_SELECT_ELEMENT_TYPES.has(type) || type === "overflow")) {
1358
- if (!options.includeSelectOptions) return readTextObject(element?.placeholder, options);
1359
- const choices = Array.isArray(element?.options) ? element.options : [];
1360
- return [readTextObject(element?.placeholder, options), ...choices.map((choice) => readTextObject(asOptionalRecord(choice)?.text, options))].filter(Boolean).join("\n");
1361
- }
1362
- }
1363
- function readControlElementsText(values, options = {}) {
1364
- const labels = values.map((value) => readControlElementText(value, options)).filter(Boolean);
1365
- return [...new Set(labels)].join("\n") || void 0;
1366
- }
1367
- function readTextLayout(block, options = {}) {
1368
- const context = block.type === "context";
1369
- return (context ? (Array.isArray(block.elements) ? block.elements : []).map((element) => {
1370
- const record = asOptionalRecord(element);
1371
- return readTextObject(record, options) ?? readAltText(record?.alt_text);
1372
- }) : [
1373
- readTextObject(block.text, options),
1374
- ...Array.isArray(block.fields) ? block.fields.map((field) => readTextObject(field, options)) : [],
1375
- readControlElementText(block.accessory, options)
1376
- ]).filter(Boolean).join(context ? " " : "\n") || void 0;
1377
- }
1378
- /** Read only user-visible text from one Slack block. */
1379
- function renderSlackBlockFallbackText(raw, options = {}) {
1380
- const block = asOptionalRecord(raw);
1381
- if (!block) return;
1382
- switch (block.type) {
1383
- case "rich_text": return normalizeOptionalString(renderSlackRichText(block.elements, options.nativeReferenceFormat === "plain" ? "native-reference" : "escaped", "\n"));
1384
- case "header": return readTextObject(block.text, options);
1385
- case "section":
1386
- case "context": return readTextLayout(block, options);
1387
- case "image": return readAltText(block.alt_text) ?? readTextObject(block.title) ?? "Shared an image";
1388
- case "video": return readTextObject(block.title, options) ?? readAltText(block.alt_text) ?? "Shared a video";
1389
- case "file": return "Shared a file";
1390
- case "actions": return Array.isArray(block.elements) ? readControlElementsText(block.elements, options) : void 0;
1391
- case "data_visualization": return renderSlackDataVisualizationFallbackText(block, options.nativeDataFormat !== "plain");
1392
- case "data_table": return renderSlackDataTableFallbackText(block, options.nativeDataFormat !== "plain");
1393
- case "table": return renderSlackTableFallbackText(block, options.nativeDataFormat !== "plain");
1394
- default: return;
1395
- }
1396
- }
1397
- function buildSlackBlocksFallbackText(blocks) {
1398
- for (const block of blocks) {
1399
- const text = renderSlackBlockFallbackText(block);
1400
- if (text) return text;
1401
- }
1402
- return "Shared a Block Kit message";
1403
- }
1404
- function buildSlackCompleteBlocksFallbackText(blocks, options = {}) {
1405
- return blocks.map((block) => renderSlackBlockFallbackText(block, options)).filter(Boolean).join("\n\n").trim() || buildSlackBlocksFallbackText(blocks);
1406
- }
1407
- //#endregion
1408
- //#region extensions/slack/src/native-data-blocks.ts
1479
+ // extensions/slack/src/native-data-blocks.ts
1409
1480
  const SLACK_MALFORMED_NATIVE_DATA_FALLBACK = "Slack could not render this chart or table data.";
1410
1481
  const SLACK_RESPONSE_URL_BODY_LIMIT_BYTES = 16384;
1411
1482
  const SLACK_RESPONSE_URL_BODY_TIMEOUT_MS = 3e4;
@@ -1508,14 +1579,12 @@ function appendSlackNativeDataFallbackText(text, blocks) {
1508
1579
  function appendSlackNativeDataPlainTextFallback(text, blocks) {
1509
1580
  return appendSlackBlockFallback(text.trim(), blocks, renderSlackNativeDataPlainTextBlock);
1510
1581
  }
1511
- //#endregion
1512
- //#region extensions/slack/src/detached-target-admission.ts
1582
+ // extensions/slack/src/detached-target-admission.ts
1513
1583
  function assertSlackDetachedTargetAllowed(accountId, teamId) {
1514
1584
  const installationKind = getSlackInstallationKind(accountId);
1515
1585
  if (installationKind && installationKind !== "workspace" && !teamId) throw new Error("unsupported_enterprise_slack_delivery: detached Slack operations require team:<team-id>:channel:<channel-id> or team:<team-id>:user:<user-id> until a workspace install is authenticated");
1516
1586
  }
1517
- //#endregion
1518
- //#region extensions/slack/src/conversation-binding-route.ts
1587
+ // extensions/slack/src/conversation-binding-route.ts
1519
1588
  const slackRouteBindingConfigCache = /* @__PURE__ */ new WeakMap();
1520
1589
  function normalizeSlackRouteBindingPeer(peer) {
1521
1590
  const rawId = peer.id.trim();
@@ -1536,7 +1605,7 @@ function normalizeSlackRouteBindingConfig(cfg) {
1536
1605
  const bindings = cfg.bindings;
1537
1606
  const cached = slackRouteBindingConfigCache.get(cfg);
1538
1607
  if (cached && cached.bindingsRef === bindings) return cached.normalizedCfg;
1539
- if (!Array.isArray(bindings)) return cfg;
1608
+ if (!bindings) return cfg;
1540
1609
  let changed = false;
1541
1610
  const normalizedBindings = bindings.map((binding) => {
1542
1611
  if (binding.type === "acp" || binding.match.channel.trim().toLowerCase() !== "slack") return binding;
@@ -1652,8 +1721,7 @@ function applySlackConfiguredBindingRoute(params, runtimeRoute) {
1652
1721
  route: runtimeRoute.boundSessionKey ? runtimeRoute.route : configuredRoute?.route ?? runtimeRoute.route
1653
1722
  };
1654
1723
  }
1655
- //#endregion
1656
- //#region extensions/slack/src/monitor/workspace-routing.ts
1724
+ // extensions/slack/src/monitor/workspace-routing.ts
1657
1725
  function resolveSlackAgentRoute(params) {
1658
1726
  const route = resolveAgentRoute({
1659
1727
  cfg: params.cfg,
@@ -1687,8 +1755,114 @@ function qualifySlackRoutePeerId(params) {
1687
1755
  function qualifySlackConversationId(conversationId, eventScope) {
1688
1756
  return eventScope ? `team:${encodeURIComponent(eventScope.teamId)}:${conversationId}` : conversationId;
1689
1757
  }
1690
- //#endregion
1691
- //#region extensions/slack/src/channel-policy-state.ts
1758
+ // extensions/slack/src/errors.ts
1759
+ const NO_ERROR_DETAIL = "no error detail";
1760
+ const MAX_ERROR_CAUSE_DEPTH = 32;
1761
+ function getSlackWebApiErrorData(error) {
1762
+ if (!(error instanceof Error)) return;
1763
+ const data = error.data;
1764
+ return data && typeof data === "object" ? data : void 0;
1765
+ }
1766
+ function addStringDetail(details, label, value) {
1767
+ if (typeof value !== "string") return;
1768
+ const trimmed = redactSensitiveText(value.trim());
1769
+ if (trimmed) details.push(label ? `${label}: ${trimmed}` : trimmed);
1770
+ }
1771
+ function addScalarDetail(details, label, value) {
1772
+ if (typeof value === "string") {
1773
+ addStringDetail(details, label, value);
1774
+ return;
1775
+ }
1776
+ if (typeof value === "number" || typeof value === "boolean") details.push(`${label}: ${String(value)}`);
1777
+ }
1778
+ function addStringListDetail(details, label, value) {
1779
+ if (!Array.isArray(value)) return;
1780
+ const entries = [];
1781
+ for (const entry of value) addStringDetail(entries, "", entry);
1782
+ if (entries.length) details.push(`${label}: ${entries.join(", ")}`);
1783
+ }
1784
+ function safeStringify(value) {
1785
+ const seen = /* @__PURE__ */ new WeakSet();
1786
+ try {
1787
+ const result = JSON.stringify(value, (_key, nested) => {
1788
+ if (typeof nested !== "object" || nested === null) return nested;
1789
+ if (seen.has(nested)) return "[Circular]";
1790
+ seen.add(nested);
1791
+ return nested;
1792
+ });
1793
+ return result ? redactSensitiveText(result) : void 0;
1794
+ } catch {
1795
+ return;
1796
+ }
1797
+ }
1798
+ function addSlackResponseMetadata(details, value) {
1799
+ if (!isRecord(value)) return;
1800
+ addStringListDetail(details, "scopes", value.scopes);
1801
+ addStringListDetail(details, "accepted", value.acceptedScopes);
1802
+ for (const [key, label] of [["messages", "slack message"], ["warnings", "slack warning"]]) {
1803
+ const entries = value[key];
1804
+ if (Array.isArray(entries)) for (const entry of entries) addStringDetail(details, label, entry);
1805
+ }
1806
+ }
1807
+ function addSlackDataDetails(details, value) {
1808
+ if (!isRecord(value)) return;
1809
+ addScalarDetail(details, "slack error", value.error);
1810
+ addScalarDetail(details, "needed", value.needed);
1811
+ addScalarDetail(details, "provided", value.provided);
1812
+ addSlackResponseMetadata(details, value.response_metadata);
1813
+ }
1814
+ function addRecordDetails(details, value) {
1815
+ addScalarDetail(details, "code", value.code);
1816
+ addScalarDetail(details, "status", value.status);
1817
+ addScalarDetail(details, "statusCode", value.statusCode);
1818
+ addScalarDetail(details, "statusMessage", value.statusMessage);
1819
+ addScalarDetail(details, "retryAfter", value.retryAfter);
1820
+ addScalarDetail(details, "errno", value.errno);
1821
+ addScalarDetail(details, "syscall", value.syscall);
1822
+ addScalarDetail(details, "hostname", value.hostname);
1823
+ addScalarDetail(details, "type", value.type);
1824
+ addStringDetail(details, "statusText", value.statusText);
1825
+ addStringDetail(details, "body", value.body);
1826
+ addSlackDataDetails(details, value.data);
1827
+ if (isRecord(value.response)) {
1828
+ addScalarDetail(details, "response status", value.response.status);
1829
+ addStringDetail(details, "response statusText", value.response.statusText);
1830
+ addSlackDataDetails(details, value.response.data);
1831
+ }
1832
+ }
1833
+ function collectSlackErrorDetails(error, seen) {
1834
+ const details = [];
1835
+ if (error === void 0 || error === null) return details;
1836
+ if (typeof error === "string") {
1837
+ addStringDetail(details, "", error);
1838
+ return details;
1839
+ }
1840
+ if (error instanceof Error) {
1841
+ addStringDetail(details, "", error.message || error.name);
1842
+ if (error.cause !== void 0) {
1843
+ const cause = formatSlackErrorWithCauses(error.cause, "", seen);
1844
+ if (cause) details.push(`cause: ${cause}`);
1845
+ }
1846
+ }
1847
+ if (isRecord(error)) addRecordDetails(details, error);
1848
+ return details;
1849
+ }
1850
+ function formatSlackErrorWithCauses(error, fallback, seen) {
1851
+ if (error instanceof Error) {
1852
+ if (seen.has(error)) return "[Circular]";
1853
+ if (seen.size >= MAX_ERROR_CAUSE_DEPTH) return "[Cause chain truncated]";
1854
+ seen.add(error);
1855
+ }
1856
+ const details = collectSlackErrorDetails(error, seen);
1857
+ if (details.length > 0) return details.join("; ");
1858
+ if (error === void 0 || error === null) return fallback;
1859
+ if (typeof error === "string" && !error.trim()) return fallback;
1860
+ return safeStringify(error) ?? fallback;
1861
+ }
1862
+ function formatSlackError(error, fallback = NO_ERROR_DETAIL) {
1863
+ return formatSlackErrorWithCauses(error, fallback, /* @__PURE__ */ new Set());
1864
+ }
1865
+ // extensions/slack/src/channel-policy-state.ts
1692
1866
  const slackChannelPolicyBindings = resolveGlobalMap(Symbol.for("openclaw.slack.channel-policy-bindings"), "close-and-restart");
1693
1867
  function setSlackChannelPolicyBindings(accountId, bindings) {
1694
1868
  slackChannelPolicyBindings.set(normalizeAccountId(accountId), new Map([...bindings].map(([key, id]) => [key, id.toUpperCase()])));
@@ -1698,8 +1872,16 @@ function getSlackChannelPolicyKeys(accountId, channelId) {
1698
1872
  if (!id) return [];
1699
1873
  return [...slackChannelPolicyBindings.get(normalizeAccountId(accountId)) ?? []].filter(([, resolvedId]) => resolvedId === id).map(([key]) => key);
1700
1874
  }
1701
- //#endregion
1702
- //#region extensions/slack/src/group-policy.ts
1875
+ // extensions/slack/src/group-policy.ts
1876
+ function hasPotentialSlackNamedPolicy(params) {
1877
+ if (params.allowNameMatching !== true) return false;
1878
+ return Object.entries(params.channels ?? {}).some(([key, entry]) => {
1879
+ if (entry == null || key === "*") return false;
1880
+ const named = !/^(?:channel:)?[CDG][A-Z0-9]+$/i.test(key);
1881
+ const entryAllows = entry.enabled !== false;
1882
+ return named && (params.decision === "allow" ? entryAllows : !entryAllows);
1883
+ });
1884
+ }
1703
1885
  function buildSlackChannelIdCandidates(channelId, teamId, options) {
1704
1886
  const trimmedId = channelId?.trim();
1705
1887
  if (!trimmedId) return [];
@@ -1751,8 +1933,104 @@ function resolveSlackGroupToolPolicy(params) {
1751
1933
  senderE164: params.senderE164
1752
1934
  });
1753
1935
  }
1754
- //#endregion
1755
- //#region extensions/slack/src/session-status.ts
1936
+ // extensions/slack/src/monitor/ingress-identity.ts
1937
+ const SLACK_USER_NAME_KIND = "plugin:slack-user-name";
1938
+ const SLACK_WORKSPACE_USER_ID_KIND = "plugin:slack-workspace-user-id";
1939
+ function normalizeSlackUserId(raw) {
1940
+ const value = (raw ?? "").trim().toLowerCase();
1941
+ if (!value) return "";
1942
+ const mention = value.match(/^<@([a-z0-9_]+)>$/i);
1943
+ if (mention?.[1]) return mention[1];
1944
+ return value.replace(/^(slack:|user:)/, "");
1945
+ }
1946
+ function normalizeSlackWorkspaceUserEntry(entry) {
1947
+ const normalized = entry.trim().toLowerCase();
1948
+ if (!normalized) return null;
1949
+ try {
1950
+ const target = parseSlackTarget(normalized);
1951
+ if (target?.kind === "user" && target.teamId) return target.normalized;
1952
+ } catch {
1953
+ return null;
1954
+ }
1955
+ return null;
1956
+ }
1957
+ function normalizeSlackBareUserEntry(entry) {
1958
+ const normalized = entry.trim().toLowerCase();
1959
+ if (!normalized || normalizeSlackWorkspaceUserEntry(normalized)) return null;
1960
+ const userId = normalizeSlackUserId(normalized);
1961
+ return /^[ubw][a-z0-9_]+$/i.test(userId) ? userId : null;
1962
+ }
1963
+ function normalizeSlackStableEntry(entry) {
1964
+ return normalizeSlackBareUserEntry(entry) ?? normalizeSlackWorkspaceUserEntry(entry);
1965
+ }
1966
+ function normalizeSlackNameEntry(entry) {
1967
+ const normalized = entry.trim().toLowerCase();
1968
+ if (!normalized || normalizeSlackStableEntry(normalized)) return null;
1969
+ return normalized.replace(/^slack:/, "") || null;
1970
+ }
1971
+ function normalizeSlackNameSubject(value) {
1972
+ return value.trim().toLowerCase() || null;
1973
+ }
1974
+ function normalizeSlackNameSlugEntry(entry) {
1975
+ const name = normalizeSlackNameEntry(entry);
1976
+ if (!name) return null;
1977
+ return normalizeSlackSlug(name) || null;
1978
+ }
1979
+ const slackIngressIdentity = defineStableChannelIngressIdentity({
1980
+ resolveParticipant: (subject) => {
1981
+ const qualified = subject.aliases?.workspaceSenderId;
1982
+ if (typeof qualified !== "string") return;
1983
+ const normalized = normalizeSlackWorkspaceUserEntry(qualified);
1984
+ const target = normalized ? parseSlackTarget(normalized) : void 0;
1985
+ return target?.teamId ? {
1986
+ domain: target.teamId,
1987
+ idKind: target.id.startsWith("b") ? "bot-id" : "user-id",
1988
+ id: target.id
1989
+ } : void 0;
1990
+ },
1991
+ key: "senderId",
1992
+ kind: "stable-id",
1993
+ authentication: "asserted",
1994
+ normalizeEntry: normalizeSlackBareUserEntry,
1995
+ normalizeSubject: normalizeSlackUserId,
1996
+ sensitivity: "pii",
1997
+ aliases: [{
1998
+ key: "workspaceSenderId",
1999
+ kind: SLACK_WORKSPACE_USER_ID_KIND,
2000
+ authentication: "asserted",
2001
+ normalizeEntry: normalizeSlackWorkspaceUserEntry,
2002
+ normalizeSubject: normalizeSlackWorkspaceUserEntry,
2003
+ sensitivity: "pii"
2004
+ }, ...[["senderName", normalizeSlackNameEntry], ["senderNameSlug", normalizeSlackNameSlugEntry]].map(([key, normalizeEntry]) => ({
2005
+ key,
2006
+ kind: SLACK_USER_NAME_KIND,
2007
+ normalizeEntry,
2008
+ normalizeSubject: normalizeSlackNameSubject,
2009
+ authentication: "mutable",
2010
+ sensitivity: "pii"
2011
+ }))]
2012
+ });
2013
+ function createSlackIngressSubject(params) {
2014
+ const senderId = normalizeSlackUserId(params.senderId);
2015
+ const teamId = normalizeOptionalLowercaseString(params.teamId);
2016
+ const senderName = params.senderName?.trim().toLowerCase();
2017
+ const senderNameSlug = senderName ? normalizeSlackSlug(senderName) : void 0;
2018
+ return {
2019
+ stableId: params.senderId,
2020
+ authentication: {
2021
+ senderId: params.senderAuthentication ?? "asserted",
2022
+ workspaceSenderId: params.senderAuthentication ?? "asserted",
2023
+ senderName: "mutable",
2024
+ senderNameSlug: "mutable"
2025
+ },
2026
+ aliases: {
2027
+ workspaceSenderId: teamId && senderId ? `team:${teamId}:user:${senderId}` : void 0,
2028
+ senderName,
2029
+ senderNameSlug
2030
+ }
2031
+ };
2032
+ }
2033
+ // extensions/slack/src/session-status.ts
1756
2034
  const MISSING_STOP_SUBSCRIPTION = "missing_agent_session_stopped_event_subscription";
1757
2035
  let warnedMissingStopSubscription = false;
1758
2036
  async function setSlackSessionStatus(params) {
@@ -1793,5 +2071,64 @@ async function renameSlackSession(params) {
1793
2071
  return false;
1794
2072
  }
1795
2073
  }
1796
- //#endregion
1797
- export { buildSlackDataVisualizationBlock as $, SLACK_MESSAGE_TEXT_HARD_LIMIT as A, resolveSlackApprovalTeamId as At, SLACK_REPLY_SELECT_ACTION_ID as B, resolvePluginApprovalSlackApprovers as Bt, isSlackNativeResponseUrlRejection as C, resolveSlackFallbackOriginTarget as Ct, buildSlackCompleteBlocksFallbackText as D, slackTargetsMatch as Dt, buildSlackBlocksFallbackText as E, shouldHandleSlackPluginViaForwardingSession as Et, truncateSlackTextByUtf8Bytes as F, isSlackExecApprovalAuthorizedSender as Ft, isSlackQuestionActionId as G, SLACK_SESSION_LINK_ACTION_ID as H, resolveSlackAutoThreadId as Ht, SLACK_BUTTON_ACTION_IDS as I, isSlackExecApprovalClientEnabled as It, encodeSlackQuestionAction as J, resolveSlackQuestionActionIds as K, SLACK_QUESTION_FINALIZATION_BLOCKS as L, normalizeSlackApproverId as Lt, SLACK_TEXT_LIMIT as M, isSlackWorkspaceInstallation as Mt, countSlackTextUtf8Bytes as N, registerSlackInstallationState as Nt, renderSlackBlockFallbackText as O, getSlackApprovalApproversForTeam as Ot, truncateSlackText as P, getSlackExecApprovalApprovers as Pt, normalizeSlackOutboundText as Q, SLACK_REPLY_BUTTON_ACTION_ID as R, resolveSlackExecApprovalTarget as Rt, isSlackInvalidBlocksResponse as S, resolveSlackApproverDmTargets as St, stripSlackNativeDataBlocks as T, shouldHandleSlackNativeApprovalRequest as Tt, isSlackApprovalActionId as U, SLACK_SELECT_ACTION_IDS as V, SLACK_PRIVATE_ACTION_DELIVERY_RESULT as Vt, isSlackCallbackActionId as W, chunkSlackMrkdwnText as X, resolveSlackQuestionAction as Y, markdownToSlackMrkdwnChunks as Z, appendSlackNativeDataPlainTextFallback as _, isSlackAnyNativeApprovalClientEnabled as _t, resolveSlackGroupRequireMention as a, renderSlackMessagePresentationChartFallbackText as at, hasSlackNativeDataBlock as b, normalizeSlackOriginTarget as bt, qualifySlackConversationId as c, SLACK_APPROVAL_HEADER_BLOCK_ID as ct, normalizeSlackRouteBindingConfig as d, SLACK_BUTTON_VALUE_MAX as dt, hasSlackDataVisualizationBlock as et, resolveSlackConversationBindingRoute as f, SLACK_PRESENTATION_CAPABILITIES as ft, appendSlackNativeDataFallbackText as g, validateSlackBlocksArray as gt, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as h, parseSlackBlocksInput as ht, buildSlackChannelPolicyScope as i, countSlackDataTableCellCharacters as it, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as j, getSlackInstallationKind as jt, SLACK_EDIT_TEXT_MAX_BYTES as k, isSlackPluginApprovalAuthorizedSender as kt, qualifySlackRoutePeerId as l, decodeSlackApprovalAction as lt, assertSlackDetachedTargetAllowed as m, SLACK_MAX_BLOCKS as mt, setSlackSessionStatus as n, buildSlackDataTableBlock as nt, resolveSlackGroupToolPolicy as o, renderSlackMessagePresentationFallbackText as ot, resolveSlackConversationBindingRouteAsync as p, SLACK_SECTION_TEXT_MAX as pt, decodeSlackQuestionAction as q, buildSlackChannelIdCandidates as r, countSlackDataTableBlocksCellCharacters as rt, setSlackChannelPolicyBindings as s, escapeSlackMrkdwn as st, renameSlackSession as t, SLACK_DATA_TABLE_AGGREGATE_CELL_CHARACTERS_MAX as tt, resolveSlackAgentRoute as u, encodeSlackApprovalAction as ut, buildSlackNativeDataAccessibilityText as v, isSlackPluginApprovalRequest as vt, renderSlackNativeDataPlainTextBlock as w, resolveTurnSourceSlackOriginTarget as wt, isSlackInvalidBlocksError as x, resolveSessionSlackOriginTarget as xt, createSlackNativeDataBaseTextConsumer as y, normalizeSlackForwardTarget as yt, SLACK_REPLY_LINK_ACTION_ID as z, shouldSuppressLocalSlackExecApprovalPrompt as zt };
2074
+ // extensions/slack/src/probe.ts
2075
+ var probe_exports = /* @__PURE__ */ __exportAll({ probeSlack: () => probeSlack });
2076
+ async function probeSlack(token, timeoutMs = 2500, opts) {
2077
+ const dispatcher = createSlackProbeDispatcher(timeoutMs);
2078
+ const client = createSlackReadClient(token, {
2079
+ rejectRateLimitedCalls: true,
2080
+ retryConfig: { retries: 0 },
2081
+ timeout: timeoutMs
2082
+ }, dispatcher);
2083
+ const probeResult = runChannelProbe(timeoutMs, async () => {
2084
+ const result = await client.auth.test();
2085
+ if (!result.ok) return {
2086
+ ok: false,
2087
+ status: 200,
2088
+ error: result.error ?? "unknown"
2089
+ };
2090
+ const userIdentity = opts?.identity === "user";
2091
+ let userId = result.user_id;
2092
+ if (userIdentity) {
2093
+ if (result.bot_id?.trim()) return {
2094
+ ok: false,
2095
+ status: 200,
2096
+ error: "Slack auth.test identified a bot token; user identity requires a user OAuth token"
2097
+ };
2098
+ userId = result.user_id?.trim();
2099
+ if (!userId) return {
2100
+ ok: false,
2101
+ status: 200,
2102
+ error: "Slack auth.test returned no human user_id for user identity"
2103
+ };
2104
+ }
2105
+ const warning = userIdentity ? void 0 : formatSlackBotTokenIdentityWarning({
2106
+ auth: result,
2107
+ accountId: opts?.accountId
2108
+ });
2109
+ const authIdentity = {
2110
+ id: userId,
2111
+ name: result.user
2112
+ };
2113
+ return {
2114
+ ok: true,
2115
+ status: 200,
2116
+ ...userIdentity ? { user: authIdentity } : { bot: authIdentity },
2117
+ team: {
2118
+ id: result.team_id,
2119
+ name: result.team
2120
+ },
2121
+ ...warning ? { warning } : {}
2122
+ };
2123
+ }, (error) => ({
2124
+ ok: false,
2125
+ status: typeof error.statusCode === "number" ? error.statusCode : null,
2126
+ error: formatSlackError(error)
2127
+ }));
2128
+ try {
2129
+ return await probeResult;
2130
+ } finally {
2131
+ await dispatcher.destroy().catch(() => void 0);
2132
+ }
2133
+ }
2134
+ export { decodeSlackApprovalAction as $, resolveSlackExecApprovalTarget as $t, isSlackInvalidBlocksResponse as A, resolveSessionSlackOriginTarget as At, SLACK_REPLY_LINK_ACTION_ID as B, allowListMatches as Bt, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as C, markdownToSlackMrkdwnChunks as Ct, createSlackNativeDataBaseTextConsumer as D, isSlackPluginApprovalRequest as Dt, buildSlackNativeDataAccessibilityText as E, isSlackAnyNativeApprovalClientEnabled as Et, truncateSlackText as F, shouldHandleSlackPluginViaForwardingSession as Ft, isSlackCallbackActionId as G, resolveSlackUserAllowed as Gt, SLACK_SELECT_ACTION_IDS as H, normalizeSlackSlug as Ht, truncateSlackTextByUtf8Bytes as I, slackTargetsMatch as It, resolveSlackQuestionActionIds as J, registerSlackInstallationState as Jt, isSlackQuestionActionForQuestion as K, getSlackInstallationKind as Kt, SLACK_BUTTON_ACTION_IDS as L, getSlackApprovalApproversForTeam as Lt, renderSlackNativeDataPlainTextBlock as M, resolveSlackFallbackOriginTarget as Mt, stripSlackNativeDataBlocks as N, resolveTurnSourceSlackOriginTarget as Nt, hasSlackNativeDataBlock as O, normalizeSlackForwardTarget as Ot, countSlackTextUtf8Bytes as P, shouldHandleSlackNativeApprovalRequest as Pt, SLACK_APPROVAL_HEADER_BLOCK_ID as Q, normalizeSlackApproverId as Qt, SLACK_QUESTION_FINALIZATION_BLOCKS as R, isSlackPluginApprovalAuthorizedSender as Rt, assertSlackDetachedTargetAllowed as S, chunkSlackMrkdwnText as St, appendSlackNativeDataPlainTextFallback as T, escapeSlackMrkdwn as Tt, SLACK_SESSION_LINK_ACTION_ID as U, resolveSlackAllowListMatch as Ut, SLACK_REPLY_SELECT_ACTION_ID as V, normalizeSlackAllowOwnerEntry as Vt, isSlackApprovalActionId as W, resolveSlackUserAllowListForTeam as Wt, encodeSlackQuestionAction as X, isSlackExecApprovalAuthorizedSender as Xt, decodeSlackQuestionAction as Y, getSlackExecApprovalApprovers as Yt, resolveSlackQuestionAction as Z, isSlackExecApprovalClientEnabled as Zt, qualifySlackRoutePeerId as _, renderSlackMessagePresentationFallbackText as _t, SLACK_USER_NAME_KIND as a, buildSlackCompleteBlocksFallbackText as at, resolveSlackConversationBindingRoute as b, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as bt, buildSlackChannelIdCandidates as c, hasSlackDataVisualizationBlock as ct, resolveSlackGroupRequireMention as d, countSlackDataTableBlocksCellCharacters as dt, shouldSuppressLocalSlackExecApprovalPrompt as en, encodeSlackApprovalAction as et, resolveSlackGroupToolPolicy as f, countSlackDataTableCellCharacters as ft, qualifySlackConversationId as g, renderSlackMessagePresentationChartFallbackText as gt, getSlackWebApiErrorData as h, SLACK_SECTION_TEXT_MAX as ht, setSlackSessionStatus as i, resolveSlackThreadTsFromContext as in, buildSlackBlocksFallbackText as it, isSlackNativeResponseUrlRejection as j, resolveSlackApproverDmTargets as jt, isSlackInvalidBlocksError as k, normalizeSlackOriginTarget as kt, buildSlackChannelPolicyScope as l, SLACK_DATA_TABLE_AGGREGATE_CELL_CHARACTERS_MAX as lt, formatSlackError as m, SLACK_PRESENTATION_CAPABILITIES as mt, probe_exports as n, SLACK_PRIVATE_ACTION_DELIVERY_RESULT as nn, parseSlackBlocksInput as nt, createSlackIngressSubject as o, renderSlackBlockFallbackText as ot, setSlackChannelPolicyBindings as p, SLACK_BUTTON_VALUE_MAX as pt, isSlackQuestionActionId as q, isSlackWorkspaceInstallation as qt, renameSlackSession as r, resolveSlackAutoThreadId as rn, validateSlackBlocksArray as rt, slackIngressIdentity as s, buildSlackDataVisualizationBlock as st, probeSlack as t, resolvePluginApprovalSlackApprovers as tn, SLACK_MAX_BLOCKS as tt, hasPotentialSlackNamedPolicy as u, buildSlackDataTableBlock as ut, resolveSlackAgentRoute as v, SLACK_EDIT_TEXT_MAX_BYTES as vt, appendSlackNativeDataFallbackText as w, normalizeSlackOutboundText as wt, resolveSlackConversationBindingRouteAsync as x, SLACK_TEXT_LIMIT as xt, normalizeSlackRouteBindingConfig as y, SLACK_MESSAGE_TEXT_HARD_LIMIT as yt, SLACK_REPLY_BUTTON_ACTION_ID as z, resolveSlackApprovalTeamId as zt };