@openclaw/slack 2026.9.6 → 2026.9.7

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 (291) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{account-inspect-DP1Bcwj4.mjs → account-inspect-DWBXpER6.mjs} +1 -1
  3. package/dist/.setup/{accounts-BBHvg0pY.mjs → accounts-D_N9IqNA.mjs} +23 -1
  4. package/dist/.setup/{action-runtime-B01d85zt.mjs → action-runtime-DfWvuiZd.mjs} +26 -41
  5. package/dist/.setup/action-runtime.runtime-Ck4bAWOX.mjs +2 -0
  6. package/dist/.setup/{actions-DKCtBgCI.mjs → actions-Df0CzcDl.mjs} +88 -175
  7. package/dist/.setup/{approval-handler.runtime-DMszKn_7.mjs → approval-handler.runtime-Ed6Sw5VK.mjs} +37 -47
  8. package/dist/.setup/{approval-message-updates-Tb_qRokK.mjs → approval-message-updates-BadvtA7R.mjs} +1 -2
  9. package/dist/.setup/{channel-CErYZ5zw.mjs → channel-C7bgPSTE.mjs} +181 -273
  10. package/dist/.setup/channel-meta-C443t-lI.mjs +27 -0
  11. package/dist/.setup/{channel-type-Dxk8VJUb.mjs → channel-type-ClOttrZ5.mjs} +13 -21
  12. package/dist/.setup/{channel.setup-BVoUtdPn.mjs → channel.setup-Dh2jzAjN.mjs} +35 -42
  13. package/dist/.setup/{config-schema-CyL279e7.mjs → config-schema-BZCxmHKG.mjs} +24 -21
  14. package/dist/.setup/{directory-config-CQTSH45W.mjs → directory-config-BOUWH3hR.mjs} +7 -10
  15. package/dist/.setup/{directory-live-BCcj89QV.mjs → directory-live-B2O4B_Ho.mjs} +9 -21
  16. package/dist/.setup/doctor-contract-CRN1Z_c7.mjs +342 -0
  17. package/dist/.setup/{message-tool-api-C0PTFaNV.mjs → message-tool-api-Cu4lwlGy.mjs} +34 -48
  18. package/dist/.setup/{provider-C-jPaGt2.mjs → monitor-BPVfkumU.mjs} +2181 -2693
  19. package/dist/.setup/{outbound-adapter-A7Wdn8ZT.mjs → outbound-adapter-Bv48XUjq.mjs} +10 -21
  20. package/dist/.setup/{pipeline.runtime-BlPOexmJ.mjs → pipeline.runtime-B1H63Frf.mjs} +311 -457
  21. package/dist/.setup/{plugin-routes-C3X0eVaK.mjs → plugin-routes-B8tooDLj.mjs} +1 -1
  22. package/dist/.setup/{policy-BApW53pI.mjs → policy-D-jfM174.mjs} +5 -5
  23. package/dist/.setup/{probe-DiYIMPJo.mjs → probe-B2Y9qc_z.mjs} +101 -39
  24. package/dist/.setup/{registry-bbjH7IHX.mjs → registry-CIbMfuf8.mjs} +6 -2
  25. package/dist/.setup/{relay-source-DfOnjJTE.mjs → relay-source-BpKdjsll.mjs} +10 -12
  26. package/dist/.setup/{replies-BBAJxUOQ.mjs → replies-BAnUtr2f.mjs} +16 -76
  27. package/dist/.setup/{reply-blocks-Bm8kf6mK.mjs → reply-blocks-SE1kTE3I.mjs} +27 -154
  28. package/dist/.setup/{resolve-channels-BXbMBbJD.mjs → resolve-channels-XXBn8UU_.mjs} +4 -5
  29. package/dist/.setup/{resolve-users-65WqvIqD.mjs → resolve-users-DW0ngD03.mjs} +20 -22
  30. package/dist/.setup/{scopes-h3YB-mMs.mjs → scopes-CasuDvaa.mjs} +6 -17
  31. package/dist/.setup/{secret-contract-DxmvbxBF.mjs → secret-contract-BaZcu6P_.mjs} +15 -20
  32. package/dist/.setup/{secret-contract-api-D9UfYujm.mjs → secret-contract-api-Dp6290Vg.mjs} +1 -1
  33. package/dist/.setup/{security-audit-BypHqcq5.mjs → security-audit-BqDc-6VL.mjs} +1 -1
  34. package/dist/.setup/{send-Cp6omkOg.mjs → send-BOVLQi3n.mjs} +84 -171
  35. package/dist/.setup/{session-status-Cf7AvWOt.mjs → session-status-DscajIsd.mjs} +315 -238
  36. package/dist/.setup/{setup-plugin-api-dLPkL06L.mjs → setup-plugin-api-DTtbTKNk.mjs} +1 -1
  37. package/dist/.setup/{setup-surface-D3DLcCxu.mjs → setup-surface-Dn7QgWRE.mjs} +24 -56
  38. package/dist/.setup/{shared-CJ3arAFL.mjs → shared-qau-uDGl.mjs} +30 -56
  39. package/dist/.setup/{slash-dispatch.runtime-HFy_XvyO.mjs → slash-dispatch.runtime--AEzLVBF.mjs} +1 -1
  40. package/dist/.setup/{streaming-compat-B-e0mqM0.mjs → streaming-compat-C5Wut626.mjs} +31 -8
  41. package/dist/.setup/{target-parsing-DEsPjngB.mjs → target-parsing-FFE26kOV.mjs} +1 -7
  42. package/dist/.setup/{targets-Cku2KCvg.mjs → targets-C6LZQL1Q.mjs} +1 -1
  43. package/dist/.setup/{thread-ts-CukseRVL.mjs → thread-ts-Cvt7WD6B.mjs} +0 -1
  44. package/dist/account-inspect-api.js +1 -1
  45. package/dist/api.js +18 -17
  46. package/dist/channel-config-api.js +1 -1
  47. package/dist/channel-plugin-api.js +1 -1
  48. package/dist/directory-contract-api.js +1 -1
  49. package/dist/doctor-contract-api.js +1 -1
  50. package/dist/http-routes-api.js +1 -1
  51. package/dist/index.js +1 -1
  52. package/dist/message-tool-api.js +1 -1
  53. package/dist/runtime-api.js +11 -12
  54. package/dist/secret-contract-api.js +1 -1
  55. package/dist/security-contract-api.js +1 -1
  56. package/dist/setup-entry.js +2 -2
  57. package/dist/setup-plugin-api.js +1 -1
  58. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  59. package/node_modules/@slack/bolt/node_modules/@types/node/child_process.d.ts +1 -1
  60. package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +20 -8
  61. package/node_modules/@slack/bolt/node_modules/@types/node/ffi.d.ts +14 -0
  62. package/node_modules/@slack/bolt/node_modules/@types/node/http2.d.ts +3 -2
  63. package/node_modules/@slack/bolt/node_modules/@types/node/net.d.ts +16 -4
  64. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  65. package/node_modules/@slack/bolt/node_modules/@types/node/process.d.ts +1 -0
  66. package/node_modules/@slack/bolt/node_modules/@types/node/quic.d.ts +39 -1
  67. package/node_modules/@slack/bolt/node_modules/@types/node/stream/iter.d.ts +9 -12
  68. package/node_modules/@slack/bolt/node_modules/@types/node/test/reporters.d.ts +1 -0
  69. package/node_modules/@slack/bolt/node_modules/@types/node/test.d.ts +72 -0
  70. package/node_modules/@slack/bolt/node_modules/@types/node/tls.d.ts +14 -10
  71. package/node_modules/@slack/bolt/node_modules/@types/node/vm.d.ts +2 -1
  72. package/node_modules/@slack/bolt/node_modules/@types/node/worker_threads.d.ts +4 -1
  73. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  74. package/node_modules/@slack/web-api/node_modules/@types/node/child_process.d.ts +1 -1
  75. package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +20 -8
  76. package/node_modules/@slack/web-api/node_modules/@types/node/ffi.d.ts +14 -0
  77. package/node_modules/@slack/web-api/node_modules/@types/node/http2.d.ts +3 -2
  78. package/node_modules/@slack/web-api/node_modules/@types/node/net.d.ts +16 -4
  79. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  80. package/node_modules/@slack/web-api/node_modules/@types/node/process.d.ts +1 -0
  81. package/node_modules/@slack/web-api/node_modules/@types/node/quic.d.ts +39 -1
  82. package/node_modules/@slack/web-api/node_modules/@types/node/stream/iter.d.ts +9 -12
  83. package/node_modules/@slack/web-api/node_modules/@types/node/test/reporters.d.ts +1 -0
  84. package/node_modules/@slack/web-api/node_modules/@types/node/test.d.ts +72 -0
  85. package/node_modules/@slack/web-api/node_modules/@types/node/tls.d.ts +14 -10
  86. package/node_modules/@slack/web-api/node_modules/@types/node/vm.d.ts +2 -1
  87. package/node_modules/@slack/web-api/node_modules/@types/node/worker_threads.d.ts +4 -1
  88. package/node_modules/get-east-asian-width/index.js +8 -3
  89. package/node_modules/get-east-asian-width/lookup-data.js +1 -1
  90. package/node_modules/get-east-asian-width/lookup.js +4 -4
  91. package/node_modules/get-east-asian-width/package.json +1 -1
  92. package/node_modules/typebox/build/compile/code.mjs +1 -2
  93. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  94. package/node_modules/typebox/build/format/iri.mjs +16 -9
  95. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  96. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  97. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  98. package/node_modules/typebox/build/guard/index.mjs +6 -0
  99. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  100. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  101. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  102. package/node_modules/typebox/build/schema/build.mjs +2 -3
  103. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  104. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  105. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  106. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  107. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  108. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  109. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  110. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  111. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  112. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  113. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  114. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  115. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  116. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  117. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  118. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  119. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  120. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  121. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  122. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  123. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  124. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  125. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  126. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  127. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  128. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  129. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  130. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  131. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  132. package/node_modules/typebox/package.json +1 -1
  133. package/node_modules/typebox/readme.md +3 -1
  134. package/node_modules/undici/README.md +81 -25
  135. package/node_modules/undici/docs/docs/api/Agent.md +249 -42
  136. package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
  137. package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
  138. package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
  139. package/node_modules/undici/docs/docs/api/Client.md +407 -162
  140. package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
  141. package/node_modules/undici/docs/docs/api/Connector.md +118 -35
  142. package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
  143. package/node_modules/undici/docs/docs/api/Cookies.md +122 -71
  144. package/node_modules/undici/docs/docs/api/Debug.md +34 -18
  145. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
  146. package/node_modules/undici/docs/docs/api/Dispatcher.md +490 -1055
  147. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +105 -93
  148. package/node_modules/undici/docs/docs/api/Errors.md +503 -28
  149. package/node_modules/undici/docs/docs/api/EventSource.md +326 -13
  150. package/node_modules/undici/docs/docs/api/Fetch.md +681 -30
  151. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -96
  152. package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
  153. package/node_modules/undici/docs/docs/api/Interceptors.md +418 -0
  154. package/node_modules/undici/docs/docs/api/MockAgent.md +333 -314
  155. package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
  156. package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
  157. package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
  158. package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
  159. package/node_modules/undici/docs/docs/api/MockPool.md +321 -258
  160. package/node_modules/undici/docs/docs/api/Pool.md +236 -41
  161. package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
  162. package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
  163. package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -55
  164. package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -27
  165. package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -79
  166. package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
  167. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +262 -517
  168. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +177 -196
  169. package/node_modules/undici/docs/docs/api/Util.md +68 -11
  170. package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
  171. package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
  172. package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
  173. package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
  174. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +233 -0
  175. package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
  176. package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
  177. package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
  178. package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
  179. package/node_modules/undici/docs/docs/getting-started.md +281 -0
  180. package/node_modules/undici/docs/docs/index.md +784 -0
  181. package/node_modules/undici/docs/docs/site.json +125 -0
  182. package/node_modules/undici/docs/docs/type-map.json +79 -0
  183. package/node_modules/undici/index.js +4 -2
  184. package/node_modules/undici/lib/api/api-connect.js +13 -11
  185. package/node_modules/undici/lib/api/api-pipeline.js +26 -13
  186. package/node_modules/undici/lib/api/api-request.js +51 -21
  187. package/node_modules/undici/lib/api/api-stream.js +81 -20
  188. package/node_modules/undici/lib/api/api-upgrade.js +21 -11
  189. package/node_modules/undici/lib/api/readable.js +45 -9
  190. package/node_modules/undici/lib/cache/memory-cache-store.js +3 -3
  191. package/node_modules/undici/lib/cache/sqlite-cache-store.js +3 -1
  192. package/node_modules/undici/lib/core/connect.js +46 -7
  193. package/node_modules/undici/lib/core/constants.js +1 -24
  194. package/node_modules/undici/lib/core/errors.js +22 -2
  195. package/node_modules/undici/lib/core/request.js +100 -18
  196. package/node_modules/undici/lib/core/symbols.js +4 -0
  197. package/node_modules/undici/lib/core/util.js +105 -48
  198. package/node_modules/undici/lib/dispatcher/agent.js +51 -32
  199. package/node_modules/undici/lib/dispatcher/balanced-pool.js +23 -27
  200. package/node_modules/undici/lib/dispatcher/client-h1.js +86 -24
  201. package/node_modules/undici/lib/dispatcher/client-h2.js +1091 -361
  202. package/node_modules/undici/lib/dispatcher/client.js +109 -36
  203. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +19 -6
  204. package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -5
  205. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +110 -0
  206. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +37 -8
  207. package/node_modules/undici/lib/dispatcher/h2c-client.js +4 -4
  208. package/node_modules/undici/lib/dispatcher/pool-base.js +28 -10
  209. package/node_modules/undici/lib/dispatcher/pool.js +30 -5
  210. package/node_modules/undici/lib/dispatcher/proxy-agent.js +95 -19
  211. package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
  212. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +32 -10
  213. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +153 -63
  214. package/node_modules/undici/lib/global.js +37 -14
  215. package/node_modules/undici/lib/handler/cache-handler.js +49 -7
  216. package/node_modules/undici/lib/handler/cache-revalidation-handler.js +10 -0
  217. package/node_modules/undici/lib/handler/decorator-handler.js +8 -3
  218. package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
  219. package/node_modules/undici/lib/handler/redirect-handler.js +66 -66
  220. package/node_modules/undici/lib/handler/retry-handler.js +191 -50
  221. package/node_modules/undici/lib/interceptor/cache.js +75 -25
  222. package/node_modules/undici/lib/interceptor/decompress.js +5 -2
  223. package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
  224. package/node_modules/undici/lib/interceptor/dns.js +12 -1
  225. package/node_modules/undici/lib/interceptor/redirect.js +3 -3
  226. package/node_modules/undici/lib/llhttp/llhttp-wasm.js +1 -1
  227. package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +1 -1
  228. package/node_modules/undici/lib/mock/mock-agent.js +21 -9
  229. package/node_modules/undici/lib/mock/mock-call-history.js +1 -1
  230. package/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
  231. package/node_modules/undici/lib/mock/mock-utils.js +281 -47
  232. package/node_modules/undici/lib/mock/snapshot-agent.js +25 -7
  233. package/node_modules/undici/lib/mock/snapshot-recorder.js +38 -3
  234. package/node_modules/undici/lib/util/cache.js +92 -10
  235. package/node_modules/undici/lib/util/runtime-features.js +3 -34
  236. package/node_modules/undici/lib/web/cache/cache.js +6 -8
  237. package/node_modules/undici/lib/web/cookies/parse.js +150 -146
  238. package/node_modules/undici/lib/web/cookies/util.js +1 -1
  239. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
  240. package/node_modules/undici/lib/web/eventsource/eventsource.js +20 -21
  241. package/node_modules/undici/lib/web/eventsource/util.js +32 -1
  242. package/node_modules/undici/lib/web/fetch/body.js +48 -10
  243. package/node_modules/undici/lib/web/fetch/constants.js +1 -1
  244. package/node_modules/undici/lib/web/fetch/formdata.js +21 -2
  245. package/node_modules/undici/lib/web/fetch/index.js +242 -223
  246. package/node_modules/undici/lib/web/fetch/request.js +35 -6
  247. package/node_modules/undici/lib/web/fetch/response.js +1 -3
  248. package/node_modules/undici/lib/web/fetch/util.js +10 -2
  249. package/node_modules/undici/lib/web/webidl/index.js +5 -7
  250. package/node_modules/undici/lib/web/websocket/frame.js +1 -7
  251. package/node_modules/undici/lib/web/websocket/receiver.js +1 -1
  252. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +10 -10
  253. package/node_modules/undici/lib/web/websocket/websocket.js +25 -3
  254. package/node_modules/undici/package.json +10 -10
  255. package/node_modules/undici/types/agent.d.ts +0 -2
  256. package/node_modules/undici/types/client.d.ts +69 -24
  257. package/node_modules/undici/types/connector.d.ts +1 -0
  258. package/node_modules/undici/types/cookies.d.ts +1 -1
  259. package/node_modules/undici/types/dispatcher.d.ts +8 -30
  260. package/node_modules/undici/types/dispatcher1-wrapper.d.ts +7 -0
  261. package/node_modules/undici/types/errors.d.ts +10 -0
  262. package/node_modules/undici/types/fetch.d.ts +5 -1
  263. package/node_modules/undici/types/formdata.d.ts +0 -6
  264. package/node_modules/undici/types/h2c-client.d.ts +6 -6
  265. package/node_modules/undici/types/handlers.d.ts +2 -0
  266. package/node_modules/undici/types/header.d.ts +5 -0
  267. package/node_modules/undici/types/index.d.ts +3 -1
  268. package/node_modules/undici/types/interceptors.d.ts +1 -1
  269. package/node_modules/undici/types/mock-agent.d.ts +11 -10
  270. package/node_modules/undici/types/mock-interceptor.d.ts +5 -1
  271. package/node_modules/undici/types/pool.d.ts +0 -2
  272. package/node_modules/undici/types/proxy-agent.d.ts +9 -2
  273. package/node_modules/undici/types/round-robin-pool.d.ts +0 -2
  274. package/node_modules/undici/types/snapshot-agent.d.ts +4 -0
  275. package/node_modules/undici/types/socks5-proxy-agent.d.ts +4 -2
  276. package/node_modules/undici/types/webidl.d.ts +0 -1
  277. package/openclaw.plugin.json +31 -3
  278. package/package.json +7 -7
  279. package/dist/.setup/accounts.runtime-DN-PPocC.mjs +0 -2
  280. package/dist/.setup/action-runtime.runtime-C8R8CUan.mjs +0 -2
  281. package/dist/.setup/doctor-contract-CtMUqjvk.mjs +0 -186
  282. package/dist/.setup/monitor-_Sht7Dqy.mjs +0 -13
  283. package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
  284. package/dist/.setup/send.runtime-B4caZU6T.mjs +0 -2
  285. package/dist/.setup/slash-commands.runtime-BpSH0b3q.mjs +0 -2
  286. package/dist/.setup/slash-skill-commands.runtime-Bi1JWZHY.mjs +0 -2
  287. package/node_modules/undici/lib/handler/unwrap-handler.js +0 -106
  288. package/node_modules/undici/lib/handler/wrap-handler.js +0 -105
  289. package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  290. package/node_modules/undici/lib/util/promise.js +0 -28
  291. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
@@ -1,27 +1,29 @@
1
- import { A as countSlackTextUtf8Bytes, C as buildSlackBlocksFallbackText, E as SLACK_EDIT_TEXT_MAX_BYTES, H as SLACK_SESSION_LINK_ACTION_ID, M as truncateSlackTextByUtf8Bytes, Pt as resolveSlackReplyToMode, Y as normalizeSlackOutboundText, c as qualifySlackRoutePeerId, j as truncateSlackText, k as SLACK_TEXT_LIMIT, ot as escapeSlackMrkdwn, v as hasSlackNativeDataBlock } from "./session-status-Cf7AvWOt.mjs";
2
- import { n as formatSlackTarget } from "./target-parsing-DEsPjngB.mjs";
3
- import { A as resolveSlackUserAllowed, E as normalizeSlackAllowOwnerEntry, T as normalizeAllowListLower, o as formatSlackError } from "./probe-DiYIMPJo.mjs";
4
- import { a as prepareSlackReply, l as resolveSlackReplyRenderPlan } from "./reply-blocks-Bm8kf6mK.mjs";
5
- import { n as resolveSlackReplyThreadTs } from "./thread-ts-CukseRVL.mjs";
6
- import { n as resolveSlackStreamingMode, t as resolveSlackNativeStreaming } from "./streaming-compat-B-e0mqM0.mjs";
7
- import { D as resolveSlackMessageText$1, E as resolveSlackBlocksText, O as buildSlackEditTextPayload, S as formatSlackFileReferenceList, T as isSlackUnfurlAttachment, a as editSlackRenderedMessage, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, v as logVerbose$1, w as hasSlackTableBlock, x as formatSlackFileReference } from "./actions-DKCtBgCI.mjs";
8
- import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-Cp6omkOg.mjs";
9
- import { A as resolveChannelContextVisibilityMode, D as readSlackAssistantThreadContext, E as buildSlackAssistantThreadMetadata, F as stripSlackMentionsForCommandDetection, M as resolveStorePath, N as updateLastRoute, O as getSessionEntry, T as resolveSlackChatType, _ as SlackStreamNotDeliveredError, b as startSlackStream, d as resolveSlackRoutingContext, f as registerSlackSessionRun, g as resolveSlackEffectiveAllowFrom, h as resolveSlackCommandIngress, j as resolveChannelResetConfig, k as readSessionUpdatedAt, l as authorizeSlackDirectMessage, m as authorizeSlackBotRoomMessage, o as resolveSlackRoomContextHints, p as resolveSlackThreadTargets, r as trackSlackDraftMessage, u as resolveConversationLabel, v as appendSlackStream, w as normalizeSlackChannelType, x as stopSlackStream, y as markSlackStreamFallbackDelivered } from "./provider-C-jPaGt2.mjs";
10
- import { n as resolveSlackChannelConfig } from "./policy-BApW53pI.mjs";
11
- import { a as resolveSlackThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as sanitizeSlackMonitorReplyPayload, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-BBAJxUOQ.mjs";
12
- import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
1
+ import { i as __reExport, n as resolveSlackStreamingMode, r as __exportAll, t as resolveSlackNativeStreaming } from "./streaming-compat-C5Wut626.mjs";
2
+ import { f as resolveSlackReplyToMode } from "./accounts-D_N9IqNA.mjs";
3
+ import { n as formatSlackTarget } from "./target-parsing-FFE26kOV.mjs";
4
+ import { A as countSlackTextUtf8Bytes, C as buildSlackBlocksFallbackText, E as SLACK_EDIT_TEXT_MAX_BYTES, H as SLACK_SESSION_LINK_ACTION_ID, M as truncateSlackTextByUtf8Bytes, Q as normalizeSlackOutboundText, c as qualifySlackRoutePeerId, j as truncateSlackText, k as SLACK_TEXT_LIMIT, lt as escapeSlackMrkdwn, v as hasSlackNativeDataBlock, w as buildSlackCompleteBlocksFallbackText } from "./session-status-DscajIsd.mjs";
5
+ import { D as normalizeSlackAllowOwnerEntry, j as resolveSlackUserAllowed, o as formatSlackError, v as readLruMapEntry, y as writeLruMapEntry } from "./probe-B2Y9qc_z.mjs";
6
+ import { a as prepareSlackReply, l as resolveSlackReplyRenderPlan, s as resolveSlackReplyBlocks } from "./reply-blocks-SE1kTE3I.mjs";
7
+ import { n as resolveSlackReplyThreadTs } from "./thread-ts-Cvt7WD6B.mjs";
8
+ import { C as hasSlackTableBlock, D as buildSlackEditTextPayload, E as resolveSlackMessageText$1, T as resolveSlackBlocksText, a as editSlackRenderedMessage, b as formatSlackFileReference, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, w as isSlackUnfurlAttachment, x as formatSlackFileReferenceList } from "./actions-Df0CzcDl.mjs";
9
+ import { c as hasSlackThreadParticipationWithPersistence, i as clearSlackThreadFailureNotice, l as recordSlackThreadFailureNotice, o as hasSlackThreadFailureNotice, p as buildSlackNativeDataDeliveryPlan, s as hasSlackThreadParticipation, t as sendMessageSlack, u as recordSlackThreadParticipation } from "./send-BOVLQi3n.mjs";
10
+ import { n as resolveSlackChannelConfig } from "./policy-D-jfM174.mjs";
11
+ import { C as resolveSlackChatType, E as stripSlackMentionsForCommandDetection, S as normalizeSlackChannelType, T as readSlackAssistantThreadContext, _ as appendSlackStream, b as stopSlackStream, c as resolveSlackRoutingContext, g as SlackStreamNotDeliveredError, h as resolveSlackEffectiveAllowFrom, i as resolveSlackRoomContextHints, l as registerSlackSessionRun, m as resolveSlackCommandIngress, p as authorizeSlackBotRoomMessage, r as trackSlackDraftMessage, s as authorizeSlackDirectMessage, u as resolveSlackThreadContext, v as markSlackStreamFallbackDelivered, w as buildSlackAssistantThreadMetadata, y as startSlackStream } from "./monitor-BPVfkumU.mjs";
12
+ import { a as emitSlackMessageSentHooks, i as sanitizeSlackMonitorReplyPayload, n as deliverReplies, t as createSlackReplyDeliveryPlan } from "./replies-BAnUtr2f.mjs";
13
+ import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
13
14
  import { resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
14
- import { buildChannelProgressDraftLine, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressWorkCounter, createDraftStreamLoop, createFinalizableDraftLifecycle, createLivePreviewLifecycle, createMessageReceiptFromOutboundResults, formatChannelProgressDraftDiffStat, formatChannelProgressDraftText, formatPlanChecklistLines, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
15
+ import { buildChannelProgressDraftLine, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressWorkCounter, createDraftStreamLoop, createFinalizableDraftLifecycle, createLivePreviewLifecycle, createMessageReceiptFromOutboundResults, formatChannelProgressDraftDiffStat, formatPlanChecklistLines, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
15
16
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
16
17
  import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
17
18
  import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
18
19
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
20
+ import { normalizeStringEntriesLower } from "openclaw/plugin-sdk/string-normalization-runtime";
21
+ import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
19
22
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
20
23
  import { buildTtsSupplementMediaPayload, getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
21
24
  import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs, resolvePromptHistoryLimit } from "openclaw/plugin-sdk/number-runtime";
22
25
  import { hash } from "node:crypto";
23
- import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
24
- import { ensureConfiguredBindingRouteReady } from "openclaw/plugin-sdk/conversation-runtime";
26
+ import { ensureConfiguredBindingRouteReady, resolveConversationLabel } from "openclaw/plugin-sdk/conversation-runtime";
25
27
  import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
26
28
  import fs from "node:fs/promises";
27
29
  import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
@@ -29,16 +31,18 @@ import { formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-run
29
31
  import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist, shouldIncludeSupplementalContext } from "openclaw/plugin-sdk/security-runtime";
30
32
  import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
31
33
  import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
34
+ import { getSessionEntry, readSessionUpdatedAt, resolveChannelResetConfig, resolveStorePath, updateLastRoute } from "openclaw/plugin-sdk/session-store-runtime";
32
35
  import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
33
36
  import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
34
37
  import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
35
- import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, isGroupThreadRouteExclusive, matchesMentionWithExplicit, readAgentRunTerminalOutcome, resolveEnvelopeFormatOptions, resolveGroupThreadConfig, resolveGroupThreadMentionFacts, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
38
+ import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, isGroupThreadRouteExclusive, matchesMentionWithExplicit, readAgentRunTerminalOutcome, resolveEnvelopeFormatOptions, resolveGroupThreadConfig, resolveGroupThreadMentionFacts, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
36
39
  import { resolveGatewayPublicOrigin } from "openclaw/plugin-sdk/config-contracts";
37
40
  import { buildControlUiSessionPath } from "openclaw/plugin-sdk/session-discussion";
38
41
  import { createStatusReactionController, logAckFailure, logTypingFailure, resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
39
42
  import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
40
43
  import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
41
44
  import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
45
+ import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
42
46
  import { DEFAULT_GROUP_HISTORY_LIMIT, buildHistoryContextFromEntries, buildInboundHistoryFromEntries } from "openclaw/plugin-sdk/reply-history";
43
47
  import { createChannelPreflightAudio, formatAudioTranscriptForAgent } from "openclaw/plugin-sdk/media-understanding-runtime";
44
48
  //#region extensions/slack/src/monitor/message-handler/timestamp.ts
@@ -55,9 +59,6 @@ function resolveSlackTimestampMs(ts) {
55
59
  }
56
60
  //#endregion
57
61
  //#region extensions/slack/src/monitor/message-handler/dispatch-helpers.ts
58
- function resolveSlackMessageTimestampMs(message) {
59
- return resolveSlackTimestampMs(message.event_ts ?? message.ts);
60
- }
61
62
  function resolveSlackBotLoopProtection(prepared) {
62
63
  const senderBotId = prepared.message.bot_id;
63
64
  if (!senderBotId) return;
@@ -71,7 +72,7 @@ function resolveSlackBotLoopProtection(prepared) {
71
72
  config: mergePairLoopGuardConfig(prepared.account.config.botLoopProtection, prepared.channelConfig?.botLoopProtection),
72
73
  defaultsConfig: prepared.ctx.cfg.channels?.defaults?.botLoopProtection,
73
74
  defaultEnabled: true,
74
- nowMs: resolveSlackMessageTimestampMs(prepared.message)
75
+ nowMs: resolveSlackTimestampMs(prepared.message.event_ts ?? prepared.message.ts)
75
76
  };
76
77
  }
77
78
  function isSlackStreamingEnabled(params) {
@@ -89,26 +90,14 @@ function resolveExplicitSlackProgressTitle(entry) {
89
90
  const trimmed = label.trim();
90
91
  return trimmed && trimmed.toLowerCase() !== "auto" ? trimmed : void 0;
91
92
  }
92
- function resolveSlackProgressStyle(entry) {
93
+ function resolveSlackProgressStyle(entry, hasReplyThread) {
93
94
  const progress = entry?.streaming?.progress;
95
+ if (!hasReplyThread && !Object.entries(progress ?? {}).some(([key, value]) => key !== "nativeTaskCards" || value !== true)) return "none";
94
96
  return progress?.style ?? (progress?.toolProgress === false ? "compact" : "card");
95
97
  }
96
- function resolveSlackNativeProgressTaskCards(entry) {
97
- if (resolveSlackProgressStyle(entry) === "compact") return false;
98
- const streaming = entry?.streaming;
99
- if (!streaming || typeof streaming !== "object" || Array.isArray(streaming)) return true;
100
- const progressConfig = streaming.progress;
101
- if (!progressConfig || typeof progressConfig !== "object" || Array.isArray(progressConfig)) return true;
102
- return progressConfig.nativeTaskCards !== false;
103
- }
104
- function resolveSlackStreamingThreadHint(params) {
105
- return resolveSlackThreadTs({
106
- replyToMode: params.replyToMode,
107
- incomingThreadTs: params.incomingThreadTs,
108
- messageTs: params.messageTs,
109
- hasReplied: false,
110
- isThreadReply: params.isThreadReply
111
- });
98
+ function resolveSlackNativeProgressTaskCards(entry, style) {
99
+ if (style !== "card") return false;
100
+ return entry?.streaming?.progress?.nativeTaskCards !== false;
112
101
  }
113
102
  const SLACK_STREAM_RECIPIENT_TEAM_CACHE_MAX = 2e3;
114
103
  const slackStreamRecipientTeamCaches = /* @__PURE__ */ new WeakMap();
@@ -123,7 +112,7 @@ function buildSlackEventDeliveryKey(params, preparedReply = prepareSlackReply(pa
123
112
  const reply = resolveSendableOutboundReplyParts(params.payload, { text: params.textOverride });
124
113
  const renderPlan = preparedReply.resolvePreview(params.textOverride);
125
114
  const plannedBlocks = renderPlan.mode === "single" ? renderPlan.blocks : renderPlan.blockPart?.blocks;
126
- const slackBlocks = readSlackReplyBlocks(params.payload) ?? plannedBlocks;
115
+ const slackBlocks = resolveSlackReplyBlocks(params.payload) ?? plannedBlocks;
127
116
  const renderedText = renderPlan.mode === "single" ? renderPlan.text : renderPlan.fallbackText;
128
117
  if (!reply.hasContent && !slackBlocks?.length && !renderedText.trim()) return null;
129
118
  return JSON.stringify({
@@ -135,27 +124,6 @@ function buildSlackEventDeliveryKey(params, preparedReply = prepareSlackReply(pa
135
124
  blocks: slackBlocks ?? null
136
125
  });
137
126
  }
138
- function readSlackStreamRecipientTeamCache(params) {
139
- if (!params.fallbackTeamId || !params.userId) return;
140
- const cacheKey = `${params.fallbackTeamId}:${params.userId}`;
141
- const cache = getSlackStreamRecipientTeamCache(params.client);
142
- const cached = cache.get(cacheKey);
143
- if (!cached) return;
144
- cache.delete(cacheKey);
145
- cache.set(cacheKey, cached);
146
- return cached;
147
- }
148
- function rememberSlackStreamRecipientTeam(params) {
149
- if (!params.fallbackTeamId || !params.userId) return;
150
- const cacheKey = `${params.fallbackTeamId}:${params.userId}`;
151
- const cache = getSlackStreamRecipientTeamCache(params.client);
152
- if (cache.has(cacheKey)) cache.delete(cacheKey);
153
- cache.set(cacheKey, params.teamId);
154
- if (cache.size > SLACK_STREAM_RECIPIENT_TEAM_CACHE_MAX) {
155
- const oldest = cache.keys().next().value;
156
- if (oldest) cache.delete(oldest);
157
- }
158
- }
159
127
  function createSlackEventDeliveryTracker() {
160
128
  const deliveredKeys = /* @__PURE__ */ new Set();
161
129
  return {
@@ -176,7 +144,9 @@ function shouldUseStreaming(params) {
176
144
  return true;
177
145
  }
178
146
  async function resolveSlackStreamRecipientTeamId(params) {
179
- const cachedTeamId = readSlackStreamRecipientTeamCache(params);
147
+ const cacheKey = params.fallbackTeamId && params.userId ? `${params.fallbackTeamId}:${params.userId}` : void 0;
148
+ const cache = cacheKey ? getSlackStreamRecipientTeamCache(params.client) : void 0;
149
+ const cachedTeamId = cache && cacheKey ? readLruMapEntry(cache, cacheKey) : void 0;
180
150
  if (cachedTeamId) return cachedTeamId;
181
151
  if (params.userId) try {
182
152
  const info = await params.client.users.info({
@@ -185,10 +155,7 @@ async function resolveSlackStreamRecipientTeamId(params) {
185
155
  });
186
156
  const teamId = info.user?.team_id ?? info.user?.profile?.team;
187
157
  if (teamId) {
188
- rememberSlackStreamRecipientTeam({
189
- ...params,
190
- teamId
191
- });
158
+ if (cache && cacheKey) writeLruMapEntry(cache, cacheKey, teamId, SLACK_STREAM_RECIPIENT_TEAM_CACHE_MAX);
192
159
  return teamId;
193
160
  }
194
161
  } catch (err) {
@@ -217,6 +184,11 @@ function createSlackDraftStream(params) {
217
184
  final: false
218
185
  };
219
186
  const normalizeUpdate = (update) => typeof update === "string" ? { text: update } : update;
187
+ const clearMessageId = () => {
188
+ streamMessage = void 0;
189
+ lastVisibleUpdate = void 0;
190
+ lastSentKey = "";
191
+ };
220
192
  const sendOrEditStreamMessage = async (pending) => {
221
193
  if (streamState.stopped) return;
222
194
  const update = normalizeUpdate(pending);
@@ -316,11 +288,7 @@ function createSlackDraftStream(params) {
316
288
  emptyValue: "",
317
289
  isEmpty: (value) => !normalizeUpdate(value).text.trim(),
318
290
  readMessageId: () => streamMessage,
319
- clearMessageId: () => {
320
- streamMessage = void 0;
321
- lastVisibleUpdate = void 0;
322
- lastSentKey = "";
323
- },
291
+ clearMessageId,
324
292
  isValidMessageId: (value) => typeof value === "object" && value !== null,
325
293
  deleteMessage: async (message) => {
326
294
  if (message.generation > cleanupGeneration) return false;
@@ -359,9 +327,7 @@ function createSlackDraftStream(params) {
359
327
  await discardPendingAndStopTracking();
360
328
  if (generation === streamGeneration) {
361
329
  clearingMessage = streamMessage;
362
- streamMessage = void 0;
363
- lastVisibleUpdate = void 0;
364
- lastSentKey = "";
330
+ clearMessageId();
365
331
  }
366
332
  }
367
333
  cleanupGeneration = generation;
@@ -384,9 +350,7 @@ function createSlackDraftStream(params) {
384
350
  streamMessage.detachedByHuman = reason === "human";
385
351
  lifecycle.retire(streamMessage, { defer: true });
386
352
  }
387
- streamMessage = void 0;
388
- lastVisibleUpdate = void 0;
389
- lastSentKey = "";
353
+ clearMessageId();
390
354
  loop.resetPending();
391
355
  };
392
356
  const finalizeMessage = async (messageId, editFinal) => {
@@ -487,12 +451,11 @@ const SLACK_PROGRESS_TASK_TITLE_MAX = 120;
487
451
  const SLACK_PROGRESS_PLAN_FALLBACK_TITLE = "Thinking";
488
452
  const SLACK_PROGRESS_LINE_DELTA_RE = /(?:^|\s)\+(\d+)\s+[−-](\d+)(?=\s|$)/u;
489
453
  const SLACK_ATTENTION_TASK_PREFIX = "openclaw-attention-";
490
- function buildSessionSources(url) {
491
- return [{
454
+ function buildSessionSources(links) {
455
+ return links.map((link) => ({
492
456
  type: "url_source",
493
- url,
494
- text: "Open in OpenClaw"
495
- }];
457
+ ...link
458
+ }));
496
459
  }
497
460
  function field(text) {
498
461
  return {
@@ -648,12 +611,13 @@ function buildSlackProgressStreamChunks(params) {
648
611
  });
649
612
  }
650
613
  const headline = params.title?.trim() || params.label?.trim();
614
+ const summaryTitle = params.finalInProgressStatus === "error" ? "Failed" : params.finalInProgressStatus === "complete" || !params.summaryRow ? "Completed" : "Working";
651
615
  const newest = tasks.at(-1);
652
- const title = compactChunkText(headline || (newest?.details ? `${newest.title} — ${newest.details}` : newest?.title) || (params.summaryRow ? "Working" : attention.at(-1)?.title) || SLACK_PROGRESS_PLAN_FALLBACK_TITLE);
616
+ const title = compactChunkText(headline || (newest?.details ? `${newest.title} — ${newest.details}` : newest?.title) || (params.summaryRow ? summaryTitle : attention.at(-1)?.title) || SLACK_PROGRESS_PLAN_FALLBACK_TITLE);
653
617
  const diffOutput = formatTaskDiffOutput(params.diffStat);
654
- if (tasks.length === 0 && (params.summaryRow || params.sessionUrl || diffOutput)) tasks.push({
618
+ if (tasks.length === 0 && (params.summaryRow || params.sessionLinks?.length || diffOutput)) tasks.push({
655
619
  id: "openclaw_summary",
656
- title: params.summaryRow ? compactTitle(title) : "Completed",
620
+ title: params.summaryRow ? compactTitle(title) : summaryTitle,
657
621
  status: params.finalInProgressStatus ?? (params.summaryRow ? "in_progress" : "complete")
658
622
  });
659
623
  tasks.push(...attention);
@@ -675,7 +639,7 @@ function buildSlackProgressStreamChunks(params) {
675
639
  if (task.details) chunk.details = task.details;
676
640
  if (task.output) chunk.output = task.output;
677
641
  if (index === finalTaskIndex && diffOutput) chunk.output = [task.output, diffOutput].filter(Boolean).join(" · ");
678
- if (index === finalTaskIndex && params.sessionUrl) chunk.sources = buildSessionSources(params.sessionUrl);
642
+ if (index === finalTaskIndex && params.sessionLinks?.length) chunk.sources = buildSessionSources(params.sessionLinks);
679
643
  return chunk;
680
644
  });
681
645
  return [{
@@ -727,7 +691,7 @@ function buildSlackProgressCardBlocks(params) {
727
691
  buildActivityText(params.lines.filter((line) => line.kind !== "approval" && lineTaskStatus(line) !== "error"), maxLineChars),
728
692
  joinRecentProgressRows(attention)
729
693
  ];
730
- const title = params.title.trim() || "Working";
694
+ const title = params.title?.trim() || (params.state === "working" ? "Working" : params.state === "success" ? "Done" : "Failed");
731
695
  const blocks = [
732
696
  params.titleFormat === "plain" ? progressTextSection({
733
697
  text: `${icon} ${title}`,
@@ -746,17 +710,17 @@ function buildSlackProgressCardBlocks(params) {
746
710
  type: "context",
747
711
  elements: [field(footer)]
748
712
  });
749
- if (params.state !== "working" && params.sessionUrl) blocks.push({
713
+ if (params.state !== "working" && params.sessionLinks?.length) blocks.push({
750
714
  type: "actions",
751
- elements: [{
715
+ elements: params.sessionLinks.map((link, index) => ({
752
716
  type: "button",
753
- action_id: SLACK_SESSION_LINK_ACTION_ID,
717
+ action_id: index === 0 ? SLACK_SESSION_LINK_ACTION_ID : `${SLACK_SESSION_LINK_ACTION_ID}:${index}`,
754
718
  text: {
755
719
  type: "plain_text",
756
- text: "Open in OpenClaw"
720
+ text: link.text
757
721
  },
758
- url: params.sessionUrl
759
- }]
722
+ url: link.url
723
+ }))
760
724
  });
761
725
  return blocks.slice(0, 50);
762
726
  }
@@ -941,25 +905,20 @@ function blocksMatch(expected, actual) {
941
905
  }
942
906
  }
943
907
  async function readSlackMessageAfterEditError(params) {
944
- if (params.threadTs) return ((await params.client.conversations.replies({
945
- token: params.token,
946
- channel: params.channelId,
947
- ts: params.threadTs,
948
- latest: params.messageId,
949
- oldest: params.messageId,
950
- inclusive: true,
951
- limit: 1
952
- })).messages ?? []).find((message) => message?.ts === params.messageId) ?? null;
953
- const message = (await params.client.conversations.history({
908
+ const query = {
954
909
  token: params.token,
955
910
  channel: params.channelId,
956
911
  latest: params.messageId,
957
912
  oldest: params.messageId,
958
913
  inclusive: true,
959
914
  limit: 1
960
- })).messages?.[0];
961
- if (!message?.ts || message.ts !== params.messageId) return null;
962
- return message;
915
+ };
916
+ const result = params.threadTs ? await params.client.conversations.replies({
917
+ ...query,
918
+ ts: params.threadTs
919
+ }) : await params.client.conversations.history(query);
920
+ const message = params.threadTs ? result.messages?.find((entry) => entry?.ts === params.messageId) : result.messages?.[0];
921
+ return message?.ts && message.ts === params.messageId ? message : null;
963
922
  }
964
923
  async function didSlackPreviewEditApplyAfterError(params) {
965
924
  const readback = await readSlackMessageAfterEditError(params);
@@ -986,15 +945,7 @@ async function finalizeSlackPreviewEdit(params) {
986
945
  });
987
946
  } catch (err) {
988
947
  try {
989
- if (await didSlackPreviewEditApplyAfterError({
990
- client: params.client,
991
- token: params.token,
992
- channelId: params.channelId,
993
- messageId: params.messageId,
994
- text: params.text,
995
- blocks: params.blocks,
996
- threadTs: params.threadTs
997
- })) {
948
+ if (await didSlackPreviewEditApplyAfterError(params)) {
998
949
  logVerbose(`slack: preview final edit response failed but readback matched message ${params.channelId}/${params.messageId}; suppressing duplicate fallback send`);
999
950
  return;
1000
951
  }
@@ -1006,37 +957,39 @@ async function finalizeSlackPreviewEdit(params) {
1006
957
  }
1007
958
  //#endregion
1008
959
  //#region extensions/slack/src/monitor/message-handler/dispatch-progress-card.ts
960
+ const MAX_VISIBLE_WORK_LINKS = 5;
1009
961
  function createSlackDraftProgressCardRuntime(params) {
1010
962
  const { account, cfg, ctx, prepared, slackClient } = params.setup;
1011
- let latestFallbackText = "";
1012
963
  let finalStatus;
1013
- const resolveSessionUrl = () => {
1014
- if (cfg.gateway?.controlUi?.enabled === false) return;
964
+ const visibleWorkSessions = /* @__PURE__ */ new Map();
965
+ const resolveSessionLinks = () => {
966
+ if (visibleWorkSessions.size > 0) return [...visibleWorkSessions.values()].slice(0, MAX_VISIBLE_WORK_LINKS).map((session, index) => {
967
+ const label = session.label?.replace(/\s+/g, " ").trim();
968
+ return {
969
+ url: session.url,
970
+ text: visibleWorkSessions.size === 1 ? "Open work session" : truncateSlackText(label ? `Open ${label}` : `Open work session ${index + 1}`, 75)
971
+ };
972
+ });
973
+ if (cfg.gateway?.controlUi?.enabled === false) return [];
1015
974
  const publicOrigin = resolveGatewayPublicOrigin(cfg);
1016
- if (!publicOrigin) return;
975
+ if (!publicOrigin) return [];
1017
976
  const url = new URL(publicOrigin);
1018
977
  const path = buildControlUiSessionPath({
1019
978
  namespace: "chat",
1020
- sessionKey: prepared.route.sessionKey,
979
+ sessionKey: prepared.ctxPayload.SessionKey ?? prepared.route.sessionKey,
1021
980
  fallbackAgentId: prepared.route.agentId,
981
+ mainKey: cfg.session?.mainKey,
1022
982
  basePath: cfg.gateway?.controlUi?.basePath
1023
983
  });
1024
- if (!path) return;
984
+ if (!path) return [];
1025
985
  url.pathname = path;
1026
- return url.toString();
986
+ return [{
987
+ url: url.toString(),
988
+ text: "Open in OpenClaw"
989
+ }];
1027
990
  };
1028
- const resolveText = (snapshot) => latestFallbackText || formatChannelProgressDraftText({
1029
- entry: account.config,
1030
- lines: [...snapshot.lines],
1031
- seed: params.progressSeed,
1032
- formatLine: formatSlackProgressDraftLine,
1033
- narration: snapshot.statusHeadline,
1034
- narrationFormat: snapshot.statusHeadlineFormat,
1035
- plan: snapshot.plan,
1036
- diffStat: snapshot.diffStat
1037
- });
1038
991
  const resolvePresentation = (snapshot, state) => {
1039
- const title = params.explicitTitle ?? snapshot.statusHeadline ?? "Working";
992
+ const title = params.explicitTitle ?? snapshot.statusHeadline;
1040
993
  const titleFormat = params.explicitTitle ? void 0 : snapshot.statusHeadlineFormat;
1041
994
  const narration = params.explicitTitle ? snapshot.statusHeadlineFormat === "plain" || snapshot.planExplanationFormat === "plain" ? [...snapshot.statusHeadline && (snapshot.statusHeadline !== snapshot.planExplanation || snapshot.statusHeadlineFormat !== snapshot.planExplanationFormat) ? [{
1042
995
  text: snapshot.statusHeadline,
@@ -1049,7 +1002,7 @@ function createSlackDraftProgressCardRuntime(params) {
1049
1002
  format: snapshot.planExplanationFormat
1050
1003
  }] : void 0;
1051
1004
  const workCounter = state === "working" ? params.progressWorkCounter : void 0;
1052
- const sessionUrl = state === "working" ? void 0 : resolveSessionUrl();
1005
+ const sessionLinks = state === "working" ? [] : resolveSessionLinks();
1053
1006
  return buildSlackProgressCardBlocks({
1054
1007
  state,
1055
1008
  title,
@@ -1061,10 +1014,10 @@ function createSlackDraftProgressCardRuntime(params) {
1061
1014
  diffStat: snapshot.diffStat,
1062
1015
  toolCalls: workCounter?.toolCalls,
1063
1016
  elapsedSeconds: workCounter?.elapsedSeconds,
1064
- sessionUrl
1017
+ sessionLinks
1065
1018
  });
1066
1019
  };
1067
- const finalize = async (status, snapshot = params.getSnapshot(), fallbackText = resolveText(snapshot)) => {
1020
+ const finalize = async (status, snapshot = params.getSnapshot()) => {
1068
1021
  if (!params.draftStream || !params.enabled) return false;
1069
1022
  await params.draftStream.dropDetachedMessages();
1070
1023
  const terminalStatus = finalStatus === "error" || status === "error" ? "error" : "success";
@@ -1076,14 +1029,15 @@ function createSlackDraftProgressCardRuntime(params) {
1076
1029
  await params.draftStream.seal();
1077
1030
  try {
1078
1031
  const finalized = await params.draftStream.finalizeMessage(messageId, async () => {
1032
+ const blocks = resolvePresentation(snapshot, terminalStatus);
1079
1033
  await finalizeSlackPreviewEdit({
1080
1034
  client: slackClient,
1081
1035
  token: ctx.botToken,
1082
1036
  accountId: account.accountId,
1083
1037
  channelId,
1084
1038
  messageId,
1085
- text: fallbackText,
1086
- blocks: resolvePresentation(snapshot, terminalStatus),
1039
+ text: buildSlackCompleteBlocksFallbackText(blocks),
1040
+ blocks,
1087
1041
  threadTs: params.getThreadTs()
1088
1042
  });
1089
1043
  });
@@ -1095,19 +1049,18 @@ function createSlackDraftProgressCardRuntime(params) {
1095
1049
  }
1096
1050
  };
1097
1051
  return {
1098
- resolveSessionUrl,
1099
- resolveText,
1052
+ resolveSessionLinks,
1053
+ onVisibleWorkSessions: (sessions) => {
1054
+ for (const session of sessions) if (!visibleWorkSessions.has(session.sessionKey)) visibleWorkSessions.set(session.sessionKey, session);
1055
+ },
1100
1056
  resolvePresentation,
1101
1057
  finalize,
1102
1058
  get hasTerminalized() {
1103
1059
  return finalStatus !== void 0;
1104
1060
  },
1105
- setFallbackText(text) {
1106
- latestFallbackText = text;
1107
- },
1108
1061
  reset() {
1109
- latestFallbackText = "";
1110
1062
  finalStatus = void 0;
1063
+ visibleWorkSessions.clear();
1111
1064
  }
1112
1065
  };
1113
1066
  }
@@ -1123,15 +1076,12 @@ function formatSlackProgressDraftLine(line) {
1123
1076
  //#endregion
1124
1077
  //#region extensions/slack/src/monitor/message-handler/dispatch-progress-native.ts
1125
1078
  function createSlackNativeProgressTransport(params) {
1126
- const { ctx, message, replyPlan, slackClient, slackIdentity, slackStreamFallbackTeamId } = params.setup;
1079
+ const { replyPlan } = params.setup;
1127
1080
  const { delivery } = params;
1128
1081
  const markDelivered = (threadTs) => {
1129
1082
  if (!delivery.streamSession?.delivered) return false;
1130
1083
  delivery.observedReplyDelivery = true;
1131
- if (threadTs) {
1132
- delivery.usedReplyThreadTs ??= threadTs;
1133
- delivery.rememberDeliveredThreadTs("block", threadTs);
1134
- }
1084
+ if (threadTs) delivery.rememberDeliveredThreadTs("block", threadTs);
1135
1085
  return true;
1136
1086
  };
1137
1087
  const waitForStart = async () => {
@@ -1152,30 +1102,15 @@ function createSlackNativeProgressTransport(params) {
1152
1102
  return false;
1153
1103
  }
1154
1104
  delivery.nativeProgressStreamThreadTs = streamThreadTs;
1155
- const startPromise = (async () => {
1156
- const session = await startSlackStream({
1157
- client: slackClient,
1158
- clientOptions: params.setup.slackClientOptions,
1159
- channel: message.channel,
1160
- threadTs: streamThreadTs,
1161
- ...update.text ? { text: update.text } : {},
1162
- ...update.chunks?.length ? { chunks: update.chunks } : {},
1163
- taskDisplayMode: "plan",
1164
- ...slackIdentity ? { identity: slackIdentity } : {},
1165
- teamId: await resolveSlackStreamRecipientTeamId({
1166
- client: slackClient,
1167
- token: ctx.botToken,
1168
- userId: message.user,
1169
- fallbackTeamId: slackStreamFallbackTeamId
1170
- }),
1171
- userId: message.user
1172
- });
1173
- delivery.streamSession = session;
1174
- return session;
1175
- })();
1105
+ const startPromise = delivery.startStream({
1106
+ threadTs: streamThreadTs,
1107
+ ...update.text ? { text: update.text } : {},
1108
+ ...update.chunks?.length ? { chunks: update.chunks } : {},
1109
+ taskDisplayMode: "plan"
1110
+ });
1176
1111
  delivery.nativeProgressStreamStartPromise = startPromise;
1177
1112
  try {
1178
- if (!await startPromise) return false;
1113
+ await startPromise;
1179
1114
  const delivered = markDelivered(streamThreadTs);
1180
1115
  return update.chunks?.length ? delivered : true;
1181
1116
  } finally {
@@ -1203,7 +1138,7 @@ function createSlackNativeProgressTransport(params) {
1203
1138
  //#region extensions/slack/src/monitor/message-handler/dispatch-progress.ts
1204
1139
  function createSlackProgressRuntime(runtimeParams) {
1205
1140
  const { setup, delivery } = runtimeParams;
1206
- const { account, cfg, ctx, hasSlackCustomIdentity, message, prepared, replyPlan, runtime, slackClient, slackIdentity, slackMessageMetadata, slackStreaming, shouldUseDraftStream, useStreaming, previewStreamingEnabled } = setup;
1141
+ const { account, cfg, ctx, hasSlackCustomIdentity, message, prepared, replyPlan, runtime, slackClient, slackIdentity, slackMessageMetadata, slackStreaming, slackProgressStyle, quietProgress, shouldUseDraftStream, useStreaming, previewStreamingEnabled } = setup;
1207
1142
  const draftStream = shouldUseDraftStream ? createSlackDraftStream({
1208
1143
  target: prepared.replyTarget,
1209
1144
  cfg,
@@ -1227,7 +1162,7 @@ function createSlackProgressRuntime(runtimeParams) {
1227
1162
  const progressDraftActive = Boolean(draftStream) || useNativeProgressStreaming;
1228
1163
  const previewToolProgressEnabled = progressDraftActive && resolveChannelStreamingPreviewToolProgress(account.config, slackStreaming.mode !== "progress", slackStreaming.mode);
1229
1164
  let shouldYieldDraftProgress = () => false;
1230
- const suppressDefaultToolProgressMessages = resolveChannelStreamingSuppressDefaultToolProgressMessages(account.config, {
1165
+ const suppressDefaultToolProgressMessages = quietProgress || resolveChannelStreamingSuppressDefaultToolProgressMessages(account.config, {
1231
1166
  draftStreamActive: Boolean(draftStream) || useNativeProgressStreaming,
1232
1167
  mode: slackStreaming.mode,
1233
1168
  previewToolProgressEnabled,
@@ -1248,7 +1183,6 @@ function createSlackProgressRuntime(runtimeParams) {
1248
1183
  };
1249
1184
  const progressWorkCounter = createChannelProgressWorkCounter();
1250
1185
  const progressSeed = `${account.accountId}:${message.channel}`;
1251
- const slackProgressStyle = resolveSlackProgressStyle(account.config);
1252
1186
  const preambleOnlyProgress = isProgressMode && slackProgressStyle === "compact" && !previewToolProgressEnabled;
1253
1187
  const useDraftProgressCard = Boolean(draftStream) && isProgressMode && slackProgressStyle === "card";
1254
1188
  const explicitProgressTitle = resolveExplicitSlackProgressTitle(account.config);
@@ -1264,7 +1198,6 @@ function createSlackProgressRuntime(runtimeParams) {
1264
1198
  draftStream,
1265
1199
  enabled: useDraftProgressCard,
1266
1200
  progressWorkCounter: previewToolProgressEnabled ? progressWorkCounter : void 0,
1267
- progressSeed,
1268
1201
  explicitTitle: explicitProgressTitle,
1269
1202
  maxLineChars: progressDraftMaxLineChars,
1270
1203
  getSnapshot: () => progressDraft.getSnapshot(),
@@ -1373,8 +1306,7 @@ function createSlackProgressRuntime(runtimeParams) {
1373
1306
  nativeUpdates.stop();
1374
1307
  await nativeUpdates.waitForInFlight();
1375
1308
  };
1376
- const appendNativeNarration = (payload, kind) => withNativeStreamOrder(() => appendNativeNarrationNow(payload, kind));
1377
- const appendNativeNarrationNow = async (payload, kind) => {
1309
+ const appendNativeNarration = (payload, kind) => withNativeStreamOrder(async () => {
1378
1310
  if (isRenderedAsProgressTitle(payload.text)) return { visibleReplySent: false };
1379
1311
  const narrationUpdate = resolveNarrationUpdate(payload.text?.trimEnd());
1380
1312
  if (!narrationUpdate.delta) return { visibleReplySent: false };
@@ -1390,7 +1322,7 @@ function createSlackProgressRuntime(runtimeParams) {
1390
1322
  nativeNarrationSourceText = narrationUpdate.next.source;
1391
1323
  }
1392
1324
  return result;
1393
- };
1325
+ });
1394
1326
  const resetProgressTurnState = () => {
1395
1327
  progressWorkCounter.reset();
1396
1328
  nativeNarrationRenderedText = "";
@@ -1419,7 +1351,6 @@ function createSlackProgressRuntime(runtimeParams) {
1419
1351
  const snapshot = options.snapshot;
1420
1352
  const latestLine = snapshot.lines.at(-1);
1421
1353
  if (preambleOnlyProgress && typeof latestLine === "object" && latestLine.complete === false) return false;
1422
- progressCard.setFallbackText(previewText);
1423
1354
  draftStream.update(preambleOnlyProgress ? {
1424
1355
  text: previewText,
1425
1356
  allowNewMessage: typeof latestLine !== "object" || latestLine.complete !== false,
@@ -1492,22 +1423,22 @@ function createSlackProgressRuntime(runtimeParams) {
1492
1423
  const buildNativeProgressCompletionChunks = (finalInProgressStatus) => {
1493
1424
  const snapshot = progressDraft.getSnapshot();
1494
1425
  const lines = resolveNativeProgressLines(snapshot);
1495
- const sessionUrl = progressCard.resolveSessionUrl();
1426
+ const sessionLinks = progressCard.resolveSessionLinks();
1496
1427
  const narrationUpdate = resolveNarrationUpdate(resolveNativeProgressNarration(snapshot));
1497
1428
  const hasRetirableNativeTasks = [...nativeStreamSnapshot.tasks.values()].some((task) => task.status !== "complete" && task.status !== "error");
1498
- if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks && !snapshot.diffStat && !narrationUpdate.delta && !sessionUrl) return;
1429
+ if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks && !snapshot.diffStat && !narrationUpdate.delta && sessionLinks.length === 0) return;
1499
1430
  const completion = reconcileSlackNativeTaskChunks({
1500
1431
  previous: nativeStreamSnapshot,
1501
1432
  finalStatus: finalInProgressStatus,
1502
1433
  chunks: buildSlackProgressStreamChunks({
1503
- title: resolveNativeProgressTitle(snapshot) ?? (lines.length === 0 && !snapshot.plan?.length ? "Working" : void 0),
1434
+ title: resolveNativeProgressTitle(snapshot),
1504
1435
  lines,
1505
1436
  plan: snapshot.plan,
1506
1437
  maxLineChars: progressDraftMaxLineChars,
1507
1438
  summaryRow: !previewToolProgressEnabled,
1508
1439
  finalInProgressStatus,
1509
1440
  diffStat: snapshot.diffStat,
1510
- sessionUrl
1441
+ sessionLinks
1511
1442
  })
1512
1443
  }).chunks;
1513
1444
  return narrationUpdate.delta ? [{
@@ -1578,12 +1509,11 @@ function createSlackProgressRuntime(runtimeParams) {
1578
1509
  await cancelNativeUpdates();
1579
1510
  }
1580
1511
  const priorSnapshot = progressDraft.getSnapshot();
1581
- const priorFallbackText = progressCard.resolveText(priorSnapshot);
1582
1512
  const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent ? buildNativeProgressCompletionChunks(nativeProgressTerminalStatus) : void 0;
1583
1513
  if (!progressDraft.beginNewTurn(options)) return false;
1584
1514
  if (useNativeProgressStreaming) await finishNativeProgressTurn(completionChunks);
1585
1515
  else {
1586
- await progressCard.finalize("success", priorSnapshot, priorFallbackText);
1516
+ await progressCard.finalize("success", priorSnapshot);
1587
1517
  await previewLifecycle.cleanup();
1588
1518
  draftStream?.forceNewMessage();
1589
1519
  await dropDetachedProgressCards();
@@ -1666,6 +1596,7 @@ function createSlackProgressRuntime(runtimeParams) {
1666
1596
  deliverNativeFinal,
1667
1597
  dropDetachedProgressCards,
1668
1598
  finalizeDraftProgressCard: progressCard.finalize,
1599
+ onVisibleWorkSessions: progressCard.onVisibleWorkSessions,
1669
1600
  onDraftBoundary,
1670
1601
  onQueuedFollowupAdmitted,
1671
1602
  onQueuedFollowupSettled,
@@ -1722,14 +1653,14 @@ async function createSlackDispatchSetup(prepared) {
1722
1653
  ctx: prepared.ctxPayload
1723
1654
  });
1724
1655
  }
1725
- const threadTargets = resolveSlackThreadTargets({
1656
+ const threadContext = resolveSlackThreadContext({
1726
1657
  message,
1727
1658
  replyToMode: prepared.replyToMode
1728
1659
  });
1729
1660
  const forcedReplyThreadTs = prepared.forcedReplyThreadTs;
1730
1661
  const slackMessageMetadata = prepared.slackMessageMetadata;
1731
- const statusThreadTs = forcedReplyThreadTs ?? threadTargets.statusThreadTs;
1732
- const isThreadReply = threadTargets.isThreadReply;
1662
+ const statusThreadTs = forcedReplyThreadTs ?? threadContext.messageThreadId;
1663
+ const isThreadReply = threadContext.isThreadReply;
1733
1664
  const replyDeliveryMode = forcedReplyThreadTs ? "off" : prepared.replyToMode;
1734
1665
  const sourceReplyDeliveryMode = resolveChannelMessageSourceReplyDeliveryMode({
1735
1666
  cfg,
@@ -1790,8 +1721,12 @@ async function createSlackDispatchSetup(prepared) {
1790
1721
  hasRepliedRef,
1791
1722
  isThreadReply: Boolean(forcedReplyThreadTs) || isThreadReply
1792
1723
  });
1724
+ const slackStreaming = resolveSlackStreamingConfig({ streaming: account.config.streaming });
1725
+ const streamThreadHint = forcedReplyThreadTs ?? replyPlan.peekThreadTs();
1726
+ const slackProgressStyle = resolveSlackProgressStyle(account.config, Boolean(streamThreadHint));
1727
+ const quietProgress = slackStreaming.mode === "progress" && slackProgressStyle === "none";
1793
1728
  const typingTarget = statusThreadTs ? `${message.channel}/${statusThreadTs}` : message.channel;
1794
- const typingReaction = ctx.typingReaction;
1729
+ const typingReaction = quietProgress && account.config.typingReaction === void 0 ? "hourglass_flowing_sand" : ctx.typingReaction;
1795
1730
  const threadStatusGate = { hasVisibleOutput: () => false };
1796
1731
  const { onModelSelected, ...replyPipeline } = createChannelMessageReplyPipeline({
1797
1732
  cfg,
@@ -1866,23 +1801,16 @@ async function createSlackDispatchSetup(prepared) {
1866
1801
  }
1867
1802
  }
1868
1803
  });
1869
- const slackStreaming = resolveSlackStreamingConfig({ streaming: account.config.streaming });
1870
- const streamThreadHint = forcedReplyThreadTs ?? resolveSlackStreamingThreadHint({
1871
- replyToMode: replyDeliveryMode,
1872
- incomingThreadTs,
1873
- messageTs,
1874
- isThreadReply
1875
- });
1876
1804
  const hookRunner = getGlobalHookRunner();
1877
1805
  const modifyingHooksRegistered = (hookRunner?.hasHooks("reply_payload_sending") ?? false) || (hookRunner?.hasHooks("message_sending") ?? false);
1878
1806
  const allowPreHookProviderStreaming = !prepared.ctxPayload.GroupThread && !modifyingHooksRegistered;
1879
- const previewStreamingEnabled = allowPreHookProviderStreaming && !sourceRepliesAreToolOnly && slackStreaming.mode !== "off";
1807
+ const previewStreamingEnabled = allowPreHookProviderStreaming && !sourceRepliesAreToolOnly && !quietProgress && slackStreaming.mode !== "off";
1880
1808
  const hasSlackCustomIdentity = Boolean(slackIdentity?.username || slackIdentity?.iconUrl || slackIdentity?.iconEmoji);
1881
1809
  const useStreaming = shouldUseStreaming({
1882
1810
  streamingEnabled: !prepared.ctxPayload.GroupThread && !sourceRepliesAreToolOnly && (allowPreHookProviderStreaming || slackStreaming.mode !== "progress") && isSlackStreamingEnabled({
1883
1811
  mode: slackStreaming.mode,
1884
1812
  nativeStreaming: slackStreaming.nativeStreaming,
1885
- nativeProgressTaskCards: resolveSlackNativeProgressTaskCards(account.config)
1813
+ nativeProgressTaskCards: resolveSlackNativeProgressTaskCards(account.config, slackProgressStyle)
1886
1814
  }),
1887
1815
  threadTs: streamThreadHint
1888
1816
  });
@@ -1906,13 +1834,10 @@ async function createSlackDispatchSetup(prepared) {
1906
1834
  isThreadReply,
1907
1835
  replyDeliveryMode,
1908
1836
  sourceReplyDeliveryMode,
1909
- sourceRepliesAreToolOnly,
1910
1837
  suppressRoomEventTyping,
1911
1838
  messageSentHookTarget,
1912
1839
  messageSentHookContext,
1913
1840
  messageSentDeliveryHookContext,
1914
- incomingThreadTs,
1915
- messageTs,
1916
1841
  statusReactionsEnabled,
1917
1842
  statusReactions,
1918
1843
  hasRepliedRef,
@@ -1921,11 +1846,13 @@ async function createSlackDispatchSetup(prepared) {
1921
1846
  onModelSelected,
1922
1847
  replyPipeline,
1923
1848
  slackStreaming,
1849
+ slackProgressStyle,
1850
+ quietProgress,
1924
1851
  streamThreadHint,
1925
1852
  previewStreamingEnabled,
1926
1853
  hasSlackCustomIdentity,
1927
1854
  shouldUseDraftStream,
1928
- disableBlockStreaming: sourceRepliesAreToolOnly ? true : resolveSlackDisableBlockStreaming({
1855
+ disableBlockStreaming: sourceRepliesAreToolOnly || quietProgress ? true : resolveSlackDisableBlockStreaming({
1929
1856
  useStreaming,
1930
1857
  shouldUseDraftStream,
1931
1858
  blockStreamingEnabled
@@ -1946,6 +1873,41 @@ function createSlackStreamingDeliveryRuntime(setup) {
1946
1873
  usedBlockReplyThreadTs: void 0,
1947
1874
  observedReplyDelivery: false
1948
1875
  };
1876
+ const startStream = async (params) => {
1877
+ const session = await startSlackStream({
1878
+ client: slackClient,
1879
+ clientOptions: slackClientOptions,
1880
+ channel: message.channel,
1881
+ ...params,
1882
+ ...slackIdentity ? { identity: slackIdentity } : {},
1883
+ teamId: await resolveSlackStreamRecipientTeamId({
1884
+ client: slackClient,
1885
+ token: ctx.botToken,
1886
+ userId: message.user,
1887
+ fallbackTeamId: slackStreamFallbackTeamId
1888
+ }),
1889
+ userId: message.user
1890
+ });
1891
+ state.streamSession = session;
1892
+ return session;
1893
+ };
1894
+ const deliverPreparedReply = (reply, replyThreadTs, deferMessageSentHooks = false) => deliverReplies({
1895
+ cfg: ctx.cfg,
1896
+ replies: [reply],
1897
+ target: prepared.replyTarget,
1898
+ token: ctx.botToken,
1899
+ accountId: account.accountId,
1900
+ runtime,
1901
+ textLimit: ctx.textLimit,
1902
+ mediaMaxBytes: ctx.mediaMaxBytes,
1903
+ replyThreadTs,
1904
+ replyToMode: replyDeliveryMode,
1905
+ ...slackIdentity ? { identity: slackIdentity } : {},
1906
+ ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {},
1907
+ ...messageSentDeliveryHookContext,
1908
+ ...deferMessageSentHooks ? { deferMessageSentHooks: true } : {},
1909
+ eventScope: prepared.eventScope
1910
+ });
1949
1911
  const emitStreamedDelivery = (content, result) => {
1950
1912
  emitSlackMessageSentHooks({
1951
1913
  ...messageSentHookContext,
@@ -1996,23 +1958,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
1996
1958
  }
1997
1959
  const fallbackText = fallbackError.pendingText.trim();
1998
1960
  if (!fallbackText) return;
1999
- const sent = await deliverReplies({
2000
- cfg: ctx.cfg,
2001
- replies: [prepareSlackReply({ text: fallbackText })],
2002
- target: prepared.replyTarget,
2003
- token: ctx.botToken,
2004
- accountId: account.accountId,
2005
- runtime,
2006
- textLimit: ctx.textLimit,
2007
- mediaMaxBytes: ctx.mediaMaxBytes,
2008
- replyThreadTs: session.threadTs,
2009
- replyToMode: replyDeliveryMode,
2010
- ...slackIdentity ? { identity: slackIdentity } : {},
2011
- ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {},
2012
- ...messageSentDeliveryHookContext,
2013
- deferMessageSentHooks: true,
2014
- eventScope: prepared.eventScope
2015
- });
1961
+ const sent = await deliverPreparedReply(prepareSlackReply({ text: fallbackText }), session.threadTs, true);
2016
1962
  if (!sent?.receipt.platformMessageIds.length) return;
2017
1963
  markSlackStreamFallbackDelivered(session);
2018
1964
  if (!session.stopped) try {
@@ -2066,22 +2012,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
2066
2012
  logVerbose("slack: suppressed duplicate normal delivery within the same turn");
2067
2013
  return { visibleReplySent: false };
2068
2014
  }
2069
- const sent = await deliverReplies({
2070
- cfg: ctx.cfg,
2071
- replies: [preparedReply],
2072
- target: prepared.replyTarget,
2073
- token: ctx.botToken,
2074
- accountId: account.accountId,
2075
- runtime,
2076
- textLimit: ctx.textLimit,
2077
- mediaMaxBytes: ctx.mediaMaxBytes,
2078
- replyThreadTs: deliveryReplyThreadTs,
2079
- replyToMode: replyDeliveryMode,
2080
- ...slackIdentity ? { identity: slackIdentity } : {},
2081
- ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {},
2082
- ...messageSentDeliveryHookContext,
2083
- eventScope: prepared.eventScope
2084
- });
2015
+ const sent = await deliverPreparedReply(preparedReply, deliveryReplyThreadTs);
2085
2016
  if (!sent?.receipt.platformMessageIds.length) return { visibleReplySent: false };
2086
2017
  state.observedReplyDelivery = true;
2087
2018
  const deliveredThreadTs = resolveSlackReplyThreadTs({
@@ -2104,7 +2035,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
2104
2035
  const reply = resolveSendableOutboundReplyParts(payload);
2105
2036
  const renderPlan = resolveSlackReplyRenderPlan(payload);
2106
2037
  const plannedBlocks = renderPlan.mode === "single" ? renderPlan.blocks : renderPlan.blockPart?.blocks;
2107
- return !state.streamFailed && !reply.hasMedia && renderPlan.mode !== "split" && !renderPlan.textIsSlackPlainText && !plannedBlocks?.length && !readSlackReplyBlocks(payload)?.length && reply.hasText && (!options?.maxTextBytes || countSlackTextUtf8Bytes(reply.trimmedText) <= options.maxTextBytes);
2038
+ return !state.streamFailed && !reply.hasMedia && renderPlan.mode !== "split" && !renderPlan.textIsSlackPlainText && !plannedBlocks?.length && !resolveSlackReplyBlocks(payload)?.length && reply.hasText && (!options?.maxTextBytes || countSlackTextUtf8Bytes(reply.trimmedText) <= options.maxTextBytes);
2108
2039
  };
2109
2040
  const deliverWithStreaming = async (params) => {
2110
2041
  if (state.streamSession?.stoppedBySlack) return { visibleReplySent: false };
@@ -2144,26 +2075,12 @@ function createSlackStreamingDeliveryRuntime(setup) {
2144
2075
  text: `${params.appendSeparator === false ? "" : "\n"}${text}`,
2145
2076
  chunks: []
2146
2077
  });
2147
- else {
2148
- session = await startSlackStream({
2149
- client: slackClient,
2150
- clientOptions: slackClientOptions,
2151
- channel: message.channel,
2152
- threadTs,
2153
- text,
2154
- chunks: [],
2155
- ...params.taskDisplayMode ? { taskDisplayMode: params.taskDisplayMode } : {},
2156
- ...slackIdentity ? { identity: slackIdentity } : {},
2157
- teamId: await resolveSlackStreamRecipientTeamId({
2158
- client: slackClient,
2159
- token: ctx.botToken,
2160
- userId: message.user,
2161
- fallbackTeamId: slackStreamFallbackTeamId
2162
- }),
2163
- userId: message.user
2164
- });
2165
- state.streamSession = session;
2166
- }
2078
+ else session = await startStream({
2079
+ threadTs,
2080
+ text,
2081
+ chunks: [],
2082
+ ...params.taskDisplayMode ? { taskDisplayMode: params.taskDisplayMode } : {}
2083
+ });
2167
2084
  messageId = session.streamer.ts;
2168
2085
  } catch (error) {
2169
2086
  state.streamFailed = true;
@@ -2221,6 +2138,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
2221
2138
  isStreamingEligible,
2222
2139
  markPreviewPayloadDelivered,
2223
2140
  rememberDeliveredThreadTs,
2141
+ startStream,
2224
2142
  resetDeliveryTracker: () => {
2225
2143
  deliveryTracker = createSlackEventDeliveryTracker();
2226
2144
  }
@@ -2324,14 +2242,7 @@ async function dispatchSlackMessageWithSetup(setup, beginSessionRun, turnAdoptio
2324
2242
  })).deliveryResult ?? { visibleReplySent: false };
2325
2243
  }
2326
2244
  if (progress.useNativeProgressStreaming) {
2327
- if (info.kind !== "final" && payload.isError !== true) {
2328
- if (!delivery.isStreamingEligible(payload)) return await delivery.deliverNormally({
2329
- payload,
2330
- kind: info.kind,
2331
- forcedThreadTs: delivery.streamSession?.threadTs ?? delivery.nativeProgressStreamThreadTs
2332
- });
2333
- return await progress.appendNativeNarration(payload, info.kind);
2334
- }
2245
+ if (info.kind !== "final" && payload.isError !== true && delivery.isStreamingEligible(payload)) return await progress.appendNativeNarration(payload, info.kind);
2335
2246
  return await delivery.deliverNormally({
2336
2247
  payload,
2337
2248
  kind: info.kind,
@@ -2482,6 +2393,7 @@ async function dispatchSlackMessageWithSetup(setup, beginSessionRun, turnAdoptio
2482
2393
  record: prepared.turn.record,
2483
2394
  botLoopProtection: resolveSlackBotLoopProtection(prepared),
2484
2395
  replyOptions: {
2396
+ onVisibleWorkSessions: progress.onVisibleWorkSessions,
2485
2397
  groupThreadReplyFormatter: formatSlackGroupThreadReply,
2486
2398
  queuedDeliveryCorrelations: [{ begin: beginSessionRun }],
2487
2399
  ...turnAdoptionLifecycle ? { turnAdoptionLifecycle } : {},
@@ -2501,9 +2413,7 @@ async function dispatchSlackMessageWithSetup(setup, beginSessionRun, turnAdoptio
2501
2413
  } : void 0,
2502
2414
  allowProgressCallbacksWhenSourceDeliverySuppressed: sourceReplyDeliveryMode === "message_tool_only" && statusReactionsEnabled ? true : void 0,
2503
2415
  allowToolLifecycleWhenProgressHidden: statusReactionsEnabled ? true : void 0,
2504
- onPartialReply: useStreaming ? void 0 : !previewStreamingEnabled ? void 0 : async (payload) => {
2505
- return progress.updateDraftFromPartial(payload.text);
2506
- },
2416
+ onPartialReply: !useStreaming && previewStreamingEnabled ? async (payload) => progress.updateDraftFromPartial(payload.text) : void 0,
2507
2417
  onAssistantMessageStart: progress.onDraftBoundary ? async () => {
2508
2418
  await progress.onDraftBoundary?.();
2509
2419
  return false;
@@ -2586,7 +2496,7 @@ async function dispatchSlackMessageWithSetup(setup, beginSessionRun, turnAdoptio
2586
2496
  }
2587
2497
  if (shouldLogVerbose()) {
2588
2498
  const finalCount = resolveInboundReplyDispatchCounts(settledDispatchResult).final;
2589
- logVerbose(`slack: delivered ${finalCount} reply${finalCount === 1 ? "" : "ies"} to ${prepared.replyTarget}`);
2499
+ logVerbose(`slack: delivered ${finalCount} repl${finalCount === 1 ? "y" : "ies"} to ${prepared.replyTarget}`);
2590
2500
  }
2591
2501
  }
2592
2502
  //#endregion
@@ -2646,12 +2556,9 @@ function formatSlackFilePlaceholder(files) {
2646
2556
  return `[attached: ${formatSlackFileReferenceList(files)}]`;
2647
2557
  }
2648
2558
  function pushUniqueText(parts, value, options = {}) {
2649
- const text = options.preserveWhitespace ? typeof value === "string" && value.trim().length > 0 ? value : void 0 : normalizeOptionalString(value);
2559
+ const text = options.preserveWhitespace ? readNonBlankString(value) : normalizeOptionalString(value);
2650
2560
  if (text && !parts.includes(text)) parts.push(text);
2651
2561
  }
2652
- function resolveSlackBlocksFallbackText(blocks) {
2653
- return resolveSlackBlocksText(blocks)?.text;
2654
- }
2655
2562
  function resolveSlackAttachmentFallbackText(attachments) {
2656
2563
  if (!Array.isArray(attachments) || attachments.length === 0) return;
2657
2564
  const parts = [];
@@ -2666,8 +2573,8 @@ function resolveSlackAttachmentFallbackText(attachments) {
2666
2573
  pushUniqueText(parts, field.title);
2667
2574
  pushUniqueText(parts, field.value);
2668
2575
  }
2669
- pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.blocks)), { preserveWhitespace: true });
2670
- pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.message_blocks)), { preserveWhitespace: true });
2576
+ pushUniqueText(parts, resolveSlackBlocksText(fallbackBlocks(attachment.blocks))?.text, { preserveWhitespace: true });
2577
+ pushUniqueText(parts, resolveSlackBlocksText(fallbackBlocks(attachment.message_blocks))?.text, { preserveWhitespace: true });
2671
2578
  }
2672
2579
  return parts.length > 0 ? parts.join("\n") : void 0;
2673
2580
  }
@@ -2721,7 +2628,7 @@ async function resolveSlackThreadStarter(params) {
2721
2628
  }
2722
2629
  return starter;
2723
2630
  } catch (err) {
2724
- logVerbose$1(`slack thread starter fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
2631
+ logVerbose(`slack thread starter fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
2725
2632
  return null;
2726
2633
  }
2727
2634
  }
@@ -2771,7 +2678,7 @@ async function resolveSlackThreadHistory(params) {
2771
2678
  }
2772
2679
  } while (cursor && pagesFetched < SLACK_THREAD_HISTORY_MAX_PAGES);
2773
2680
  if (cursor) {
2774
- logVerbose$1(`slack thread history capped channel=${params.channelId} ts=${params.threadTs} pages=${SLACK_THREAD_HISTORY_MAX_PAGES}`);
2681
+ logVerbose(`slack thread history capped channel=${params.channelId} ts=${params.threadTs} pages=${SLACK_THREAD_HISTORY_MAX_PAGES}`);
2775
2682
  params.onOmission?.("Slack thread exceeds the three-page automatic history budget");
2776
2683
  return [];
2777
2684
  }
@@ -2786,7 +2693,7 @@ async function resolveSlackThreadHistory(params) {
2786
2693
  } catch (err) {
2787
2694
  params.assertCurrent?.();
2788
2695
  params.onOmission?.(formatErrorMessage(err));
2789
- logVerbose$1(`slack thread history fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
2696
+ logVerbose(`slack thread history fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
2790
2697
  return [];
2791
2698
  }
2792
2699
  }
@@ -2869,9 +2776,7 @@ async function resolveSlackPreflightAudioTranscript(params) {
2869
2776
  mediaIndex
2870
2777
  } : null;
2871
2778
  }
2872
- async function sendSlackPreflightAudioTranscriptEcho(params) {
2873
- await slackPreflightAudio.send(params);
2874
- }
2779
+ const sendSlackPreflightAudioTranscriptEcho = slackPreflightAudio.send.bind(slackPreflightAudio);
2875
2780
  async function discardSlackPreflightMedia(media) {
2876
2781
  await Promise.allSettled((media ?? []).map((entry) => fs.rm(entry.path, { force: true })));
2877
2782
  }
@@ -2881,7 +2786,7 @@ const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
2881
2786
  const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
2882
2787
  const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
2883
2788
  const MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS = 2e3;
2884
- const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-DKCtBgCI.mjs").then((n) => n._));
2789
+ const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-Df0CzcDl.mjs").then((n) => n._));
2885
2790
  function formatSlackUnavailableMedia(params) {
2886
2791
  let fileReferences = params.files?.map((file) => `${formatSlackFileReference(file)} unavailable (${file.reason})`).join(", ");
2887
2792
  if (fileReferences && fileReferences.length > MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS) fileReferences = `${truncateUtf16Safe(fileReferences, MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS)}; … (file references truncated)`;
@@ -2900,18 +2805,15 @@ function formatSlackUnavailableMedia(params) {
2900
2805
  }
2901
2806
  function collectUniqueSlackMentionIds$1(texts) {
2902
2807
  const seen = /* @__PURE__ */ new Set();
2903
- const mentionIds = [];
2904
2808
  for (const text of texts) {
2905
2809
  if (!text) continue;
2906
2810
  SLACK_USER_MENTION_RE$1.lastIndex = 0;
2907
2811
  for (const match of text.matchAll(SLACK_USER_MENTION_RE$1)) {
2908
2812
  const userId = match[1];
2909
- if (!userId || seen.has(userId)) continue;
2910
- seen.add(userId);
2911
- mentionIds.push(userId);
2813
+ if (userId) seen.add(userId);
2912
2814
  }
2913
2815
  }
2914
- return mentionIds;
2816
+ return [...seen];
2915
2817
  }
2916
2818
  function renderSlackUserMentions(text, renderedMentions) {
2917
2819
  if (!text || renderedMentions.size === 0) return text;
@@ -2922,8 +2824,7 @@ function renderSlackUserMentions(text, renderedMentions) {
2922
2824
  }
2923
2825
  function filterInheritedParentFiles(params) {
2924
2826
  const { files, isThreadReply, threadStarter } = params;
2925
- if (!isThreadReply || !files?.length) return files;
2926
- if (!threadStarter?.files?.length) return files;
2827
+ if (!isThreadReply || !files?.length || !threadStarter?.files?.length) return files;
2927
2828
  const starterFileIds = new Set(threadStarter.files.map((file) => file.id));
2928
2829
  const filtered = files.filter((file) => !file.id || !starterFileIds.has(file.id));
2929
2830
  if (filtered.length < files.length) logVerbose(`slack: filtered ${files.length - filtered.length} inherited parent file(s) from thread reply`);
@@ -2950,14 +2851,7 @@ async function resolveSlackMessageContent(params) {
2950
2851
  const effectiveDirectMedia = attachmentContent?.media.length ? attachmentContent.media : null;
2951
2852
  const mediaPlaceholder = effectiveDirectMedia?.map((item) => item.placeholder).join(" ");
2952
2853
  let botAttachmentText;
2953
- if (params.isBotMessage && !attachmentContent?.text) {
2954
- const botAttachmentTextParts = [];
2955
- for (const attachment of params.message.attachments ?? []) {
2956
- const text = normalizeOptionalString(attachment.text) ?? normalizeOptionalString(attachment.fallback);
2957
- if (text) botAttachmentTextParts.push(text);
2958
- }
2959
- botAttachmentText = botAttachmentTextParts.length > 0 ? botAttachmentTextParts.join("\n") : void 0;
2960
- }
2854
+ if (params.isBotMessage && !attachmentContent?.text) botAttachmentText = (params.message.attachments ?? []).map((attachment) => normalizeOptionalString(attachment.text) ?? normalizeOptionalString(attachment.fallback)).filter(Boolean).join("\n") || void 0;
2961
2855
  const textParts = [
2962
2856
  resolveSlackMessageText$1(params.message),
2963
2857
  attachmentContent?.text,
@@ -2986,17 +2880,9 @@ async function resolveSlackMessageContent(params) {
2986
2880
  renderedMentions.set(result.userId, result.rendered);
2987
2881
  }
2988
2882
  }
2989
- const renderedMessageText = renderSlackUserMentions(textParts[0], renderedMentions);
2990
- const renderedAttachmentText = renderSlackUserMentions(textParts[1], renderedMentions);
2991
- const renderedBotAttachmentText = renderSlackUserMentions(textParts[2], renderedMentions);
2992
2883
  const commandSourceText = renderSlackUserMentions(normalizeOptionalString(params.message.text), renderedMentions) ?? "";
2993
2884
  const rawBody = formatSlackUnavailableMedia({
2994
- body: [
2995
- renderedMessageText,
2996
- renderedAttachmentText,
2997
- renderedBotAttachmentText,
2998
- mediaPlaceholder
2999
- ].filter(Boolean).join("\n") || "",
2885
+ body: [...textParts.map((text) => renderSlackUserMentions(text, renderedMentions)), mediaPlaceholder].filter(Boolean).join("\n"),
3000
2886
  files: attachmentContent?.files,
3001
2887
  unavailableMediaCount: attachmentContent?.unavailableMediaCount ?? 0
3002
2888
  });
@@ -3011,7 +2897,7 @@ async function resolveSlackMessageContent(params) {
3011
2897
  //#endregion
3012
2898
  //#region extensions/slack/src/monitor/message-handler/prepare-dm-history.ts
3013
2899
  function resolveSlackDmHistoryLimit(params) {
3014
- const override = params.userId && params.account.config.dms?.[params.userId]?.historyLimit !== void 0 ? params.account.config.dms[params.userId]?.historyLimit : void 0;
2900
+ const override = params.userId ? params.account.config.dms?.[params.userId]?.historyLimit : void 0;
3015
2901
  return resolvePromptHistoryLimit(override ?? params.defaultLimit, 0);
3016
2902
  }
3017
2903
  async function resolveSlackDmHistoryContext(params) {
@@ -3088,52 +2974,6 @@ function isSlackThreadAuthorCurrentBot(params) {
3088
2974
  if (identity.botId && author.botId && author.botId === identity.botId) return true;
3089
2975
  return false;
3090
2976
  }
3091
- function resolveSlackThreadHistoryFilterPolicy(params) {
3092
- if (params.retainCurrentBotHistory) return { currentBot: "all" };
3093
- if (!params.includeBotStarterAsRootContext || !params.starterTs) return { currentBot: "omit" };
3094
- return {
3095
- currentBot: "root-only",
3096
- rootTs: params.starterTs
3097
- };
3098
- }
3099
- function applySlackThreadHistoryFilterPolicy(params) {
3100
- const kept = [];
3101
- let omittedCurrentBot = 0;
3102
- for (const entry of params.history) {
3103
- if (!isSlackThreadAuthorCurrentBot({
3104
- identity: params.identity,
3105
- author: entry
3106
- })) {
3107
- kept.push(entry);
3108
- continue;
3109
- }
3110
- if (params.policy.currentBot === "all" || params.policy.currentBot === "root-only" && entry.ts === params.policy.rootTs) kept.push(entry);
3111
- else omittedCurrentBot += 1;
3112
- }
3113
- return {
3114
- kept,
3115
- omittedCurrentBot
3116
- };
3117
- }
3118
- function shouldIncludeBotThreadStarterContext(params) {
3119
- if (!params.hasStarterText) return false;
3120
- return params.starterIsCurrentBot && params.isNewThreadSession;
3121
- }
3122
- function ensureSlackThreadHistoryHasBotRoot(params) {
3123
- if (!params.includeBotStarterAsRootContext || !params.threadStarter?.text) return params.history;
3124
- if (params.history.some((entry) => entry.ts === params.threadStarter?.ts)) return params.history;
3125
- return [params.threadStarter, ...params.history];
3126
- }
3127
- function formatSlackBotStarterThreadLabel(params) {
3128
- const base = `Slack thread ${params.roomLabel}`;
3129
- if (!params.starterText) return base;
3130
- const snippet = formatSlackThreadLabelSnippet(params.starterText).trim();
3131
- if (!snippet) return base;
3132
- return `${base} (assistant root): ${snippet}`;
3133
- }
3134
- function formatSlackThreadLabelSnippet(text) {
3135
- return truncateUtf16Safe(text.replace(/\s+/g, " "), 80);
3136
- }
3137
2977
  //#endregion
3138
2978
  //#region extensions/slack/src/monitor/message-handler/prepare-room-history.ts
3139
2979
  const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
@@ -3300,8 +3140,11 @@ async function resolveSlackHistoryMedia(params) {
3300
3140
  }
3301
3141
  //#endregion
3302
3142
  //#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
3303
- const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-DKCtBgCI.mjs").then((n) => n._));
3143
+ const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-Df0CzcDl.mjs").then((n) => n._));
3304
3144
  const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
3145
+ function formatSlackThreadLabelSnippet(text) {
3146
+ return truncateUtf16Safe(text.replace(/\s+/g, " "), 80);
3147
+ }
3305
3148
  function resolveSlackThreadSessionFreshness(params) {
3306
3149
  return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
3307
3150
  agentId: params.agentId,
@@ -3316,27 +3159,15 @@ function resolveSlackThreadSessionFreshness(params) {
3316
3159
  });
3317
3160
  }
3318
3161
  async function resolveSlackThreadUserMap(params) {
3319
- const uniqueUserIds = [];
3320
- const seen = /* @__PURE__ */ new Set();
3321
- for (const item of params.messages) {
3322
- if (!item.userId || seen.has(item.userId)) continue;
3323
- seen.add(item.userId);
3324
- uniqueUserIds.push(item.userId);
3325
- }
3326
- const userMap = /* @__PURE__ */ new Map();
3327
- if (uniqueUserIds.length === 0) return userMap;
3162
+ const uniqueUserIds = [...new Set(params.messages.map((item) => item.userId).filter((id) => Boolean(id)))];
3328
3163
  const { results } = await runTasksWithConcurrency({
3329
3164
  tasks: uniqueUserIds.map((id) => async () => {
3330
3165
  const user = await params.ctx.resolveUserName(id, params.eventScope);
3331
- return user ? {
3332
- id,
3333
- user
3334
- } : null;
3166
+ return user ? [id, user] : null;
3335
3167
  }),
3336
3168
  limit: SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY
3337
3169
  });
3338
- for (const result of results) if (result) userMap.set(result.id, result.user);
3339
- return userMap;
3170
+ return new Map(results.flatMap((result) => result ? [result] : []));
3340
3171
  }
3341
3172
  async function resolveSlackThreadContextData(params) {
3342
3173
  const botIdentity = {
@@ -3375,10 +3206,7 @@ async function resolveSlackThreadContextData(params) {
3375
3206
  const starter = params.threadStarter;
3376
3207
  const starterSenderName = params.allowNameMatching && params.allowFromLower.length > 0 && starter?.userId ? (await params.ctx.resolveUserName(starter.userId, params.eventScope))?.name : void 0;
3377
3208
  params.assertHistoryCurrent?.();
3378
- const starterIsCurrentBot = Boolean(starter && isCurrentBotAuthor({
3379
- userId: starter.userId,
3380
- botId: starter.botId
3381
- }));
3209
+ const starterIsCurrentBot = Boolean(starter && isCurrentBotAuthor(starter));
3382
3210
  const starterAllowed = !starter || !starterIsCurrentBot && resolveSlackUserAllowed({
3383
3211
  allowList: params.allowFromLower,
3384
3212
  teamId: params.eventScope?.teamId ?? params.ctx.teamId,
@@ -3420,18 +3248,12 @@ async function resolveSlackThreadContextData(params) {
3420
3248
  }
3421
3249
  }
3422
3250
  } else threadLabel = `Slack thread ${params.roomLabel}`;
3423
- const includeBotStarterAsRootContext = shouldIncludeBotThreadStarterContext({
3424
- starterIsCurrentBot,
3425
- isNewThreadSession: shouldSeedInitialThreadContext,
3426
- hasStarterText: Boolean(starter?.text)
3427
- });
3251
+ const includeBotStarterAsRootContext = Boolean(starter?.text && starterIsCurrentBot && shouldSeedInitialThreadContext);
3428
3252
  if (starter?.text && starterIsCurrentBot && !includeBotStarterAsRootContext) logVerbose("slack: omitted current-bot thread starter from context");
3429
3253
  else if (starter?.text && !includeStarterContext && !starterIsCurrentBot) logVerbose(`slack: omitted thread starter from context (mode=${params.contextVisibilityMode}, sender_allowed=${starterAllowed ? "yes" : "no"})`);
3430
3254
  else if (includeBotStarterAsRootContext) {
3431
- threadLabel = formatSlackBotStarterThreadLabel({
3432
- roomLabel: params.roomLabel,
3433
- starterText: starter?.text
3434
- });
3255
+ const snippet = formatSlackThreadLabelSnippet(starter?.text ?? "").trim();
3256
+ threadLabel = `Slack thread ${params.roomLabel}${snippet ? ` (assistant root): ${snippet}` : ""}`;
3435
3257
  logVerbose("slack: retained current-bot thread starter as assistant root context");
3436
3258
  }
3437
3259
  const threadInitialHistoryLimit = Math.min(params.account.config?.thread?.initialHistoryLimit ?? 20, params.historyLimit ?? Number.POSITIVE_INFINITY);
@@ -3469,24 +3291,15 @@ async function resolveSlackThreadContextData(params) {
3469
3291
  text: threadStarterBody,
3470
3292
  ts: currentBotRootTs
3471
3293
  } : null;
3472
- const threadHistoryWithBotRoot = ensureSlackThreadHistoryHasBotRoot({
3473
- history: enrichedStarter && !threadHistory.some((entry) => entry.ts === currentBotRootTs) ? [enrichedStarter, ...threadHistory.length >= threadInitialHistoryLimit ? threadHistory.slice(1) : threadHistory] : threadHistory,
3474
- includeBotStarterAsRootContext,
3475
- threadStarter: starter ? {
3476
- ...starter,
3477
- ts: currentBotRootTs
3478
- } : null
3479
- });
3294
+ const threadHistoryWithEnrichedRoot = enrichedStarter && !threadHistory.some((entry) => entry.ts === currentBotRootTs) ? [enrichedStarter, ...threadHistory.length >= threadInitialHistoryLimit ? threadHistory.slice(1) : threadHistory] : threadHistory;
3295
+ const threadHistoryWithBotRoot = includeBotStarterAsRootContext && starter && !threadHistoryWithEnrichedRoot.some((entry) => entry.ts === currentBotRootTs) ? [{
3296
+ ...starter,
3297
+ ts: currentBotRootTs
3298
+ }, ...threadHistoryWithEnrichedRoot] : threadHistoryWithEnrichedRoot;
3480
3299
  if (threadHistoryWithBotRoot.length > 0) {
3481
- const { kept: threadHistoryWithoutCurrentBot, omittedCurrentBot: omittedCurrentBotHistoryCount } = applySlackThreadHistoryFilterPolicy({
3482
- history: threadHistoryWithBotRoot,
3483
- policy: resolveSlackThreadHistoryFilterPolicy({
3484
- includeBotStarterAsRootContext,
3485
- starterTs: currentBotRootTs,
3486
- retainCurrentBotHistory: params.isGroupDm && (isMissingThreadSession || isOutboundOnlyThreadSession)
3487
- }),
3488
- identity: botIdentity
3489
- });
3300
+ const retainCurrentBotHistory = params.isGroupDm && (isMissingThreadSession || isOutboundOnlyThreadSession);
3301
+ const threadHistoryWithoutCurrentBot = threadHistoryWithBotRoot.filter((entry) => !isCurrentBotAuthor(entry) || retainCurrentBotHistory || includeBotStarterAsRootContext && entry.ts === currentBotRootTs);
3302
+ const omittedCurrentBotHistoryCount = threadHistoryWithBotRoot.length - threadHistoryWithoutCurrentBot.length;
3490
3303
  const userMapForFilter = params.contextVisibilityMode !== "all" && params.allowNameMatching && params.allowFromLower.length > 0 ? await resolveSlackThreadUserMap({
3491
3304
  ctx: params.ctx,
3492
3305
  messages: threadHistoryWithoutCurrentBot,
@@ -3501,10 +3314,7 @@ async function resolveSlackThreadContextData(params) {
3501
3314
  mode: params.contextVisibilityMode,
3502
3315
  kind: "thread",
3503
3316
  isSenderAllowed: (historyMsg) => {
3504
- if (isCurrentBotAuthor({
3505
- userId: historyMsg.userId,
3506
- botId: historyMsg.botId
3507
- })) return true;
3317
+ if (isCurrentBotAuthor(historyMsg)) return true;
3508
3318
  const msgUser = historyMsg.userId ? userMapForFilter.get(historyMsg.userId) : null;
3509
3319
  return resolveSlackUserAllowed({
3510
3320
  allowList: params.allowFromLower,
@@ -3525,10 +3335,7 @@ async function resolveSlackThreadContextData(params) {
3525
3335
  const historyParts = [];
3526
3336
  for (const historyMsg of filteredThreadHistory) {
3527
3337
  const msgUser = historyMsg.userId ? userMap.get(historyMsg.userId) : null;
3528
- const isCurrentBot = isCurrentBotAuthor({
3529
- userId: historyMsg.userId,
3530
- botId: historyMsg.botId
3531
- });
3338
+ const isCurrentBot = isCurrentBotAuthor(historyMsg);
3532
3339
  const role = isCurrentBot || historyMsg.botId ? "assistant" : "user";
3533
3340
  const msgSenderName = isCurrentBot ? "Bot (this assistant)" : msgUser?.name ?? (historyMsg.botId ? `Bot (${historyMsg.botId})` : "Unknown");
3534
3341
  const msgWithId = `${historyMsg.ts === currentBotRootTs && threadStarterBody ? threadStarterBody : historyMsg.text}\n[slack message id: ${historyMsg.ts ?? "unknown"} channel: ${params.message.channel}]`;
@@ -3556,12 +3363,64 @@ async function resolveSlackThreadContextData(params) {
3556
3363
  };
3557
3364
  }
3558
3365
  //#endregion
3366
+ //#region src/channels/mention-gating.ts
3367
+ function resolveBotThreadMentionPolicy(params) {
3368
+ if (!params.isBotOwnedThread || params.requireMentionInBotThreads === void 0) return {
3369
+ requireMention: params.requireMention,
3370
+ implicitMentionKinds: params.implicitMentionKinds
3371
+ };
3372
+ return {
3373
+ requireMention: params.requireMentionInBotThreads,
3374
+ implicitMentionKinds: params.requireMentionInBotThreads ? params.implicitMentionKinds?.filter((kind) => kind === "native") : params.implicitMentionKinds
3375
+ };
3376
+ }
3377
+ //#endregion
3378
+ //#region \0openclaw:bundled-sdk:openclaw/plugin-sdk/channel-mention-gating
3379
+ var channel_mention_gating_exports = /* @__PURE__ */ __exportAll({ resolveBotThreadMentionPolicy: () => resolveBotThreadMentionPolicy });
3380
+ import * as import_openclaw_plugin_sdk_channel_mention_gating from "openclaw/plugin-sdk/channel-mention-gating";
3381
+ __reExport(channel_mention_gating_exports, import_openclaw_plugin_sdk_channel_mention_gating);
3382
+ //#endregion
3383
+ //#region extensions/slack/src/monitor/message-handler/prepare-thread-mentions.ts
3384
+ async function resolveSlackThreadMentionPolicy(params) {
3385
+ const { ctx, account, message, conversation, thread } = params;
3386
+ const { isRoom, isDirectMessage, channelConfig } = conversation;
3387
+ let implicitMentionKinds = [];
3388
+ if (!isDirectMessage && message.thread_ts && !params.wasMentioned) {
3389
+ const replyToBotKinds = (0, channel_mention_gating_exports.implicitMentionKindWhen)("reply_to_bot", Boolean(ctx.botUserId && message.parent_user_id === ctx.botUserId));
3390
+ implicitMentionKinds = replyToBotKinds.length > 0 ? replyToBotKinds : (0, channel_mention_gating_exports.implicitMentionKindWhen)("bot_thread_participant", await hasSlackThreadParticipationWithPersistence({
3391
+ accountId: account.accountId,
3392
+ channelId: message.channel,
3393
+ threadTs: message.thread_ts,
3394
+ teamId: params.teamId
3395
+ }));
3396
+ }
3397
+ const requireMentionInBotThreads = channelConfig?.requireMentionInBotThreads ?? account.config.requireMentionInBotThreads;
3398
+ let isBotOwnedThread = false;
3399
+ if (isRoom && thread.isThreadReply && requireMentionInBotThreads !== void 0) {
3400
+ const parentUserId = normalizeOptionalString(message.parent_user_id);
3401
+ if (parentUserId) isBotOwnedThread = Boolean(ctx.botUserId && parentUserId === ctx.botUserId);
3402
+ else {
3403
+ const starter = await params.getThreadStarter();
3404
+ isBotOwnedThread = Boolean(starter && starter.ts === thread.threadTs && isSlackThreadAuthorCurrentBot({
3405
+ identity: ctx,
3406
+ author: starter
3407
+ }));
3408
+ }
3409
+ }
3410
+ return resolveBotThreadMentionPolicy({
3411
+ isBotOwnedThread,
3412
+ requireMentionInBotThreads,
3413
+ requireMention: isRoom ? channelConfig?.requireMention ?? ctx.defaultRequireMention : false,
3414
+ implicitMentionKinds
3415
+ });
3416
+ }
3417
+ //#endregion
3559
3418
  //#region extensions/slack/src/monitor/message-handler/subteam-mentions.ts
3560
3419
  const SUBTEAM_MENTION_RE = /<!subteam\^([A-Z0-9]+)(?:\|[^>]*)?>/gi;
3561
3420
  const SUBTEAM_MEMBER_CACHE_TTL_MS = 3e5;
3562
3421
  const subteamMemberCache = /* @__PURE__ */ new WeakMap();
3563
3422
  function normalizeSlackId(value) {
3564
- return typeof value === "string" && value.trim() ? value.trim().toUpperCase() : void 0;
3423
+ return normalizeOptionalString(value)?.toUpperCase();
3565
3424
  }
3566
3425
  function extractSlackSubteamMentionIds(text) {
3567
3426
  if (!text) return [];
@@ -3594,7 +3453,7 @@ async function readSlackSubteamUsers(params) {
3594
3453
  params.log?.(`slack: failed to resolve user-group mention ${params.subteamId}: ${response.error ?? "unknown_error"}`);
3595
3454
  return /* @__PURE__ */ new Set();
3596
3455
  }
3597
- const users = new Set((response.users ?? []).map((userId) => normalizeSlackId(userId)).filter(Boolean));
3456
+ const users = new Set((response.users ?? []).map(normalizeSlackId).filter((userId) => userId !== void 0));
3598
3457
  const expiresAt = resolveExpiresAtMsFromDurationMs(SUBTEAM_MEMBER_CACHE_TTL_MS, { nowMs: params.now });
3599
3458
  if (expiresAt !== void 0) bySubteam.set(cacheKey, {
3600
3459
  expiresAt,
@@ -3635,13 +3494,6 @@ function resolveSlackGroupSessionSubject(params) {
3635
3494
  if (channelName && workspaceName) return `${workspaceName} #${channelName}`;
3636
3495
  return `Slack Channel (Workspace ID: ${params.workspaceId}, Channel ID: ${params.channelId})`;
3637
3496
  }
3638
- function recordString(record, key) {
3639
- return normalizeOptionalString(record?.[key]);
3640
- }
3641
- function recordNullableString(record, key) {
3642
- const value = record?.[key];
3643
- return value === null ? null : normalizeOptionalString(value);
3644
- }
3645
3497
  function mergeSlackAssistantThreadContext(primary, fallback) {
3646
3498
  if (!primary) return fallback;
3647
3499
  if (!fallback) return primary;
@@ -3661,16 +3513,16 @@ function resolveSlackMessageAssistantThreadContext(message) {
3661
3513
  const thread = asOptionalRecord(message.assistant_thread);
3662
3514
  if (!thread) return;
3663
3515
  const context = asOptionalRecord(thread.context);
3664
- const assistantChannelId = recordString(thread, "channel_id") ?? message.channel;
3665
- const threadTs = recordString(thread, "thread_ts") ?? message.thread_ts ?? message.ts;
3516
+ const assistantChannelId = normalizeOptionalString(thread.channel_id) ?? message.channel;
3517
+ const threadTs = normalizeOptionalString(thread.thread_ts) ?? message.thread_ts ?? message.ts;
3666
3518
  if (!assistantChannelId || !threadTs) return;
3667
3519
  return {
3668
3520
  assistantChannelId,
3669
3521
  threadTs,
3670
- userId: recordString(thread, "user_id") ?? message.user,
3671
- channelId: recordString(context, "channel_id"),
3672
- teamId: recordString(context, "team_id"),
3673
- enterpriseId: recordNullableString(context, "enterprise_id")
3522
+ userId: normalizeOptionalString(thread.user_id) ?? message.user,
3523
+ channelId: normalizeOptionalString(context?.channel_id),
3524
+ teamId: normalizeOptionalString(context?.team_id),
3525
+ enterpriseId: context?.enterprise_id === null ? null : normalizeOptionalString(context?.enterprise_id)
3674
3526
  };
3675
3527
  }
3676
3528
  async function restoreSlackAssistantThreadContextFromMetadata(params) {
@@ -3752,7 +3604,7 @@ async function resolveSlackConversationContext(params) {
3752
3604
  const cfg = ctx.cfg;
3753
3605
  let channelInfo = {};
3754
3606
  let resolvedChannelType = normalizeSlackChannelType(message.channel_type, message.channel);
3755
- if (resolvedChannelType !== "im" && (!message.channel_type || message.channel_type !== "im")) {
3607
+ if (resolvedChannelType !== "im" && message.channel_type !== "im") {
3756
3608
  channelInfo = await ctx.resolveChannelName(message.channel, params.eventScope);
3757
3609
  resolvedChannelType = normalizeSlackChannelType(message.channel_type ?? channelInfo.type ?? ctx.recallSlackChannelType(message.channel, params.eventScope), message.channel);
3758
3610
  }
@@ -3771,7 +3623,7 @@ async function resolveSlackConversationContext(params) {
3771
3623
  defaultRequireMention: ctx.defaultRequireMention,
3772
3624
  allowNameMatching: ctx.allowNameMatching
3773
3625
  }) : null;
3774
- const allowBotsSetting = channelConfig?.allowBots ?? account.config?.allowBots ?? cfg.channels?.slack?.allowBots ?? false;
3626
+ const allowBotsSetting = channelConfig?.allowBots ?? account.config?.allowBots ?? cfg.channels?.slack?.allowBots ?? true;
3775
3627
  return {
3776
3628
  channelInfo,
3777
3629
  channelName,
@@ -3789,7 +3641,7 @@ async function authorizeSlackInboundMessage(params) {
3789
3641
  const { ctx, account, message, conversation, drop } = params;
3790
3642
  const { isDirectMessage, channelName, resolvedChannelType, isBotMessage, allowBotsMode } = conversation;
3791
3643
  if (isBotMessage) {
3792
- if (message.user && ctx.botUserId && message.user === ctx.botUserId) return null;
3644
+ if (ctx.botUserId && message.user === ctx.botUserId || ctx.botId && message.bot_id === ctx.botId) return null;
3793
3645
  if (allowBotsMode === "off") return drop("bot-disabled");
3794
3646
  }
3795
3647
  if (isDirectMessage && !message.user) return drop("missing-user");
@@ -3938,20 +3790,21 @@ async function prepareSlackMessage(params) {
3938
3790
  eventScope: opts.eventScope
3939
3791
  });
3940
3792
  const channelRequireMention = channelConfig?.requireMention ?? ctx.defaultRequireMention ?? true;
3941
- const channelChatType = isDirectMessage ? "direct" : isGroupDm ? "group" : "channel";
3793
+ const chatType = resolveSlackChatType(conversation.resolvedChannelType);
3942
3794
  const restoredAssistantThreadContext = await restoredAssistantThreadContextPromise;
3943
3795
  const assistantThreadContext = mergeSlackAssistantThreadContext(messageAssistantThreadContext, cachedAssistantThreadContext ?? restoredAssistantThreadContext);
3944
3796
  const assistantThreadContextToCache = messageAssistantThreadContext || restoredAssistantThreadContext ? assistantThreadContext : void 0;
3945
3797
  if (assistantThreadContextToCache) ctx.saveSlackAssistantThreadContext(assistantThreadContextToCache, opts.eventScope);
3946
- const hasAgentViewMessageSignal = isDirectMessage && !opts.eventScope && !assistantThreadContext && isSlackAppContext(message.app_context);
3798
+ const canUseManagedView = isDirectMessage && !opts.eventScope && !assistantThreadContext;
3799
+ const hasAgentViewMessageSignal = canUseManagedView && isSlackAppContext(message.app_context);
3947
3800
  if (hasAgentViewMessageSignal) await ctx.recordSlackAgentView();
3948
3801
  const managedViewThreadTs = message.thread_ts;
3949
- const isManagedViewRoot = isDirectMessage && !opts.eventScope && !assistantThreadContext && !message.parent_user_id && Boolean(managedViewThreadTs && message.ts && managedViewThreadTs === message.ts);
3802
+ const isManagedViewRoot = canUseManagedView && !message.parent_user_id && Boolean(managedViewThreadTs && message.ts && managedViewThreadTs === message.ts);
3950
3803
  if (isManagedViewRoot && managedViewThreadTs) await ctx.recordSlackManagedViewThread(message.channel, managedViewThreadTs);
3951
- const hasManagedViewThread = isDirectMessage && !opts.eventScope && !assistantThreadContext && Boolean(managedViewThreadTs && await ctx.isSlackManagedViewThread(message.channel, managedViewThreadTs));
3952
- const isAgentViewMessage = isDirectMessage && !opts.eventScope && !assistantThreadContext && (hasAgentViewMessageSignal || isManagedViewRoot || hasManagedViewThread || await ctx.isSlackAgentView());
3804
+ const hasManagedViewThread = canUseManagedView && Boolean(managedViewThreadTs && await ctx.isSlackManagedViewThread(message.channel, managedViewThreadTs));
3805
+ const isAgentViewMessage = canUseManagedView && (hasAgentViewMessageSignal || isManagedViewRoot || hasManagedViewThread || await ctx.isSlackAgentView());
3953
3806
  const agentViewThreadTs = isAgentViewMessage ? message.thread_ts ?? message.ts : void 0;
3954
- const channelReplyToMode = channelConfig?.replyToMode ?? resolveSlackReplyToMode(account, channelChatType);
3807
+ const channelReplyToMode = channelConfig?.replyToMode ?? resolveSlackReplyToMode(account, chatType);
3955
3808
  const willImplicitlyThreadReply = isRoom && !channelRequireMention && channelReplyToMode !== "off";
3956
3809
  const seedTopLevelRoomThreadBySource = opts.source === "app_mention" || opts.wasMentioned === true || explicitlyMentioned || willImplicitlyThreadReply;
3957
3810
  const resolveMessageRouting = (seedTopLevelRoomThread) => resolveSlackRoutingContext({
@@ -4034,16 +3887,6 @@ async function prepareSlackMessage(params) {
4034
3887
  ok: true,
4035
3888
  name: void 0
4036
3889
  });
4037
- let implicitMentionKinds = [];
4038
- if (!isDirectMessage && message.thread_ts && !wasMentioned) {
4039
- const replyToBotKinds = implicitMentionKindWhen("reply_to_bot", Boolean(ctx.botUserId && message.parent_user_id === ctx.botUserId));
4040
- implicitMentionKinds = replyToBotKinds.length > 0 ? replyToBotKinds : implicitMentionKindWhen("bot_thread_participant", await hasSlackThreadParticipationWithPersistence({
4041
- accountId: account.accountId,
4042
- channelId: message.channel,
4043
- threadTs: message.thread_ts,
4044
- teamId: opts.eventScope?.teamId
4045
- }));
4046
- }
4047
3890
  let threadStarterPromise;
4048
3891
  const getThreadStarter = () => {
4049
3892
  threadStarterPromise ??= isThreadReply && threadTs ? resolveSlackThreadStarter({
@@ -4079,7 +3922,18 @@ async function prepareSlackMessage(params) {
4079
3922
  cfg,
4080
3923
  surface: "slack"
4081
3924
  });
4082
- const shouldRequireMention = isRoom ? channelConfig?.requireMention ?? ctx.defaultRequireMention : false;
3925
+ const { requireMention: shouldRequireMention, implicitMentionKinds } = await resolveSlackThreadMentionPolicy({
3926
+ ctx,
3927
+ account,
3928
+ message,
3929
+ conversation,
3930
+ thread: routing,
3931
+ wasMentioned,
3932
+ teamId: opts.eventScope?.teamId,
3933
+ getThreadStarter
3934
+ });
3935
+ opts.abortSignal?.throwIfAborted();
3936
+ if (opts.isRuntimePolicyCurrent?.() === false) return drop("final-route-denied");
4083
3937
  const implicitMentions = resolveChannelImplicitMentions({
4084
3938
  cfg,
4085
3939
  channel: "slack",
@@ -4095,6 +3949,7 @@ async function prepareSlackMessage(params) {
4095
3949
  ctx,
4096
3950
  teamId: opts.eventScope?.teamId ?? ctx.teamId,
4097
3951
  senderId,
3952
+ senderAuthentication: message.user ? opts.senderAuthentication : void 0,
4098
3953
  senderName: senderNameForAuth,
4099
3954
  channelType: conversation.resolvedChannelType ?? "channel",
4100
3955
  channelId: message.channel,
@@ -4128,7 +3983,7 @@ async function prepareSlackMessage(params) {
4128
3983
  allowFromLower,
4129
3984
  eventScope: opts.eventScope
4130
3985
  })) return drop("unauthorized-bot");
4131
- const threadContextAllowFromLower = isRoom ? channelUsersAllowlistConfigured ? normalizeAllowListLower(channelConfig?.users) : [] : isDirectMessage ? allowFromLower : [];
3986
+ const threadContextAllowFromLower = isRoom ? channelUsersAllowlistConfigured ? normalizeStringEntriesLower(channelConfig?.users) : [] : isDirectMessage ? allowFromLower : [];
4132
3987
  const contextVisibilityMode = resolveChannelContextVisibilityMode({
4133
3988
  cfg: ctx.cfg,
4134
3989
  channel: "slack",
@@ -4245,7 +4100,6 @@ async function prepareSlackMessage(params) {
4245
4100
  const ignoreOtherMentions = channelConfig?.ignoreOtherMentions ?? false;
4246
4101
  if (isRoom && ignoreOtherMentions && Boolean(ctx.botUserId) && hasAnyMention && !wasMentioned) return drop("other-mention");
4247
4102
  if (isRoom && shouldRequireMention && mentionDecision.shouldSkip) return drop("missing-mention");
4248
- const chatType = resolveSlackChatType(conversation.resolvedChannelType);
4249
4103
  const inboundEventKind = classifyChannelInboundEvent({
4250
4104
  conversation: { kind: chatType },
4251
4105
  unmentionedGroupPolicy: resolveUnmentionedGroupInboundPolicy({
@@ -4258,6 +4112,8 @@ async function prepareSlackMessage(params) {
4258
4112
  });
4259
4113
  const threadStarter = await getThreadStarter();
4260
4114
  const resolvedMessageContent = await getMessageContent();
4115
+ opts.abortSignal?.throwIfAborted();
4116
+ if (opts.isRuntimePolicyCurrent?.() === false) return drop("final-route-denied");
4261
4117
  if (!resolvedMessageContent) return drop("empty-content");
4262
4118
  const { rawBody, effectiveDirectMedia, commandSourceText, mentionStripPatterns } = resolvedMessageContent;
4263
4119
  const bodyForAgent = preflightAudioTranscript ? formatSlackAudioTranscriptForAgent({
@@ -4278,7 +4134,7 @@ async function prepareSlackMessage(params) {
4278
4134
  }) === "message_tool_only";
4279
4135
  const statusReactionsExplicitlyEnabled = cfg.messages?.statusReactions?.enabled === true;
4280
4136
  const isRoomEvent = inboundEventKind === "room_event";
4281
- const shouldAckReaction$1 = () => Boolean(ackReaction && shouldAckReaction({
4137
+ const shouldAckReaction$1 = Boolean(ackReaction && shouldAckReaction({
4282
4138
  scope: cfg.messages?.ackReactionScope,
4283
4139
  inboundEventKind,
4284
4140
  isDirect: isDirectMessage,
@@ -4289,7 +4145,7 @@ async function prepareSlackMessage(params) {
4289
4145
  shouldBypassMention
4290
4146
  }));
4291
4147
  const ackReactionMessageTs = message.ts;
4292
- const shouldSendAckReaction = shouldAckReaction$1() && (!sourceRepliesAreToolOnly || effectiveWasMentioned || shouldBypassMention || isRoomEvent);
4148
+ const shouldSendAckReaction = shouldAckReaction$1 && (!sourceRepliesAreToolOnly || effectiveWasMentioned || shouldBypassMention || isRoomEvent);
4293
4149
  const statusReactionsWillHandle = Boolean(ackReactionMessageTs) && !isRoomEvent && statusReactionsExplicitlyEnabled && shouldSendAckReaction;
4294
4150
  const ackReactionPromise = !statusReactionsWillHandle && shouldSendAckReaction && ackReactionMessageTs && ackReactionValue ? reactSlackMessage(message.channel, ackReactionMessageTs, ackReactionValue, {
4295
4151
  token: ctx.botToken,
@@ -4417,20 +4273,18 @@ async function prepareSlackMessage(params) {
4417
4273
  let { threadStarterBody, threadHistoryBody, shouldSeedInitialThreadContext } = threadContextData;
4418
4274
  const threadScopedHistory = isThreadReply && ctx.threadHistoryScope === "thread";
4419
4275
  let roomHistory = [];
4420
- if (isRoomish && ctx.historyLimit > 0 && (!threadScopedHistory || !shouldSeedInitialThreadContext)) {
4421
- if (sessionEntry?.updatedAt !== 0) roomHistory = await resolveSlackRoomHistory({
4422
- ctx,
4423
- message,
4424
- threadTs: threadScopedHistory ? threadTs : void 0,
4425
- oldest: sessionEntry?.sessionStartedAt ? (sessionEntry.sessionStartedAt / 1e3).toFixed(6) : void 0,
4426
- excludedMessageIds,
4427
- allowFromLower: threadContextAllowFromLower,
4428
- contextVisibilityMode,
4429
- eventScope: opts.eventScope,
4430
- assertCurrent: assertHistoryCurrent,
4431
- abortSignal: opts.abortSignal
4432
- });
4433
- }
4276
+ if (isRoomish && ctx.historyLimit > 0 && (!threadScopedHistory || !shouldSeedInitialThreadContext) && sessionEntry?.updatedAt !== 0) roomHistory = await resolveSlackRoomHistory({
4277
+ ctx,
4278
+ message,
4279
+ threadTs: threadScopedHistory ? threadTs : void 0,
4280
+ oldest: sessionEntry?.sessionStartedAt ? (sessionEntry.sessionStartedAt / 1e3).toFixed(6) : void 0,
4281
+ excludedMessageIds,
4282
+ allowFromLower: threadContextAllowFromLower,
4283
+ contextVisibilityMode,
4284
+ eventScope: opts.eventScope,
4285
+ assertCurrent: assertHistoryCurrent,
4286
+ abortSignal: opts.abortSignal
4287
+ });
4434
4288
  const effectiveMedia = effectiveDirectMedia ?? threadStarterMedia;
4435
4289
  let inboundMedia = await toInboundMediaFactsWithMetadata(effectiveMedia, { transcribed: (entry) => effectiveMedia === effectiveDirectMedia && entry === preflightAudioMedia });
4436
4290
  opts.abortSignal?.throwIfAborted();