@openclaw/slack 2026.10.10 → 2026.11.5-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/dist/.setup/{account-inspect-Bc7TVU8F.mjs → account-inspect-DgQgj0wk.mjs} +11 -8
  2. package/dist/.setup/{accounts-CEgdyqoW.mjs → accounts-EaPP0fFY.mjs} +10 -1
  3. package/dist/.setup/{action-runtime-DPoxYao5.mjs → action-runtime-CK9QZgQl.mjs} +38 -45
  4. package/dist/.setup/action-runtime.runtime-CpZktret.mjs +1 -0
  5. package/dist/.setup/{actions-PF2cP6to.mjs → actions-s3CcFO45.mjs} +89 -76
  6. package/dist/.setup/{approval-handler.runtime-BtRklemy.mjs → approval-handler.runtime-Ch7BecYK.mjs} +26 -30
  7. package/dist/.setup/{approval-message-updates-CpwbsEj6.mjs → approval-message-updates-CqcRoa28.mjs} +1 -1
  8. package/dist/.setup/{channel-B6bRmYmX.mjs → channel-CAvo_WNZ.mjs} +566 -338
  9. package/dist/.setup/{channel-type-Dh4vwh1Y.mjs → channel-type-9Lw6yLf2.mjs} +4 -8
  10. package/dist/.setup/{channel.setup-BBzT6uKA.mjs → channel.setup-BlgXNuCJ.mjs} +13 -13
  11. package/dist/.setup/{config-schema-Cz3uId-c.mjs → config-schema-Bx1tCZB0.mjs} +3 -7
  12. package/dist/.setup/cursor-pages-jVn3Vkfi.mjs +309 -0
  13. package/dist/.setup/{directory-config-BEPra1E2.mjs → directory-config-CGvKYg9F.mjs} +3 -3
  14. package/dist/.setup/{directory-live-BkUwPrS0.mjs → directory-live-DNdw97LA.mjs} +4 -4
  15. package/dist/.setup/{doctor-contract-HK8aedwU.mjs → doctor-contract-BB2KJ9Ni.mjs} +37 -45
  16. package/dist/.setup/{message-tool-api-DeiQJoRV.mjs → message-tool-api-B38BpEaE.mjs} +4 -3
  17. package/dist/.setup/{monitor-DsZUQtTM.mjs → monitor-BD86SotB.mjs} +3397 -3672
  18. package/dist/.setup/{outbound-adapter-C0R5jz6S.mjs → outbound-adapter-BH6iPWBj.mjs} +30 -36
  19. package/dist/.setup/paths-CQZI_5WY.mjs +7 -0
  20. package/dist/.setup/{pipeline.runtime-CIFVL0kf.mjs → pipeline.runtime-C4ELxaRU.mjs} +415 -534
  21. package/dist/.setup/{policy-Bp1FvE6m.mjs → policy-C6_DdlSf.mjs} +1 -2
  22. package/dist/.setup/{session-status-CHkEn3HM.mjs → probe-B_Ax1vS1.mjs} +985 -622
  23. package/dist/.setup/question-delivery-D3qAIwuv.mjs +38 -0
  24. package/dist/.setup/{relay-source-DFBDTA5Z.mjs → relay-source-a8jodKuO.mjs} +11 -4
  25. package/dist/.setup/{replies-7DRN46EL.mjs → replies-Bq7n0gfM.mjs} +34 -19
  26. package/dist/.setup/{reply-blocks-DOjiDr44.mjs → reply-blocks-DyYYRrP_.mjs} +200 -205
  27. package/dist/.setup/{resolve-channels-BNQ1KZXh.mjs → resolve-channels-CF2JME9q.mjs} +4 -7
  28. package/dist/.setup/{resolve-users-C4dC8Z7D.mjs → resolve-users-DDcCAjH1.mjs} +8 -16
  29. package/dist/.setup/{scopes-C1aeCBa6.mjs → scopes-CzHC_dwV.mjs} +2 -1
  30. package/dist/.setup/{secret-contract-D0UY2JWF.mjs → secret-contract-CqVqR7MP.mjs} +4 -2
  31. package/dist/.setup/{secret-contract-api-BhzGpUb0.mjs → secret-contract-api-DaCXZ47j.mjs} +1 -1
  32. package/dist/.setup/{send-C5uXkmZV.mjs → send-WJZ73VSf.mjs} +297 -333
  33. package/dist/.setup/{send-results-D-o6PgtS.mjs → send-results-Bm6V1ekL.mjs} +3 -4
  34. package/dist/.setup/setup-plugin-api-DJXIB8CF.mjs +2 -0
  35. package/dist/.setup/{setup-surface-CtM1pm-9.mjs → setup-surface-uIqP2B0Y.mjs} +5 -6
  36. package/dist/.setup/{slash-dispatch.runtime-Bnn9a5qB.mjs → slash-dispatch.runtime-Cwuwv7FL.mjs} +2 -2
  37. package/dist/.setup/{target-parsing-0pRZtahO.mjs → target-parsing-DwYAP3ts.mjs} +1 -2
  38. package/dist/.setup/{targets-BqXz7CpG.mjs → targets-eeOxA_b_.mjs} +1 -1
  39. package/dist/.source-module-urls/c5ffd0957b234c7c12090e7de4eca2482ef339b8561e078da55b734211b0ba58.json +1 -0
  40. package/dist/account-inspect-api.js +1 -1
  41. package/dist/api.js +16 -17
  42. package/dist/channel-config-api.js +1 -1
  43. package/dist/channel-plugin-api.js +1 -1
  44. package/dist/directory-contract-api.js +1 -1
  45. package/dist/doctor-contract-api.js +1 -1
  46. package/dist/index.js +0 -6
  47. package/dist/message-tool-api.js +1 -1
  48. package/dist/runtime-api.js +10 -12
  49. package/dist/secret-contract-api.js +1 -1
  50. package/dist/setup-entry.js +2 -2
  51. package/dist/setup-plugin-api.js +1 -1
  52. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
  53. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
  54. package/node_modules/@slack/bolt/node_modules/@types/node/util.d.ts +6 -3
  55. package/node_modules/@slack/bolt/node_modules/body-parser/README.md +13 -17
  56. package/node_modules/@slack/bolt/node_modules/body-parser/lib/read.js +57 -74
  57. package/node_modules/@slack/bolt/node_modules/body-parser/lib/types/json.js +11 -11
  58. package/node_modules/@slack/bolt/node_modules/body-parser/lib/types/urlencoded.js +5 -5
  59. package/node_modules/@slack/bolt/node_modules/body-parser/lib/utils.js +15 -0
  60. package/node_modules/@slack/bolt/node_modules/body-parser/package.json +12 -7
  61. package/node_modules/@slack/bolt/node_modules/content-disposition/README.md +105 -35
  62. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.d.ts +72 -0
  63. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js +388 -0
  64. package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js.map +1 -0
  65. package/node_modules/@slack/bolt/node_modules/content-disposition/package.json +31 -19
  66. package/node_modules/@slack/bolt/node_modules/content-type/README.md +34 -57
  67. package/node_modules/@slack/bolt/node_modules/content-type/package.json +35 -25
  68. package/node_modules/@slack/bolt/node_modules/express/Readme.md +15 -9
  69. package/node_modules/@slack/bolt/node_modules/express/lib/application.js +2 -2
  70. package/node_modules/@slack/bolt/node_modules/express/lib/request.js +32 -19
  71. package/node_modules/@slack/bolt/node_modules/express/lib/response.js +27 -30
  72. package/node_modules/@slack/bolt/node_modules/express/package.json +10 -10
  73. package/node_modules/@slack/bolt/node_modules/qs/.github/THREAT_MODEL.md +4 -2
  74. package/node_modules/@slack/bolt/node_modules/qs/CHANGELOG.md +38 -14
  75. package/node_modules/@slack/bolt/node_modules/qs/README.md +31 -3
  76. package/node_modules/@slack/bolt/node_modules/qs/dist/qs.js +20 -20
  77. package/node_modules/@slack/bolt/node_modules/qs/lib/parse.js +94 -4
  78. package/node_modules/@slack/bolt/node_modules/qs/lib/stringify.js +4 -4
  79. package/node_modules/@slack/bolt/node_modules/qs/lib/utils.js +130 -6
  80. package/node_modules/@slack/bolt/node_modules/qs/package.json +4 -4
  81. package/node_modules/@slack/bolt/node_modules/qs/test/parse.js +174 -0
  82. package/node_modules/@slack/bolt/node_modules/qs/test/stringify.js +263 -33
  83. package/node_modules/@slack/bolt/node_modules/qs/test/utils.js +184 -0
  84. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
  85. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
  86. package/node_modules/@slack/web-api/node_modules/@types/node/util.d.ts +6 -3
  87. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  88. package/node_modules/typebox/build/format/duration.mjs +2 -2
  89. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  90. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  91. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  92. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  93. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  94. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  95. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  96. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  97. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  98. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  99. package/node_modules/typebox/build/schema/build.mjs +1 -0
  100. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  101. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  102. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  103. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  104. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  105. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  106. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  107. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  108. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  109. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  110. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  111. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  112. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  113. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  114. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  115. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  116. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  117. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  118. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  119. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  120. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  121. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  122. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  123. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  124. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  125. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  126. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  127. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  128. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  129. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  130. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  131. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  132. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  133. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  134. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  135. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  136. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  137. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  138. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  139. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  140. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  141. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  142. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  143. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  144. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  145. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  146. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  147. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  148. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  149. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  150. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  151. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  152. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  153. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  154. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  155. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  156. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  157. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  158. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  159. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  160. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  161. package/node_modules/typebox/package.json +1 -1
  162. package/node_modules/typebox/readme.md +1 -1
  163. package/node_modules/undici/docs/docs/api/Interceptors.md +15 -2
  164. package/node_modules/undici/lib/dispatcher/client-h2.js +78 -3
  165. package/node_modules/undici/lib/dispatcher/pool-base.js +20 -3
  166. package/node_modules/undici/package.json +3 -3
  167. package/node_modules/undici/types/api.d.ts +1 -1
  168. package/node_modules/undici/types/utility.d.ts +4 -4
  169. package/node_modules/zod/package.json +1 -1
  170. package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
  171. package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
  172. package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
  173. package/node_modules/zod/src/v4/core/compile.ts +9 -0
  174. package/node_modules/zod/src/v4/core/schemas.ts +35 -1
  175. package/node_modules/zod/src/v4/core/util.ts +13 -0
  176. package/node_modules/zod/src/v4/core/versions.ts +1 -1
  177. package/node_modules/zod/v4/core/compile.cjs +8 -0
  178. package/node_modules/zod/v4/core/compile.js +8 -0
  179. package/node_modules/zod/v4/core/schemas.cjs +30 -0
  180. package/node_modules/zod/v4/core/schemas.d.cts +3 -1
  181. package/node_modules/zod/v4/core/schemas.d.ts +3 -1
  182. package/node_modules/zod/v4/core/schemas.js +30 -0
  183. package/node_modules/zod/v4/core/util.cjs +15 -0
  184. package/node_modules/zod/v4/core/util.d.cts +2 -0
  185. package/node_modules/zod/v4/core/util.d.ts +2 -0
  186. package/node_modules/zod/v4/core/util.js +14 -0
  187. package/node_modules/zod/v4/core/versions.cjs +1 -1
  188. package/node_modules/zod/v4/core/versions.js +1 -1
  189. package/openclaw.plugin.json +6 -30
  190. package/package.json +7 -7
  191. package/dist/.setup/action-runtime.runtime-DWKWaKgC.mjs +0 -1
  192. package/dist/.setup/http-GpAVKwSX.mjs +0 -2
  193. package/dist/.setup/plugin-routes-lXsy_bNV.mjs +0 -21
  194. package/dist/.setup/probe-C5VWf3sz.mjs +0 -686
  195. package/dist/.setup/registry-1G0f1zuZ.mjs +0 -34
  196. package/dist/.setup/setup-plugin-api-D7DoueEh.mjs +0 -2
  197. package/dist/.setup/shared-CohTHxM1.mjs +0 -255
  198. package/dist/.source-module-urls/562d694877afe9d9dcbb3b32a8883c16974738f2aa892c48d45572cdc9a62529.json +0 -1
  199. package/dist/http-routes-api.js +0 -1
  200. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/LICENSE +0 -22
  201. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +0 -71
  202. package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +0 -52
  203. package/node_modules/@slack/bolt/node_modules/content-disposition/index.js +0 -536
  204. package/node_modules/@slack/bolt/node_modules/content-type/HISTORY.md +0 -29
  205. package/node_modules/@slack/bolt/node_modules/content-type/index.js +0 -225
  206. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +0 -22
  207. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +0 -71
  208. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +0 -46
  209. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +0 -176
  210. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +0 -1
  211. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +0 -52
  212. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/LICENSE +0 -22
  213. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +0 -71
  214. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +0 -46
  215. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +0 -176
  216. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +0 -1
  217. package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +0 -52
  218. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  219. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
  220. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.d.ts +0 -0
  221. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js +0 -0
  222. /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js.map +0 -0
@@ -1,21 +1,23 @@
1
1
  import { r as isSlackPluginAccountConfigured } from "./account-configured-35y0-Hso.mjs";
2
- import { c as resolveSlackAccountAllowFrom, d as resolveSlackOperationToken, f as resolveSlackReplyToMode, i as listSlackAccountIds, n as hasImplicitDefaultSlackAccount, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-CEgdyqoW.mjs";
3
- import { a as parseSlackTarget, i as normalizeSlackMessagingTarget, n as formatSlackTarget, o as resolveSlackChannelId, r as looksLikeSlackTargetId, t as canonicalizeSlackApiTargetId } from "./target-parsing-0pRZtahO.mjs";
4
- import { t as slackContextTargetsMatch } from "./targets-BqXz7CpG.mjs";
5
- import { At as resolveSlackApprovalTeamId, Bt as resolvePluginApprovalSlackApprovers, Ct as resolveSlackFallbackOriginTarget, Dt as slackTargetsMatch, Et as shouldHandleSlackPluginViaForwardingSession, Ft as isSlackExecApprovalAuthorizedSender, Ht as resolveSlackAutoThreadId, It as isSlackExecApprovalClientEnabled, M as SLACK_TEXT_LIMIT, Mt as isSlackWorkspaceInstallation, N as countSlackTextUtf8Bytes, Ot as getSlackApprovalApproversForTeam, Pt as getSlackExecApprovalApprovers, Q as normalizeSlackOutboundText, Rt as resolveSlackExecApprovalTarget, St as resolveSlackApproverDmTargets, Tt as shouldHandleSlackNativeApprovalRequest, _t as isSlackAnyNativeApprovalClientEnabled, a as resolveSlackGroupRequireMention, bt as normalizeSlackOriginTarget, c as qualifySlackConversationId, d as normalizeSlackRouteBindingConfig, f as resolveSlackConversationBindingRoute, ft as SLACK_PRESENTATION_CAPABILITIES, jt as getSlackInstallationKind, k as SLACK_EDIT_TEXT_MAX_BYTES, kt as isSlackPluginApprovalAuthorizedSender, l as qualifySlackRoutePeerId, m as assertSlackDetachedTargetAllowed, n as setSlackSessionStatus, o as resolveSlackGroupToolPolicy, ot as renderSlackMessagePresentationFallbackText, vt as isSlackPluginApprovalRequest, wt as resolveTurnSourceSlackOriginTarget, xt as resolveSessionSlackOriginTarget, yt as normalizeSlackForwardTarget, zt as shouldSuppressLocalSlackExecApprovalPrompt } from "./session-status-CHkEn3HM.mjs";
6
- import { _ as getSlackWriteClient, c as collectSlackCursorPages, o as formatSlackError, u as createSlackLookupClient } from "./probe-C5VWf3sz.mjs";
7
- import { c as resolveSlackReplyDeliveryMessages, o as resolveSlackReplyBlockResolution, p as buildSlackPresentationBlocksIfComplete, r as normalizeSlackReplyPayload, s as resolveSlackReplyBlocks } from "./reply-blocks-DOjiDr44.mjs";
2
+ import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, d as resolveSlackMarkdownOptions, f as resolveSlackOperationToken, i as listSlackAccountIds, l as resolveSlackAccountDmPolicy, n as hasImplicitDefaultSlackAccount, o as resolveDefaultSlackAccountId, p as resolveSlackReplyToMode, s as resolveSlackAccount } from "./accounts-EaPP0fFY.mjs";
3
+ import { t as inspectSlackAccount } from "./account-inspect-DgQgj0wk.mjs";
4
+ import { a as parseSlackTarget, i as normalizeSlackMessagingTarget, n as formatSlackTarget, o as resolveSlackChannelId, r as looksLikeSlackTargetId, t as canonicalizeSlackApiTargetId } from "./target-parsing-DwYAP3ts.mjs";
5
+ import { t as slackContextTargetsMatch } from "./targets-eeOxA_b_.mjs";
6
+ import { $t as resolveSlackExecApprovalTarget, At as resolveSessionSlackOriginTarget, Dt as isSlackPluginApprovalRequest, Et as isSlackAnyNativeApprovalClientEnabled, Ft as shouldHandleSlackPluginViaForwardingSession, It as slackTargetsMatch, Kt as getSlackInstallationKind, Lt as getSlackApprovalApproversForTeam, Mt as resolveSlackFallbackOriginTarget, Nt as resolveTurnSourceSlackOriginTarget, Ot as normalizeSlackForwardTarget, P as countSlackTextUtf8Bytes, Pt as shouldHandleSlackNativeApprovalRequest, Rt as isSlackPluginApprovalAuthorizedSender, S as assertSlackDetachedTargetAllowed, Xt as isSlackExecApprovalAuthorizedSender, Yt as getSlackExecApprovalApprovers, Zt as isSlackExecApprovalClientEnabled, _ as qualifySlackRoutePeerId, _t as renderSlackMessagePresentationFallbackText, b as resolveSlackConversationBindingRoute, d as resolveSlackGroupRequireMention, en as shouldSuppressLocalSlackExecApprovalPrompt, f as resolveSlackGroupToolPolicy, g as qualifySlackConversationId, i as setSlackSessionStatus, jt as resolveSlackApproverDmTargets, kt as normalizeSlackOriginTarget, m as formatSlackError, mt as SLACK_PRESENTATION_CAPABILITIES, qt as isSlackWorkspaceInstallation, rn as resolveSlackAutoThreadId, s as slackIngressIdentity, t as probeSlack, tn as resolvePluginApprovalSlackApprovers, vt as SLACK_EDIT_TEXT_MAX_BYTES, wt as normalizeSlackOutboundText, xt as SLACK_TEXT_LIMIT, y as normalizeSlackRouteBindingConfig, zt as resolveSlackApprovalTeamId } from "./probe-B_Ax1vS1.mjs";
8
7
  import { n as resolveSlackReplyThreadTs, r as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-47Au2-Yn.mjs";
9
- import { n as extractSlackToolSend, t as describeSlackMessageTool } from "./message-tool-api-DeiQJoRV.mjs";
10
- import { n as resolveSlackChannelType, r as resolveSlackConversationInfo } from "./channel-type-Dh4vwh1Y.mjs";
11
- import { t as getOptionalSlackRuntime } from "./runtime-C6HKn7Av.mjs";
12
- import { n as slackPluginBase, r as slackSecurityAdapter, t as slackConfigAdapter } from "./shared-CohTHxM1.mjs";
13
- import { i as SLACK_CHANNEL } from "./channel.setup-BBzT6uKA.mjs";
14
- import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
15
- import { normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/account-resolution";
8
+ import { n as extractSlackToolSend, t as describeSlackMessageTool } from "./message-tool-api-B38BpEaE.mjs";
9
+ import { a as resolveSlackReplyBlockResolution, o as resolveSlackReplyBlocks, r as normalizeSlackReplyPayload, s as resolveSlackReplyDeliveryMessages } from "./reply-blocks-DyYYRrP_.mjs";
10
+ import { r as createSlackLookupClient, t as collectSlackCursorPages, u as getSlackWriteClient } from "./cursor-pages-jVn3Vkfi.mjs";
11
+ import { n as resolveSlackChannelType, r as resolveSlackConversationInfo } from "./channel-type-9Lw6yLf2.mjs";
12
+ import { n as SLACK_CHANNEL_META } from "./channel-meta-C5vsCo3a.mjs";
13
+ import { i as SLACK_CHANNEL, r as slackBaseConfigAdapter, t as slackSetupPlugin } from "./channel.setup-BlgXNuCJ.mjs";
14
+ import { n as normalizeCompatibilityConfig, r as runtime_doctor_migrations_exports, t as legacyConfigRules } from "./doctor-contract-BB2KJ9Ni.mjs";
15
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-CqVqR7MP.mjs";
16
+ import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
16
17
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
17
- import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
18
+ import { adaptScopedAccountAccessor, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
18
19
  import { buildOutboundBaseSessionKey, normalizeMessageChannel, resolveAccountEntry, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
20
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$2 } from "openclaw/plugin-sdk/account-id";
19
21
  import { buildLegacyDmAccountAllowlistAdapter, createAccountScopedAllowlistNameResolver, createFlatAllowlistOverrideResolver } from "openclaw/plugin-sdk/allowlist-config-edit";
20
22
  import { buildThreadAwareOutboundSessionRoute, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
21
23
  import { createChannelMessageAdapterFromOutbound, createRuntimeOutboundDelegates } from "openclaw/plugin-sdk/channel-outbound";
@@ -33,8 +35,10 @@ import { createChannelNativeOriginTargetResolverAsync, createNativeApprovalForwa
33
35
  import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
34
36
  import { resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
35
37
  import { normalizeLegacyInteractiveReply, normalizeMessagePresentation } from "openclaw/plugin-sdk/interactive-runtime";
36
- import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
37
38
  import { readPositiveIntegerParam as readPositiveIntegerParam$1, readStringParam as readStringParam$1 } from "openclaw/plugin-sdk/param-readers";
39
+ import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, createConditionalWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
40
+ import { identityEntryAuthenticationClassifier } from "openclaw/plugin-sdk/channel-ingress-runtime";
41
+ import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
38
42
  // extensions/slack/src/approval-native.ts
39
43
  function resolveSlackNativeSuppressionAccountId({ target, request }) {
40
44
  return normalizeOptionalString(target.accountId) ?? normalizeOptionalString(request.request.turnSourceAccountId);
@@ -99,7 +103,7 @@ const baseSlackApprovalCapability = createApproverRestrictedNativeApprovalCapabi
99
103
  ],
100
104
  isConfigured: isSlackAnyNativeApprovalClientEnabled,
101
105
  shouldHandle: shouldHandleSlackNativeApprovalRequest,
102
- load: async () => (await import("./approval-handler.runtime-BtRklemy.mjs")).slackApprovalNativeRuntime
106
+ load: async () => (await import("./approval-handler.runtime-Ch7BecYK.mjs")).slackApprovalNativeRuntime
103
107
  })
104
108
  });
105
109
  const baseSlackNativeAdapter = baseSlackApprovalCapability.nativeAsync;
@@ -167,7 +171,7 @@ const slackApprovalCapability = {
167
171
  }
168
172
  } : void 0
169
173
  };
170
- // extensions/slack/src/message-action-dispatch.ts
174
+ // extensions/slack/src/channel-actions.ts
171
175
  const SLACK_MESSAGE_ACTIONS = /* @__PURE__ */ new Map([
172
176
  ["reactions", "reactions"],
173
177
  ["delete", "deleteMessage"],
@@ -178,195 +182,28 @@ const SLACK_MESSAGE_ACTIONS = /* @__PURE__ */ new Map([
178
182
  function readSlackForceDocument(params) {
179
183
  return readBooleanParam(params, "forceDocument") ?? readBooleanParam(params, "asDocument") ?? false;
180
184
  }
181
- function renderSlackActionPresentation(content, presentation) {
185
+ function renderSlackActionPresentation(content, presentation, markdownOptions) {
186
+ const renderedContent = normalizeSlackOutboundText(content ?? "", markdownOptions);
182
187
  if (!presentation) return {
183
- text: content ?? "",
188
+ text: renderedContent,
184
189
  usesPresentationTextFallback: false
185
190
  };
186
- const renderedBlocks = presentation.blocks.some((block) => (block.type === "text" || block.type === "context") && block.text.trim().length > 3e3) ? void 0 : buildSlackPresentationBlocksIfComplete(presentation);
187
- const usesPresentationTextFallback = !renderedBlocks || renderedBlocks.length > 50;
188
- const blocks = usesPresentationTextFallback ? void 0 : renderedBlocks;
191
+ const resolution = resolveSlackReplyBlockResolution({
192
+ text: content,
193
+ presentation
194
+ }, markdownOptions);
195
+ const segment = resolution.segments.length === 1 ? resolution.segments[0] : void 0;
196
+ const usesPresentationTextFallback = segment?.kind !== "blocks" || presentation.blocks.some((block) => (block.type === "text" || block.type === "context") && block.text.trim().length > 3e3);
197
+ const blocks = !usesPresentationTextFallback && segment?.kind === "blocks" ? segment.blocks : void 0;
189
198
  return {
190
199
  ...blocks?.length ? { blocks } : {},
191
200
  text: usesPresentationTextFallback || presentation.blocks.some((block) => block.type === "chart" || block.type === "table") ? renderSlackMessagePresentationFallbackText({
192
- text: content,
201
+ text: resolution.authoredTextPlacement === "blocks" ? void 0 : renderedContent,
193
202
  presentation
194
- }) : content ?? "",
203
+ }) : renderedContent,
195
204
  usesPresentationTextFallback
196
205
  };
197
206
  }
198
- async function handleSlackMessageAction(params) {
199
- const { providerId, ctx, invoke } = params;
200
- const { action, cfg, params: actionParams } = ctx;
201
- const accountId = ctx.accountId ?? void 0;
202
- const invokeSlackAction = (request, toolContext = ctx.toolContext) => invoke({
203
- ...request,
204
- accountId
205
- }, cfg, toolContext);
206
- const resolveChannelId = () => {
207
- const raw = readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to", { required: true });
208
- const target = parseSlackTarget(raw, { defaultKind: "channel" });
209
- const channelId = resolveSlackChannelId(raw);
210
- return formatSlackTarget({
211
- teamId: target?.teamId,
212
- kind: "channel",
213
- id: channelId
214
- });
215
- };
216
- if (action === "conversation-open") return await invokeSlackAction({
217
- action: "openConversation",
218
- userIds: actionParams.userIds,
219
- teamId: readStringParam$1(actionParams, "teamId")
220
- });
221
- if (action === "send") {
222
- const to = readStringParam$1(actionParams, "to", { required: true });
223
- const content = readStringParam$1(actionParams, "message", {
224
- required: false,
225
- allowEmpty: true
226
- });
227
- const mediaUrl = readStringParam$1(actionParams, "media", { trim: false });
228
- const presentation = normalizeMessagePresentation(actionParams.presentation);
229
- const interactive = normalizeLegacyInteractiveReply(actionParams.interactive);
230
- const hasStructuredContent = Boolean(presentation || interactive?.blocks.length);
231
- const resolution = resolveSlackReplyBlockResolution({
232
- text: content,
233
- presentation,
234
- interactive
235
- }, { materializeAuthoredText: hasStructuredContent });
236
- const preparedMessages = resolution.segments.length > 0 ? resolveSlackReplyDeliveryMessages({
237
- authoredTextPlacement: resolution.authoredTextPlacement,
238
- segments: resolution.segments,
239
- text: content
240
- }) : [];
241
- if (!content && preparedMessages.length === 0 && !mediaUrl) throw new Error("Slack send requires message, blocks, or media.");
242
- const replyBroadcast = readBooleanParam(actionParams, "replyBroadcast");
243
- if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
244
- const threadId = readStringParam$1(actionParams, "threadId");
245
- const replyTo = readStringParam$1(actionParams, "replyTo");
246
- const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
247
- const toolContext = preparedMessages.length > 0 ? {
248
- ...ctx.toolContext,
249
- preparedMessages
250
- } : ctx.toolContext;
251
- return await invokeSlackAction({
252
- action: "sendMessage",
253
- to,
254
- content: content ?? "",
255
- mediaUrl: mediaUrl ?? void 0,
256
- ...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
257
- threadTs: resolveSlackThreadTsValue({
258
- replyToId: replyTo,
259
- threadId
260
- }),
261
- ...topLevel ? { topLevel: true } : {},
262
- ...replyBroadcast ? { replyBroadcast } : {}
263
- }, toolContext);
264
- }
265
- if (action === "react") {
266
- const messageIdRaw = resolveReactionMessageId({
267
- args: actionParams,
268
- toolContext: ctx.toolContext
269
- });
270
- if (messageIdRaw == null) throw new Error("messageId required. Provide messageId explicitly or react to the current inbound message.");
271
- const messageId = String(messageIdRaw);
272
- const emoji = readStringParam$1(actionParams, "emoji", { allowEmpty: true });
273
- const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : void 0;
274
- return await invokeSlackAction({
275
- action: "react",
276
- channelId: resolveChannelId(),
277
- messageId,
278
- emoji,
279
- remove
280
- });
281
- }
282
- const messageAction = SLACK_MESSAGE_ACTIONS.get(action);
283
- if (messageAction) {
284
- const messageId = action === "list-pins" ? void 0 : readStringParam$1(actionParams, "messageId", { required: true });
285
- return await invokeSlackAction({
286
- action: messageAction,
287
- channelId: resolveChannelId(),
288
- messageId,
289
- ...action === "reactions" ? { limit: actionParams.limit } : {}
290
- });
291
- }
292
- if (action === "read") return await invokeSlackAction({
293
- action: "readMessages",
294
- channelId: resolveChannelId(),
295
- limit: actionParams.limit,
296
- before: readStringParam$1(actionParams, "before"),
297
- after: readStringParam$1(actionParams, "after"),
298
- messageId: readStringParam$1(actionParams, "messageId"),
299
- threadId: readStringParam$1(actionParams, "threadId")
300
- });
301
- if (action === "edit") {
302
- const messageId = readStringParam$1(actionParams, "messageId", { required: true });
303
- const { blocks, text: accessibleContent, usesPresentationTextFallback } = renderSlackActionPresentation(readStringParam$1(actionParams, "message", { allowEmpty: true }), normalizeMessagePresentation(actionParams.presentation));
304
- const tableMode = resolveMarkdownTableMode({
305
- cfg,
306
- channel: "slack",
307
- accountId: accountId ?? resolveDefaultSlackAccountId(cfg)
308
- });
309
- if (!blocks && countSlackTextUtf8Bytes(normalizeSlackOutboundText(accessibleContent, { tableMode })) > 4e3) throw new Error(`${usesPresentationTextFallback ? "Slack presentation fallback" : "Slack edit"} exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`);
310
- if (!accessibleContent && !blocks) throw new Error("Slack edit requires message or blocks.");
311
- return await invokeSlackAction({
312
- action: "editMessage",
313
- channelId: resolveChannelId(),
314
- messageId,
315
- content: accessibleContent,
316
- blocks
317
- });
318
- }
319
- if (action === "member-info") {
320
- const requesterAccountId = ctx.requesterAccountId ? normalizeAccountId$1(ctx.requesterAccountId) : void 0;
321
- const targetAccountId = normalizeAccountId$1(accountId ?? resolveDefaultSlackAccountId(cfg));
322
- const requesterUserId = normalizeOptionalLowercaseString(ctx.toolContext?.currentChannelProvider) === "slack" && requesterAccountId !== void 0 && requesterAccountId === targetAccountId ? normalizeOptionalString(ctx.requesterSenderId) : void 0;
323
- const userId = readStringParam$1(actionParams, "userId") ?? requesterUserId;
324
- if (!userId) throw new Error("member-info requires a userId outside a current Slack conversation.");
325
- return await invokeSlackAction({
326
- action: "memberInfo",
327
- userId
328
- });
329
- }
330
- if (action === "emoji-list") return await invokeSlackAction({
331
- action: "emojiList",
332
- limit: readPositiveIntegerParam$1(actionParams, "limit", { message: "limit must be a positive integer." })
333
- });
334
- if (action === "download-file") {
335
- const fileIdParam = readStringParam$1(actionParams, "fileId");
336
- const messageIdParam = readStringParam$1(actionParams, "messageId") ?? readStringParam$1(actionParams, "message_id");
337
- if (!fileIdParam && messageIdParam) throw new Error("download-file requires fileId (the Slack file id, for example F0B0LTT8M36 from event.files[].id), not messageId. Did you mean to pass fileId? messageId is the Slack message timestamp and is used by react / reactions / edit / delete / pin / unpin actions, not download-file.");
338
- const fileId = readStringParam$1(actionParams, "fileId", { required: true });
339
- const channelId = readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to");
340
- const threadId = readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo");
341
- return await invokeSlackAction({
342
- action: "downloadFile",
343
- fileId,
344
- channelId: channelId ?? void 0,
345
- threadId: threadId ?? void 0
346
- });
347
- }
348
- if (action === "upload-file") {
349
- if (readBooleanParam(actionParams, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
350
- const to = readStringParam$1(actionParams, "to") ?? resolveChannelId();
351
- const filePath = readStringParam$1(actionParams, "filePath", { trim: false }) ?? readStringParam$1(actionParams, "path", { trim: false }) ?? readStringParam$1(actionParams, "media", { trim: false });
352
- if (!filePath) throw new Error("upload-file requires filePath, path, or media");
353
- const threadId = readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo");
354
- const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
355
- return await invokeSlackAction({
356
- action: "uploadFile",
357
- to,
358
- filePath,
359
- initialComment: readStringParam$1(actionParams, "initialComment", { allowEmpty: true }) ?? readStringParam$1(actionParams, "message", { allowEmpty: true }) ?? readStringParam$1(actionParams, "caption", { allowEmpty: true }) ?? "",
360
- filename: readStringParam$1(actionParams, "filename"),
361
- title: readStringParam$1(actionParams, "title"),
362
- threadTs: threadId ?? void 0,
363
- ...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
364
- ...topLevel ? { topLevel: true } : {}
365
- });
366
- }
367
- throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
368
- }
369
- // extensions/slack/src/channel-actions.ts
370
207
  const SLACK_TOOL_DELIVERY_ACTIONS = /* @__PURE__ */ new Set([
371
208
  "deleteMessage",
372
209
  "editMessage",
@@ -376,7 +213,7 @@ const SLACK_TOOL_DELIVERY_ACTIONS = /* @__PURE__ */ new Set([
376
213
  "unpinMessage",
377
214
  "uploadFile"
378
215
  ]);
379
- const loadSlackActionRuntime$1 = createLazyRuntimeModule(() => import("./action-runtime.runtime-DWKWaKgC.mjs"));
216
+ const loadSlackActionRuntime = createLazyRuntimeModule(() => import("./action-runtime.runtime-CpZktret.mjs"));
380
217
  function resolveSlackActionContext(ctx, toolContext) {
381
218
  if (!toolContext && !ctx.mediaAccess && !ctx.mediaLocalRoots && !ctx.mediaReadFile && !ctx.conversationReadOrigin && !ctx.requesterAccountId && !ctx.requesterSenderId && !ctx.assertDirectAdapterHandoff) return;
382
219
  return {
@@ -406,14 +243,187 @@ function createSlackActions(providerId, options) {
406
243
  isToolDeliveryAction: ({ args }) => typeof args.action === "string" && SLACK_TOOL_DELIVERY_ACTIONS.has(args.action),
407
244
  prepareSendPayload: ({ ctx, to, payload }) => ctx.action === "send" && !shouldUseWorkspaceAwareSlackActionSend(to, ctx.toolContext) ? payload : null,
408
245
  handleAction: async (ctx) => {
409
- return await handleSlackMessageAction({
410
- providerId,
411
- ctx,
412
- invoke: async (action, cfg, toolContext) => {
413
- const actionContext = resolveSlackActionContext(ctx, toolContext);
414
- return await (options?.invoke ? options.invoke(action, cfg, actionContext) : (await loadSlackActionRuntime$1()).handleSlackAction(action, cfg, actionContext));
415
- }
246
+ const { action, cfg, params: actionParams } = ctx;
247
+ const accountId = ctx.accountId ?? void 0;
248
+ const invokeSlackAction = async (request, toolContext = ctx.toolContext) => {
249
+ const requestAction = {
250
+ ...request,
251
+ accountId
252
+ };
253
+ const actionContext = resolveSlackActionContext(ctx, toolContext);
254
+ return await (options?.invoke ? options.invoke(requestAction, cfg, actionContext) : (await loadSlackActionRuntime()).handleSlackAction(requestAction, cfg, actionContext));
255
+ };
256
+ const resolveChannelId = () => {
257
+ const raw = readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to", { required: true });
258
+ const target = parseSlackTarget(raw, { defaultKind: "channel" });
259
+ const channelId = resolveSlackChannelId(raw);
260
+ return formatSlackTarget({
261
+ teamId: target?.teamId,
262
+ kind: "channel",
263
+ id: channelId
264
+ });
265
+ };
266
+ if (action === "channel-create") return await invokeSlackAction({
267
+ action: "createChannel",
268
+ name: readStringParam$1(actionParams, "name", { required: true }),
269
+ teamId: readStringParam$1(actionParams, "teamId")
416
270
  });
271
+ if (action === "conversation-open") return await invokeSlackAction({
272
+ action: "openConversation",
273
+ userIds: actionParams.userIds,
274
+ teamId: readStringParam$1(actionParams, "teamId")
275
+ });
276
+ if (action === "send") {
277
+ const to = readStringParam$1(actionParams, "to", { required: true });
278
+ const content = readStringParam$1(actionParams, "message", {
279
+ required: false,
280
+ allowEmpty: true
281
+ });
282
+ const mediaUrl = readStringParam$1(actionParams, "media", { trim: false });
283
+ const presentation = normalizeMessagePresentation(actionParams.presentation);
284
+ const interactive = normalizeLegacyInteractiveReply(actionParams.interactive);
285
+ const hasStructuredContent = Boolean(presentation || interactive?.blocks.length);
286
+ const resolution = resolveSlackReplyBlockResolution({
287
+ text: content,
288
+ presentation,
289
+ interactive
290
+ }, {
291
+ ...resolveSlackMarkdownOptions({
292
+ cfg,
293
+ accountId
294
+ }),
295
+ materializeAuthoredText: hasStructuredContent
296
+ });
297
+ const preparedMessages = resolution.segments.length > 0 ? resolveSlackReplyDeliveryMessages({
298
+ authoredTextPlacement: resolution.authoredTextPlacement,
299
+ segments: resolution.segments,
300
+ text: content
301
+ }) : [];
302
+ if (!content && preparedMessages.length === 0 && !mediaUrl) throw new Error("Slack send requires message, blocks, or media.");
303
+ const replyBroadcast = readBooleanParam(actionParams, "replyBroadcast");
304
+ if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
305
+ const threadId = readStringParam$1(actionParams, "threadId");
306
+ const replyTo = readStringParam$1(actionParams, "replyTo");
307
+ const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
308
+ const toolContext = preparedMessages.length > 0 ? {
309
+ ...ctx.toolContext,
310
+ preparedMessages
311
+ } : ctx.toolContext;
312
+ return await invokeSlackAction({
313
+ action: "sendMessage",
314
+ to,
315
+ content: content ?? "",
316
+ mediaUrl,
317
+ ...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
318
+ threadTs: resolveSlackThreadTsValue({
319
+ replyToId: replyTo,
320
+ threadId
321
+ }),
322
+ ...topLevel ? { topLevel: true } : {},
323
+ ...replyBroadcast ? { replyBroadcast } : {}
324
+ }, toolContext);
325
+ }
326
+ if (action === "react") {
327
+ const messageIdRaw = resolveReactionMessageId({
328
+ args: actionParams,
329
+ toolContext: ctx.toolContext
330
+ });
331
+ if (messageIdRaw == null) throw new Error("messageId required. Provide messageId explicitly or react to the current inbound message.");
332
+ const messageId = String(messageIdRaw);
333
+ const emoji = readStringParam$1(actionParams, "emoji", { allowEmpty: true });
334
+ const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : void 0;
335
+ return await invokeSlackAction({
336
+ action: "react",
337
+ channelId: resolveChannelId(),
338
+ messageId,
339
+ emoji,
340
+ remove
341
+ });
342
+ }
343
+ const messageAction = SLACK_MESSAGE_ACTIONS.get(action);
344
+ if (messageAction) {
345
+ const messageId = action === "list-pins" ? void 0 : readStringParam$1(actionParams, "messageId", { required: true });
346
+ return await invokeSlackAction({
347
+ action: messageAction,
348
+ channelId: resolveChannelId(),
349
+ messageId,
350
+ ...action === "reactions" ? { limit: actionParams.limit } : {}
351
+ });
352
+ }
353
+ if (action === "read") return await invokeSlackAction({
354
+ action: "readMessages",
355
+ channelId: resolveChannelId(),
356
+ limit: actionParams.limit,
357
+ before: readStringParam$1(actionParams, "before"),
358
+ after: readStringParam$1(actionParams, "after"),
359
+ messageId: readStringParam$1(actionParams, "messageId"),
360
+ threadId: readStringParam$1(actionParams, "threadId")
361
+ });
362
+ if (action === "edit") {
363
+ const messageId = readStringParam$1(actionParams, "messageId", { required: true });
364
+ const { blocks, text: accessibleContent, usesPresentationTextFallback } = renderSlackActionPresentation(readStringParam$1(actionParams, "message", { allowEmpty: true }), normalizeMessagePresentation(actionParams.presentation), resolveSlackMarkdownOptions({
365
+ cfg,
366
+ accountId
367
+ }));
368
+ if (!blocks && countSlackTextUtf8Bytes(accessibleContent) > 4e3) throw new Error(`${usesPresentationTextFallback ? "Slack presentation fallback" : "Slack edit"} exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`);
369
+ if (!accessibleContent && !blocks) throw new Error("Slack edit requires message or blocks.");
370
+ return await invokeSlackAction({
371
+ action: "editMessage",
372
+ channelId: resolveChannelId(),
373
+ messageId,
374
+ content: accessibleContent,
375
+ blocks
376
+ }, {
377
+ ...ctx.toolContext,
378
+ preparedEditText: accessibleContent
379
+ });
380
+ }
381
+ if (action === "member-info") {
382
+ const requesterAccountId = ctx.requesterAccountId ? normalizeAccountId(ctx.requesterAccountId) : void 0;
383
+ const targetAccountId = normalizeAccountId(accountId ?? resolveDefaultSlackAccountId(cfg));
384
+ const requesterUserId = normalizeOptionalLowercaseString(ctx.toolContext?.currentChannelProvider) === "slack" && requesterAccountId !== void 0 && requesterAccountId === targetAccountId ? normalizeOptionalString(ctx.requesterSenderId) : void 0;
385
+ const userId = readStringParam$1(actionParams, "userId") ?? requesterUserId;
386
+ if (!userId) throw new Error("member-info requires a userId outside a current Slack conversation.");
387
+ return await invokeSlackAction({
388
+ action: "memberInfo",
389
+ userId
390
+ });
391
+ }
392
+ if (action === "emoji-list") return await invokeSlackAction({
393
+ action: "emojiList",
394
+ limit: readPositiveIntegerParam$1(actionParams, "limit", { message: "limit must be a positive integer." })
395
+ });
396
+ if (action === "download-file") {
397
+ const fileIdParam = readStringParam$1(actionParams, "fileId");
398
+ const messageIdParam = readStringParam$1(actionParams, "messageId") ?? readStringParam$1(actionParams, "message_id");
399
+ if (!fileIdParam && messageIdParam) throw new Error("download-file requires fileId (the Slack file id, for example F0B0LTT8M36 from event.files[].id), not messageId. Did you mean to pass fileId? messageId is the Slack message timestamp and is used by react / reactions / edit / delete / pin / unpin actions, not download-file.");
400
+ return await invokeSlackAction({
401
+ action: "downloadFile",
402
+ fileId: fileIdParam ?? readStringParam$1(actionParams, "fileId", { required: true }),
403
+ channelId: readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to"),
404
+ threadId: readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo")
405
+ });
406
+ }
407
+ if (action === "upload-file") {
408
+ if (readBooleanParam(actionParams, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
409
+ const to = readStringParam$1(actionParams, "to") ?? resolveChannelId();
410
+ const filePath = readStringParam$1(actionParams, "filePath", { trim: false }) ?? readStringParam$1(actionParams, "path", { trim: false }) ?? readStringParam$1(actionParams, "media", { trim: false });
411
+ if (!filePath) throw new Error("upload-file requires filePath, path, or media");
412
+ const threadId = readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo");
413
+ const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
414
+ return await invokeSlackAction({
415
+ action: "uploadFile",
416
+ to,
417
+ filePath,
418
+ initialComment: readStringParam$1(actionParams, "initialComment", { allowEmpty: true }) ?? readStringParam$1(actionParams, "message", { allowEmpty: true }) ?? readStringParam$1(actionParams, "caption", { allowEmpty: true }) ?? "",
419
+ filename: readStringParam$1(actionParams, "filename"),
420
+ title: readStringParam$1(actionParams, "title"),
421
+ threadTs: threadId,
422
+ ...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
423
+ ...topLevel ? { topLevel: true } : {}
424
+ });
425
+ }
426
+ throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
417
427
  }
418
428
  };
419
429
  }
@@ -429,9 +439,9 @@ function shouldUseWorkspaceAwareSlackActionSend(rawTarget, context) {
429
439
  }
430
440
  // extensions/slack/src/conversation-route-owner.ts
431
441
  function prepareSlackConversationRouteOwner(params) {
432
- const accountId = normalizeAccountId(params.accountId);
442
+ const accountId = normalizeAccountId$2(params.accountId);
433
443
  const accountConfig = resolveAccountEntry(params.cfg.channels?.slack?.accounts, accountId);
434
- if (params.cfg.channels?.slack?.enabled === false || accountConfig?.enabled === false || !accountConfig && (accountId !== DEFAULT_ACCOUNT_ID || !hasImplicitDefaultSlackAccount(params.cfg))) return {
444
+ if (params.cfg.channels?.slack?.enabled === false || accountConfig?.enabled === false || !accountConfig && (accountId !== DEFAULT_ACCOUNT_ID$1 || !hasImplicitDefaultSlackAccount(params.cfg))) return {
435
445
  kind: "terminal",
436
446
  owner: null
437
447
  };
@@ -513,7 +523,7 @@ function prepareSlackConversationRouteOwner(params) {
513
523
  }
514
524
  };
515
525
  }
516
- async function prepareSlackConversationRouteOwnersAsync(inputs, inspectBindings) {
526
+ const slackConversationRouteOwners = { prepareConversationRouteOwnersAsync: async (inputs, inspectBindings) => {
517
527
  const prepared = inputs.map(prepareSlackConversationRouteOwner);
518
528
  const inspect = await inspectBindings(prepared.flatMap((item) => item.kind === "prepared" && item.route.bindingsEnabled ? [{
519
529
  channel: "slack",
@@ -546,8 +556,7 @@ async function prepareSlackConversationRouteOwnersAsync(inputs, inspectBindings)
546
556
  thread: thread()
547
557
  });
548
558
  });
549
- }
550
- const slackConversationRouteOwners = { prepareConversationRouteOwnersAsync: prepareSlackConversationRouteOwnersAsync };
559
+ } };
551
560
  // extensions/slack/src/enterprise-user-route.ts
552
561
  /** Resolve a workspace for a detached Enterprise DM without opening a conversation. */
553
562
  async function resolveSlackEnterpriseUserTeamId(params) {
@@ -573,6 +582,244 @@ async function resolveSlackEnterpriseUserTeamId(params) {
573
582
  if (!teamId) throw new Error("unsupported_enterprise_slack_delivery: recipient shares no verified installed workspace");
574
583
  return teamId;
575
584
  }
585
+ // extensions/slack/src/security.ts
586
+ const resolveSlackDmPolicy = createScopedDmSecurityResolver({
587
+ channelKey: "slack",
588
+ resolvePolicy: (account) => account.config.dmPolicy,
589
+ resolveAllowFrom: (account) => account.config.allowFrom,
590
+ resolveAccess: ({ cfg, account }) => ({
591
+ dmPolicy: resolveSlackAccountDmPolicy({
592
+ cfg,
593
+ accountId: account.accountId
594
+ }),
595
+ allowFrom: resolveSlackAccountAllowFrom({
596
+ cfg,
597
+ accountId: account.accountId
598
+ })
599
+ }),
600
+ policyPathSuffix: "dmPolicy",
601
+ classifyEntryAuthentication: identityEntryAuthenticationClassifier(slackIngressIdentity),
602
+ normalizeEntry: (raw) => raw.trim().replace(/^(slack|user):/i, "").trim()
603
+ });
604
+ const collectSlackSecurityWarnings = createOpenProviderConfiguredRouteWarningCollector({
605
+ providerConfigPresent: (cfg) => cfg.channels?.slack !== void 0,
606
+ resolveGroupPolicy: (account) => account.config.groupPolicy,
607
+ resolveRouteAllowlistConfigured: (account) => Boolean(account.config.channels) && Object.keys(account.config.channels ?? {}).length > 0,
608
+ configureRouteAllowlist: {
609
+ surface: "Slack channels",
610
+ openScope: "any channel not explicitly denied",
611
+ groupPolicyPath: "channels.slack.groupPolicy",
612
+ routeAllowlistPath: "channels.slack.channels"
613
+ },
614
+ missingRouteAllowlist: {
615
+ surface: "Slack channels",
616
+ openBehavior: "with no channel allowlist; any channel can trigger (mention-gated)",
617
+ remediation: "Set channels.slack.groupPolicy=\"allowlist\" and configure channels.slack.channels"
618
+ }
619
+ });
620
+ const collectSlackSecurityFindings = createConditionalWarningCollector.findings({
621
+ collectWarnings: collectSlackSecurityWarnings,
622
+ checkId: "channels.slack.groups.open",
623
+ severity: "warn",
624
+ title: "Slack security warning"
625
+ });
626
+ const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-C3hXCfDt.mjs").then((n) => n.n));
627
+ const slackSecurityAdapter = {
628
+ resolveDmPolicy: resolveSlackDmPolicy,
629
+ collectWarnings: collectSlackSecurityFindings,
630
+ collectAuditFindings: async (params) => {
631
+ const { collectSlackSecurityAuditFindings } = await loadSlackSecurityAuditModule();
632
+ return await collectSlackSecurityAuditFindings(params);
633
+ }
634
+ };
635
+ // extensions/slack/src/doctor.ts
636
+ const isSlackMutableUnqualifiedAllowEntry = buildMutableAllowEntryDetector({ stableIdPattern: /^(?:(?:(?:[sS][lL][aA][cC][kK]|[uU][sS][eE][rR]):)?(?:[UWBCGDT][A-Z0-9]{2,}|[A-Za-z0-9]{8,})|<@[A-Za-z0-9]{8,}>)$/ });
637
+ const collectSlackMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
638
+ channel: "slack",
639
+ detector: (entry) => {
640
+ if (/^team:/i.test(entry)) try {
641
+ const target = parseSlackTarget(entry);
642
+ if (target?.kind === "user" && target.teamId) return false;
643
+ } catch {}
644
+ return isSlackMutableUnqualifiedAllowEntry(entry);
645
+ },
646
+ collectLists: (scope) => collectStandardAllowlistLists(scope, {
647
+ includeGroupAllowFrom: false,
648
+ includeDm: true,
649
+ includeGroups: true,
650
+ groupsKey: "channels",
651
+ groupField: "users"
652
+ })
653
+ });
654
+ const SLACK_CANONICAL_CHANNEL_ID_RE = /^(?:channel:)?[CG][A-Z0-9]{8,}$/;
655
+ const SLACK_LOWERCASE_CHANNEL_ID_RE = /^(?:channel:)?[cg][0-9][a-z0-9]{7,}$/;
656
+ const SLACK_CANONICAL_DM_ID_RE = /^(?:channel:)?D[A-Z0-9]{8,}$/;
657
+ const SLACK_PREFIXED_LOWERCASE_DM_ID_RE = /^channel:d[a-z0-9]{8,}$/;
658
+ const SLACK_AMBIGUOUS_LOWERCASE_DM_ID_RE = /^d[a-z0-9]{8,}$/;
659
+ const SLACK_AMBIGUOUS_LOWERCASE_CHANNEL_ID_RE = /^(?:channel:)?[cgd][a-z][a-z0-9]{7,}$/;
660
+ const SLACK_CHANNEL_NAME_RE = /^[\p{L}\p{M}\p{N}_-]{1,80}$/u;
661
+ const SLACK_CHANNEL_NAME_ALPHANUMERIC_RE = /[\p{L}\p{N}]/u;
662
+ function looksLikeSlackChannelId(channelKey) {
663
+ const workspaceChannelId = parseWorkspaceQualifiedChannelId(channelKey);
664
+ return workspaceChannelId !== void 0 && /^[CG]/i.test(workspaceChannelId) || SLACK_CANONICAL_CHANNEL_ID_RE.test(channelKey) || SLACK_LOWERCASE_CHANNEL_ID_RE.test(channelKey);
665
+ }
666
+ function looksLikeSlackDmId(channelKey) {
667
+ const workspaceChannelId = parseWorkspaceQualifiedChannelId(channelKey);
668
+ return workspaceChannelId !== void 0 && /^D/i.test(workspaceChannelId) || SLACK_CANONICAL_DM_ID_RE.test(channelKey) || SLACK_PREFIXED_LOWERCASE_DM_ID_RE.test(channelKey);
669
+ }
670
+ function parseWorkspaceQualifiedChannelId(channelKey) {
671
+ if (!/^team:/i.test(channelKey)) return;
672
+ try {
673
+ const target = parseSlackTarget(channelKey);
674
+ return target?.kind === "channel" && target.teamId ? target.id : void 0;
675
+ } catch {
676
+ return;
677
+ }
678
+ }
679
+ function looksLikeSlackChannelNameKey(channelKey) {
680
+ const name = channelKey.startsWith("#") ? channelKey.slice(1) : channelKey;
681
+ return name === name.toLowerCase() && SLACK_CHANNEL_NAME_RE.test(name) && SLACK_CHANNEL_NAME_ALPHANUMERIC_RE.test(name);
682
+ }
683
+ function collectSlackNameKeyedChannelWarnings({ cfg }) {
684
+ const warnings = /* @__PURE__ */ new Set();
685
+ const slackCfg = (0, runtime_doctor_migrations_exports.asObjectRecord)((0, runtime_doctor_migrations_exports.asObjectRecord)(cfg.channels)?.slack);
686
+ const providerChannels = (0, runtime_doctor_migrations_exports.asObjectRecord)(slackCfg?.channels);
687
+ const accounts = (0, runtime_doctor_migrations_exports.asObjectRecord)(slackCfg?.accounts);
688
+ for (const accountId of listSlackAccountIds(cfg)) {
689
+ const account = (0, runtime_doctor_migrations_exports.asObjectRecord)(mergeSlackAccountConfig(cfg, accountId));
690
+ if (!account || slackCfg?.enabled === false || account.enabled === false) continue;
691
+ const effectiveGroupPolicy = (typeof account.groupPolicy === "string" ? account.groupPolicy : void 0) ?? "allowlist";
692
+ const rawAccount = (0, runtime_doctor_migrations_exports.asObjectRecord)(accounts?.[accountId]);
693
+ const accountPrefix = rawAccount ? `channels.slack.accounts.${accountId}` : "channels.slack";
694
+ const accountChannels = (0, runtime_doctor_migrations_exports.asObjectRecord)(rawAccount?.channels);
695
+ const channels = accountChannels ?? providerChannels;
696
+ if (!channels) continue;
697
+ const channelsPrefix = accountChannels ? `channels.slack.accounts.${accountId}` : "channels.slack";
698
+ const fallbackDescription = Object.hasOwn(channels, "*") ? `${channelsPrefix}.channels."*" applies instead and this entry's overrides are ignored` : effectiveGroupPolicy === "open" ? "this entry's overrides are ignored and the channel remains allowed by groupPolicy: \"open\"" : "messages from the channel are dropped";
699
+ for (const channelKey of Object.keys(channels)) {
700
+ if (channelKey === "*") continue;
701
+ if (looksLikeSlackDmId(channelKey)) {
702
+ warnings.add(`${channelsPrefix}.channels."${channelKey}" is a Slack DM conversation ID, but ${channelsPrefix}.channels only configures channel and group rooms. Configure DM access with ${accountPrefix}.dmPolicy and ${accountPrefix}.allowFrom instead.`);
703
+ continue;
704
+ }
705
+ if (SLACK_AMBIGUOUS_LOWERCASE_DM_ID_RE.test(channelKey)) {
706
+ if (account.dangerouslyAllowNameMatching === true && looksLikeSlackChannelNameKey(channelKey)) continue;
707
+ warnings.add(`${channelsPrefix}.channels."${channelKey}" is ambiguous: it may be a lowercase Slack DM conversation ID or a channel name. Configure DMs with ${accountPrefix}.dmPolicy and ${accountPrefix}.allowFrom; otherwise re-key the room with its stable C/G ID.`);
708
+ continue;
709
+ }
710
+ if (effectiveGroupPolicy === "disabled") continue;
711
+ const channelConfig = (0, runtime_doctor_migrations_exports.asObjectRecord)(channels[channelKey]);
712
+ if (effectiveGroupPolicy === "open" && Object.keys(channelConfig ?? {}).length === 0) continue;
713
+ if (looksLikeSlackChannelId(channelKey)) continue;
714
+ if (account.dangerouslyAllowNameMatching === true && looksLikeSlackChannelNameKey(channelKey)) continue;
715
+ if (SLACK_AMBIGUOUS_LOWERCASE_CHANNEL_ID_RE.test(channelKey)) {
716
+ warnings.add(`${channelsPrefix}.channels."${channelKey}" is ambiguous: it may be a lowercase Slack channel ID or a channel name. If it is a channel name, inbound routing will not match it and ${fallbackDescription}. Re-key it with the channel's stable ID (e.g. C0123ABCD, from the channel's About details or conversations.info).`);
717
+ continue;
718
+ }
719
+ warnings.add(`${channelsPrefix}.channels."${channelKey}" is keyed by a channel name or unsupported ID form, not a routable Slack channel ID; under groupPolicy: "${effectiveGroupPolicy}" inbound routing does not match this entry, so ${fallbackDescription}. Re-key it with the channel's ID (e.g. C0123ABCD, from the channel's About details or conversations.info).`);
720
+ }
721
+ }
722
+ return [...warnings];
723
+ }
724
+ async function collectSlackUserIdentityWarnings(params) {
725
+ const warnings = [];
726
+ for (const accountId of listSlackAccountIds(params.cfg)) {
727
+ const account = inspectSlackAccount({
728
+ cfg: params.cfg,
729
+ accountId,
730
+ envBotToken: params.env?.SLACK_BOT_TOKEN,
731
+ envAppToken: params.env?.SLACK_APP_TOKEN,
732
+ envUserToken: params.env?.SLACK_USER_TOKEN
733
+ });
734
+ if (!account.enabled || account.identity !== "user") continue;
735
+ const path = accountId === "default" ? "channels.slack" : `channels.slack.accounts.${accountId}`;
736
+ const mode = account.mode ?? "socket";
737
+ if (mode === "socket" && account.appTokenStatus === "missing") warnings.push(`- ${path}: identity "user" in Socket Mode requires appToken for companion-app events.`);
738
+ else if (mode === "http" && account.signingSecretStatus === "missing") warnings.push(`- ${path}: identity "user" in HTTP mode requires signingSecret for companion-app events.`);
739
+ if (!account.userToken) {
740
+ warnings.push(account.userTokenStatus === "configured_unavailable" ? `- ${path}: userToken is configured but unavailable; Slack auth.test validation was skipped.` : `- ${path}: identity "user" requires userToken for the authorizing human.`);
741
+ continue;
742
+ }
743
+ const probe = await probeSlack(account.userToken, 2500, {
744
+ accountId,
745
+ identity: "user"
746
+ });
747
+ if (!probe.ok) {
748
+ warnings.push(`- ${path}: userToken auth.test failed: ${probe.error ?? "unknown error"}.`);
749
+ continue;
750
+ }
751
+ const userId = probe.user?.id?.trim();
752
+ const userName = probe.user?.name?.trim();
753
+ if (!userId) {
754
+ warnings.push(`- ${path}: userToken auth.test succeeded but returned no human user_id.`);
755
+ continue;
756
+ }
757
+ warnings.push(`- ${path}: user identity authenticated as ${userName ? `@${userName} ` : ""}(${userId}).`);
758
+ }
759
+ return warnings;
760
+ }
761
+ const slackDoctor = {
762
+ dmAllowFromMode: "topOnly",
763
+ groupModel: "route",
764
+ groupAllowFromFallbackToAllowFrom: false,
765
+ warnOnEmptyGroupSenderAllowlist: false,
766
+ legacyConfigRules,
767
+ normalizeCompatibilityConfig,
768
+ collectPreviewWarnings: collectSlackUserIdentityWarnings,
769
+ collectMutableAllowlistWarnings: ({ cfg }) => [...collectSlackMutableAllowlistWarnings({ cfg }), ...collectSlackNameKeyedChannelWarnings({ cfg })]
770
+ };
771
+ // extensions/slack/src/shared.ts
772
+ const slackConfigAdapter = {
773
+ ...slackBaseConfigAdapter,
774
+ inspectAccount: adaptScopedAccountAccessor(inspectSlackAccount)
775
+ };
776
+ const slackPluginBase = {
777
+ ...slackSetupPlugin,
778
+ meta: {
779
+ ...SLACK_CHANNEL_META,
780
+ preferSessionLookupForAnnounceTarget: true
781
+ },
782
+ doctor: slackDoctor,
783
+ agentPrompt: {
784
+ questionInputMode: "buttons",
785
+ customInlineButtonHint: true,
786
+ inboundFormattingHints: () => ({
787
+ text_markup: "markdown",
788
+ rules: [
789
+ "Write replies in standard Markdown; OpenClaw converts them to Slack mrkdwn.",
790
+ "Bold uses **double asterisks**; *single asterisks* or _underscores_ produce italics.",
791
+ "Links use [label](url). Keep Slack mentions as <@USER_ID>.",
792
+ "Use presentation table blocks for tabular data; Markdown pipe tables are not auto-promoted.",
793
+ "Only raw Block Kit or presentation text fields use Slack mrkdwn directly: *bold*, _italic_, ~strike~, and <url|label> links. Avoid Markdown headings or pipe tables in those fields."
794
+ ]
795
+ }),
796
+ messageToolHints: () => [
797
+ "- Use `presentation` buttons/selects for discrete choices or parameter picks instead of asking the user to type one.",
798
+ "- For line, bar, area, or pie data, use a `presentation` chart block; Slack renders it as a native chart and retains a text data summary for accessibility.",
799
+ "- For row-and-column data, use an explicit `presentation` table block; Slack renders it as a native table and retains a linear text summary for accessibility. Markdown pipe tables are not auto-promoted.",
800
+ "- Slack plain text sends: write standard Markdown; OpenClaw converts it to Slack mrkdwn, including `**bold**`, headings, lists, and `[label](url)` links.",
801
+ "- When mentioning Slack users, use the stable `<@USER_ID>` token from Slack context instead of plain `@name` text so Slack notifies and links the user.",
802
+ "- Slack Block Kit or presentation text fields are sent as Slack mrkdwn directly; use `*bold*`, `_italic_`, `~strike~`, `<url|label>` links, and avoid Markdown headings or pipe tables there."
803
+ ]
804
+ },
805
+ config: {
806
+ ...slackSetupPlugin.config,
807
+ ...slackConfigAdapter,
808
+ isConfigured: isSlackPluginAccountConfigured,
809
+ describeAccount: (account) => describeAccountSnapshot({
810
+ account,
811
+ configured: isSlackPluginAccountConfigured(account),
812
+ extra: {
813
+ botTokenSource: account.botTokenSource,
814
+ appTokenSource: account.appTokenSource
815
+ }
816
+ })
817
+ },
818
+ secrets: {
819
+ secretTargetRegistryEntries,
820
+ collectRuntimeConfigAssignments
821
+ }
822
+ };
576
823
  // extensions/slack/src/threading-tool-context.ts
577
824
  function buildSlackThreadingToolContext(params) {
578
825
  const account = resolveSlackAccount({
@@ -606,20 +853,16 @@ function buildSlackThreadingToolContext(params) {
606
853
  // extensions/slack/src/channel.ts
607
854
  const loadExtensionSharedSdk = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/extension-shared"));
608
855
  const loadTargetResolverRuntimeSdk = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/target-resolver-runtime"));
609
- const loadSlackScopesModule = createLazyRuntimeModule(() => import("./scopes-C1aeCBa6.mjs"));
610
- const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-C0R5jz6S.mjs"));
856
+ const loadSlackScopesModule = createLazyRuntimeModule(() => import("./scopes-CzHC_dwV.mjs"));
857
+ const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-BH6iPWBj.mjs"));
611
858
  const bindSlackOutbound = createLazyRuntimeMethodBinder(loadSlackOutboundAdapterModule);
612
- async function resolveSlackHandleAction() {
613
- return getOptionalSlackRuntime()?.channel?.slack?.handleSlackAction ?? (await loadSlackActionRuntime()).handleSlackAction;
614
- }
615
- const loadSlackDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-BEPra1E2.mjs").then((n) => n.t));
616
- const loadSlackResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-BNQ1KZXh.mjs").then((n) => n.n));
617
- const loadSlackResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-C4dC8Z7D.mjs").then((n) => n.n));
618
- const loadSlackActionRuntime = createLazyRuntimeModule(() => import("./action-runtime.runtime-DWKWaKgC.mjs"));
619
- const loadSlackSendRuntime = createLazyRuntimeModule(() => import("./send-C5uXkmZV.mjs").then((n) => n.n));
620
- const loadSlackProbeModule = createLazyRuntimeModule(() => import("./probe-C5VWf3sz.mjs").then((n) => n.n));
621
- const loadSlackMonitorModule = createLazyRuntimeModule(() => import("./monitor-DsZUQtTM.mjs").then((n) => n.t));
622
- const loadSlackDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-BkUwPrS0.mjs").then((n) => n.t));
859
+ const loadSlackDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-CGvKYg9F.mjs").then((n) => n.t));
860
+ const loadSlackResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-CF2JME9q.mjs").then((n) => n.n));
861
+ const loadSlackResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-DDcCAjH1.mjs").then((n) => n.n));
862
+ const loadSlackSendRuntime = createLazyRuntimeModule(() => import("./send-WJZ73VSf.mjs").then((n) => n.n));
863
+ const loadSlackProbeModule = createLazyRuntimeModule(() => import("./probe-B_Ax1vS1.mjs").then((n) => n.n));
864
+ const loadSlackMonitorModule = createLazyRuntimeModule(() => import("./monitor-BD86SotB.mjs").then((n) => n.t));
865
+ const loadSlackDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-DNdw97LA.mjs").then((n) => n.t));
623
866
  async function setSlackHeartbeatThreadStatus(params) {
624
867
  const threadTs = resolveSlackThreadTsValue({ threadId: params.threadId });
625
868
  const target = parseSlackTarget(params.to, { defaultKind: "channel" });
@@ -666,106 +909,6 @@ function normalizeSlackAcpConversationId(raw) {
666
909
  const conversationId = normalizeLowercaseStringOrEmpty(parsed?.id ?? trimmed.replace(/^slack:/i, "").replace(/^(?:channel|group|direct|user):/i, ""));
667
910
  return conversationId ? { conversationId } : null;
668
911
  }
669
- function matchSlackAcpConversation(params) {
670
- const bindingConversationId = normalizeSlackAcpConversationId(params.bindingConversationId)?.conversationId;
671
- const conversationId = normalizeSlackAcpConversationId(params.conversationId)?.conversationId;
672
- const parentConversationId = normalizeSlackAcpConversationId(params.parentConversationId)?.conversationId;
673
- if (!bindingConversationId || !conversationId) return null;
674
- if (bindingConversationId === conversationId) return {
675
- conversationId,
676
- matchPriority: 2
677
- };
678
- if (parentConversationId && parentConversationId !== conversationId && bindingConversationId === parentConversationId) return {
679
- conversationId: parentConversationId,
680
- matchPriority: 1
681
- };
682
- return null;
683
- }
684
- async function resolveSlackOutboundSessionRoute(params) {
685
- const parsed = parseSlackTarget(params.target, { defaultKind: "channel" });
686
- if (!parsed) return null;
687
- const apiTargetId = canonicalizeSlackApiTargetId(parsed.kind, parsed.id, params.target);
688
- const isDm = parsed.kind === "user";
689
- if (params.deliveryPurpose === "heartbeat-owner" && isDm && !parsed.teamId && /^[UW][A-Z0-9]{8,}$/.test(apiTargetId)) {
690
- const teamId = await resolveSlackEnterpriseUserTeamId({
691
- cfg: params.cfg,
692
- accountId: params.accountId,
693
- userId: apiTargetId
694
- });
695
- if (teamId) {
696
- parsed.teamId = teamId;
697
- parsed.id = apiTargetId;
698
- }
699
- }
700
- let peerKind = isDm ? "direct" : "channel";
701
- let peerId = formatSlackTarget(parsed);
702
- let recipientSessionExact = isDm ? /^[UW][A-Z0-9]{8,}$/i.test(parsed.id) : /^C[A-Z0-9]{8,}$/i.test(parsed.id);
703
- if (!isDm && /^D/i.test(parsed.id)) {
704
- const conversation = await resolveSlackConversationInfo({
705
- cfg: params.cfg,
706
- accountId: params.accountId,
707
- channelId: apiTargetId,
708
- teamId: parsed.teamId
709
- });
710
- if (conversation.type !== "dm" || !conversation.user) return null;
711
- peerKind = "direct";
712
- peerId = formatSlackTarget({
713
- teamId: parsed.teamId,
714
- kind: "user",
715
- id: conversation.user
716
- });
717
- recipientSessionExact = true;
718
- } else if (!isDm && /^G/i.test(parsed.id)) {
719
- const channelType = await resolveSlackChannelType({
720
- cfg: params.cfg,
721
- accountId: params.accountId,
722
- channelId: apiTargetId,
723
- teamId: parsed.teamId
724
- });
725
- if (channelType === "group") peerKind = "group";
726
- if (channelType === "dm") peerKind = "direct";
727
- recipientSessionExact = channelType !== "unknown";
728
- }
729
- const peer = {
730
- kind: peerKind,
731
- id: peerId
732
- };
733
- const unpartitionedBaseSessionKey = buildOutboundBaseSessionKey({
734
- channel: "slack",
735
- cfg: params.cfg,
736
- agentId: params.agentId,
737
- accountId: params.accountId,
738
- peer
739
- });
740
- const baseSessionKey = parsed.teamId && peerKind === "direct" && (params.cfg.session?.dmScope ?? "main") === "main" ? `${unpartitionedBaseSessionKey}:account:${encodeURIComponent(resolveSlackAccount({
741
- cfg: params.cfg,
742
- accountId: params.accountId
743
- }).accountId).toLowerCase()}:team:${encodeURIComponent(parsed.teamId).toLowerCase()}` : unpartitionedBaseSessionKey;
744
- return buildThreadAwareOutboundSessionRoute({
745
- route: {
746
- sessionKey: baseSessionKey,
747
- baseSessionKey,
748
- recipientSessionExact,
749
- peer,
750
- chatType: peerKind === "direct" ? "direct" : "channel",
751
- from: peerKind === "direct" ? `slack:${peerId}` : peerKind === "group" ? `slack:group:${peerId}` : `slack:channel:${peerId}`,
752
- to: parsed.teamId ? peerId : peerKind === "direct" ? `user:${peerId}` : `channel:${peerId}`
753
- },
754
- replyToId: params.replyToId,
755
- threadId: params.threadId,
756
- currentSessionKey: params.currentSessionKey,
757
- canRecoverCurrentThread: () => peerKind !== "direct" || (params.cfg.session?.dmScope ?? "main") !== "main"
758
- });
759
- }
760
- function formatSlackScopeDiagnostic(params) {
761
- const source = params.result.source ? ` (${params.result.source})` : "";
762
- const label = params.tokenType === "user" ? "User scopes" : "Bot scopes";
763
- if (params.result.ok && params.result.scopes?.length) return { text: `${label}${source}: ${params.result.scopes.join(", ")}` };
764
- return {
765
- text: `${label}: ${params.result.error ?? "scope lookup failed"}`,
766
- tone: "error"
767
- };
768
- }
769
912
  const resolveSlackAllowlistGroupOverrides = createFlatAllowlistOverrideResolver({
770
913
  resolveRecord: (account) => account.channels,
771
914
  label: (key) => key,
@@ -881,11 +1024,21 @@ const slackPlugin = createChatChannelPlugin({
881
1024
  },
882
1025
  bindings: {
883
1026
  compileConfiguredBinding: ({ conversationId }) => normalizeSlackAcpConversationId(conversationId),
884
- matchInboundConversation: ({ compiledBinding, conversationId, parentConversationId }) => matchSlackAcpConversation({
885
- bindingConversationId: compiledBinding.conversationId,
886
- conversationId,
887
- parentConversationId
888
- })
1027
+ matchInboundConversation: ({ compiledBinding, conversationId: rawConversationId, parentConversationId: rawParentConversationId }) => {
1028
+ const bindingConversationId = normalizeSlackAcpConversationId(compiledBinding.conversationId)?.conversationId;
1029
+ const conversationId = normalizeSlackAcpConversationId(rawConversationId)?.conversationId;
1030
+ const parentConversationId = normalizeSlackAcpConversationId(rawParentConversationId)?.conversationId;
1031
+ if (!bindingConversationId || !conversationId) return null;
1032
+ if (bindingConversationId === conversationId) return {
1033
+ conversationId,
1034
+ matchPriority: 2
1035
+ };
1036
+ if (parentConversationId && parentConversationId !== conversationId && bindingConversationId === parentConversationId) return {
1037
+ conversationId: parentConversationId,
1038
+ matchPriority: 1
1039
+ };
1040
+ return null;
1041
+ }
889
1042
  },
890
1043
  conversationBindings: { isCurrentConversationBindingSupported: ({ accountId }) => isSlackWorkspaceInstallation(accountId) },
891
1044
  messaging: {
@@ -906,7 +1059,82 @@ const slackPlugin = createChatChannelPlugin({
906
1059
  return normalizeSlackMessagingTarget(`channel:${id}`);
907
1060
  },
908
1061
  inferTargetChatType: ({ to }) => resolveSlackRouteTarget(to)?.chatType,
909
- resolveOutboundSessionRoute: resolveSlackOutboundSessionRoute,
1062
+ resolveOutboundSessionRoute: async (params) => {
1063
+ const parsed = parseSlackTarget(params.target, { defaultKind: "channel" });
1064
+ if (!parsed) return null;
1065
+ const apiTargetId = canonicalizeSlackApiTargetId(parsed.kind, parsed.id, params.target);
1066
+ const isDm = parsed.kind === "user";
1067
+ if (params.deliveryPurpose === "heartbeat-owner" && isDm && !parsed.teamId && /^[UW][A-Z0-9]{8,}$/.test(apiTargetId)) {
1068
+ const teamId = await resolveSlackEnterpriseUserTeamId({
1069
+ cfg: params.cfg,
1070
+ accountId: params.accountId,
1071
+ userId: apiTargetId
1072
+ });
1073
+ if (teamId) {
1074
+ parsed.teamId = teamId;
1075
+ parsed.id = apiTargetId;
1076
+ }
1077
+ }
1078
+ let peerKind = isDm ? "direct" : "channel";
1079
+ let peerId = formatSlackTarget(parsed);
1080
+ let recipientSessionExact = isDm ? /^[UW][A-Z0-9]{8,}$/i.test(parsed.id) : /^C[A-Z0-9]{8,}$/i.test(parsed.id);
1081
+ if (!isDm && /^D/i.test(parsed.id)) {
1082
+ const conversation = await resolveSlackConversationInfo({
1083
+ cfg: params.cfg,
1084
+ accountId: params.accountId,
1085
+ channelId: apiTargetId,
1086
+ teamId: parsed.teamId
1087
+ });
1088
+ if (conversation.type !== "dm" || !conversation.user) return null;
1089
+ peerKind = "direct";
1090
+ peerId = formatSlackTarget({
1091
+ teamId: parsed.teamId,
1092
+ kind: "user",
1093
+ id: conversation.user
1094
+ });
1095
+ recipientSessionExact = true;
1096
+ } else if (!isDm && /^G/i.test(parsed.id)) {
1097
+ const channelType = await resolveSlackChannelType({
1098
+ cfg: params.cfg,
1099
+ accountId: params.accountId,
1100
+ channelId: apiTargetId,
1101
+ teamId: parsed.teamId
1102
+ });
1103
+ if (channelType === "group") peerKind = "group";
1104
+ if (channelType === "dm") peerKind = "direct";
1105
+ recipientSessionExact = channelType !== "unknown";
1106
+ }
1107
+ const peer = {
1108
+ kind: peerKind,
1109
+ id: peerId
1110
+ };
1111
+ const unpartitionedBaseSessionKey = buildOutboundBaseSessionKey({
1112
+ channel: "slack",
1113
+ cfg: params.cfg,
1114
+ agentId: params.agentId,
1115
+ accountId: params.accountId,
1116
+ peer
1117
+ });
1118
+ const baseSessionKey = parsed.teamId && peerKind === "direct" && (params.cfg.session?.dmScope ?? "main") === "main" ? `${unpartitionedBaseSessionKey}:account:${encodeURIComponent(resolveSlackAccount({
1119
+ cfg: params.cfg,
1120
+ accountId: params.accountId
1121
+ }).accountId).toLowerCase()}:team:${encodeURIComponent(parsed.teamId).toLowerCase()}` : unpartitionedBaseSessionKey;
1122
+ return buildThreadAwareOutboundSessionRoute({
1123
+ route: {
1124
+ sessionKey: baseSessionKey,
1125
+ baseSessionKey,
1126
+ recipientSessionExact,
1127
+ peer,
1128
+ chatType: peerKind === "direct" ? "direct" : "channel",
1129
+ from: peerKind === "direct" ? `slack:${peerId}` : peerKind === "group" ? `slack:group:${peerId}` : `slack:channel:${peerId}`,
1130
+ to: parsed.teamId ? peerId : peerKind === "direct" ? `user:${peerId}` : `channel:${peerId}`
1131
+ },
1132
+ replyToId: params.replyToId,
1133
+ threadId: params.threadId,
1134
+ currentSessionKey: params.currentSessionKey,
1135
+ canRecoverCurrentThread: () => peerKind !== "direct" || (params.cfg.session?.dmScope ?? "main") !== "main"
1136
+ });
1137
+ },
910
1138
  hasStructuredReplyPayload: ({ payload }) => {
911
1139
  try {
912
1140
  return Boolean(resolveSlackReplyBlocks(payload)?.length);
@@ -968,7 +1196,7 @@ const slackPlugin = createChatChannelPlugin({
968
1196
  mapResolved: (entry) => entry
969
1197
  });
970
1198
  } },
971
- actions: createSlackActions(SLACK_CHANNEL, { invoke: async (action, cfg, toolContext) => await (await resolveSlackHandleAction())(action, cfg, toolContext) }),
1199
+ actions: createSlackActions(SLACK_CHANNEL),
972
1200
  message: slackMessageAdapter,
973
1201
  heartbeat: {
974
1202
  sendTyping: (params) => setSlackHeartbeatThreadStatus({
@@ -981,7 +1209,7 @@ const slackPlugin = createChatChannelPlugin({
981
1209
  })
982
1210
  },
983
1211
  status: createComputedAccountStatusAdapter({
984
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
1212
+ defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID$1),
985
1213
  buildChannelSummary: async ({ snapshot }) => {
986
1214
  const { buildPassiveProbedChannelStatusSummary } = await loadExtensionSharedSdk();
987
1215
  return buildPassiveProbedChannelStatusSummary(snapshot, snapshot.identity === "user" ? {
@@ -1004,8 +1232,7 @@ const slackPlugin = createChatChannelPlugin({
1004
1232
  ...account.identity === "user" ? { identity: "user" } : {}
1005
1233
  });
1006
1234
  },
1007
- formatCapabilitiesProbe: ({ probe }) => {
1008
- const slackProbe = probe;
1235
+ formatCapabilitiesProbe: ({ probe: slackProbe }) => {
1009
1236
  const lines = [];
1010
1237
  if (slackProbe?.warning) lines.push({
1011
1238
  text: `Warning: ${slackProbe.warning}`,
@@ -1035,10 +1262,12 @@ const slackPlugin = createChatChannelPlugin({
1035
1262
  ok: false,
1036
1263
  error: `Slack ${tokenType} token missing.`
1037
1264
  };
1038
- lines.push(formatSlackScopeDiagnostic({
1039
- tokenType,
1040
- result
1041
- }));
1265
+ const source = result.source ? ` (${result.source})` : "";
1266
+ const label = tokenType === "user" ? "User scopes" : "Bot scopes";
1267
+ lines.push(result.ok && result.scopes?.length ? { text: `${label}${source}: ${result.scopes.join(", ")}` } : {
1268
+ text: `${label}: ${result.error ?? "scope lookup failed"}`,
1269
+ tone: "error"
1270
+ });
1042
1271
  details[`${tokenType}Scopes`] = result;
1043
1272
  }
1044
1273
  return {
@@ -1084,8 +1313,7 @@ const slackPlugin = createChatChannelPlugin({
1084
1313
  abortSignal: ctx.abortSignal,
1085
1314
  mediaMaxMb: account.config.mediaMaxMb,
1086
1315
  slashCommand: account.config.slashCommand,
1087
- setStatus: ctx.setStatus,
1088
- getStatus: ctx.getStatus
1316
+ setStatus: ctx.setStatus
1089
1317
  });
1090
1318
  }
1091
1319
  },