@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,9 +1,35 @@
1
- import { $ as buildSlackDataVisualizationBlock, D as buildSlackCompleteBlocksFallbackText, E as buildSlackBlocksFallbackText, I as SLACK_BUTTON_ACTION_IDS, J as encodeSlackQuestionAction, O as renderSlackBlockFallbackText, P as truncateSlackText, V as SLACK_SELECT_ACTION_IDS, X as chunkSlackMrkdwnText, Z as markdownToSlackMrkdwnChunks, at as renderSlackMessagePresentationChartFallbackText, b as hasSlackNativeDataBlock, et as hasSlackDataVisualizationBlock, g as appendSlackNativeDataFallbackText, ht as parseSlackBlocksInput, it as countSlackDataTableCellCharacters, nt as buildSlackDataTableBlock, pt as SLACK_SECTION_TEXT_MAX, rt as countSlackDataTableBlocksCellCharacters, ut as encodeSlackApprovalAction, v as buildSlackNativeDataAccessibilityText } from "./session-status-CHkEn3HM.mjs";
1
+ import { Ct as markdownToSlackMrkdwnChunks, E as buildSlackNativeDataAccessibilityText, F as truncateSlackText, H as SLACK_SELECT_ACTION_IDS, L as SLACK_BUTTON_ACTION_IDS, O as hasSlackNativeDataBlock, St as chunkSlackMrkdwnText, Tt as escapeSlackMrkdwn, X as encodeSlackQuestionAction, at as buildSlackCompleteBlocksFallbackText, ct as hasSlackDataVisualizationBlock, dt as countSlackDataTableBlocksCellCharacters, et as encodeSlackApprovalAction, ft as countSlackDataTableCellCharacters, gt as renderSlackMessagePresentationChartFallbackText, ht as SLACK_SECTION_TEXT_MAX, it as buildSlackBlocksFallbackText, nt as parseSlackBlocksInput, ot as renderSlackBlockFallbackText, st as buildSlackDataVisualizationBlock, ut as buildSlackDataTableBlock, w as appendSlackNativeDataFallbackText } from "./probe-B_Ax1vS1.mjs";
2
2
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
4
4
  import { legacyInteractiveReplyToPresentation, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
5
- import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
6
5
  import { resolveAskUserQuestionOptionIndex, resolveAskUserQuestionOptionIndices, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
6
+ import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
7
+ // extensions/slack/src/authored-text.ts
8
+ function isSlackAuthoredTextRepresentedInFragments(plan, fragments) {
9
+ if (plan.length === 0) return false;
10
+ if (fragments.some((_, start) => plan.every((text, index) => text === fragments[start + index]))) return true;
11
+ const [text] = plan;
12
+ if (plan.length !== 1 || !text || /[*_~`<]/u.test(text)) return false;
13
+ for (let start = 0; start < fragments.length; start += 1) {
14
+ let offset = 0;
15
+ for (let end = start; end < fragments.length; end += 1) {
16
+ const fragment = fragments[end];
17
+ if (typeof fragment !== "string" || !text.startsWith(fragment, offset)) break;
18
+ offset += fragment.length;
19
+ if (offset === text.length) return true;
20
+ if (!/\s/u.test(text[offset] ?? "")) break;
21
+ while (/\s/u.test(text[offset] ?? "")) offset += 1;
22
+ }
23
+ }
24
+ return false;
25
+ }
26
+ /** Resolve placement from producer facts, before accessibility text changes the payload text. */
27
+ function resolveSlackAuthoredTextPlacement(params) {
28
+ const text = normalizeOptionalString(params.text);
29
+ if (!text) return "none";
30
+ const fragments = (params.renderedTextFragments ?? params.interactive?.blocks.flatMap((block) => block.type === "text" ? [block.text] : []) ?? []).map((fragment) => fragment?.trim() ?? null).filter((fragment) => fragment !== "");
31
+ return isSlackAuthoredTextRepresentedInFragments((params.authoredChunks ?? [text]).map((fragment) => fragment.trim()).filter(Boolean), fragments) ? "blocks" : "outside-blocks";
32
+ }
7
33
  // extensions/slack/src/blocks-render.ts
8
34
  const SLACK_BUTTON_URL_MAX = 3e3;
9
35
  function buildSlackPlainText(text, maxLength) {
@@ -13,10 +39,6 @@ function buildSlackPlainText(text, maxLength) {
13
39
  emoji: true
14
40
  };
15
41
  }
16
- function resolveSlackButtonStyle(style) {
17
- if (style === "primary" || style === "danger") return style;
18
- if (style === "success") return "primary";
19
- }
20
42
  function resolveSlackActionTarget(action, questionOptionIndices) {
21
43
  if (!action) return;
22
44
  if (action.type === "approval") return {
@@ -59,42 +81,10 @@ function resolveSlackActionTarget(action, questionOptionIndices) {
59
81
  value: command
60
82
  } : void 0;
61
83
  }
62
- function resolveSlackButtonTarget(button, questionOptionIndices) {
63
- if (button.action !== void 0) {
64
- const action = resolveMessagePresentationButtonAction(button);
65
- return action ? resolveSlackActionTarget(action, questionOptionIndices) : void 0;
66
- }
67
- const legacyUrl = normalizeOptionalString(button.url ?? button.webApp?.url ?? button.web_app?.url);
68
- if (legacyUrl && legacyUrl.length <= SLACK_BUTTON_URL_MAX) return {
69
- kind: "link",
70
- url: legacyUrl
71
- };
72
- const legacyValue = normalizeOptionalString(button.value);
73
- if (legacyValue) return {
74
- kind: "reply",
75
- value: legacyValue
76
- };
77
- return legacyUrl ? {
78
- kind: "link",
79
- url: legacyUrl
80
- } : void 0;
81
- }
82
84
  function isSlackTextFallbackButton(button) {
83
85
  const action = resolveMessagePresentationButtonAction(button);
84
86
  return action?.type === "question" && "intent" in action && action.intent === "custom-input";
85
87
  }
86
- function resolveSlackOptionTarget(option) {
87
- if (option.action !== void 0) {
88
- const action = resolveMessagePresentationOptionAction(option);
89
- const target = action ? resolveSlackActionTarget(action) : void 0;
90
- return target?.kind === "link" || target?.kind === "question" ? void 0 : target;
91
- }
92
- const value = normalizeOptionalString(option.value);
93
- return value ? {
94
- kind: "reply",
95
- value
96
- } : void 0;
97
- }
98
88
  function readSlackOpenClawBlockIndex(blockId, prefix) {
99
89
  if (!blockId.startsWith(prefix)) return;
100
90
  const value = Number.parseInt(blockId.slice(prefix.length), 10);
@@ -136,7 +126,18 @@ function buildSlackPresentationBlocksIfComplete(presentation, options = {}) {
136
126
  function compileSlackPresentationBlocks(presentation, options, requireComplete) {
137
127
  if (!presentation) return [];
138
128
  if (requireComplete && presentation.title && presentation.title.trim().length > 150) return;
139
- const tables = buildSlackPresentationTables(presentation, options);
129
+ let tables = [];
130
+ let cellCharacterCount = options.dataTableCellCharacterCountOffset ?? 0;
131
+ for (const block of presentation.blocks) {
132
+ if (block.type !== "table") continue;
133
+ const table = buildSlackDataTableBlock(block, { cellCharacterCountOffset: cellCharacterCount });
134
+ if (!table) {
135
+ tables = void 0;
136
+ break;
137
+ }
138
+ cellCharacterCount += countSlackDataTableCellCharacters(table);
139
+ tables.push(table);
140
+ }
140
141
  if (requireComplete && !tables) return;
141
142
  const blocks = [];
142
143
  if (presentation.title) blocks.push({
@@ -175,8 +176,79 @@ function compileSlackPresentationBlocks(presentation, options, requireComplete)
175
176
  }
176
177
  if (block.type === "buttons" || block.type === "select") {
177
178
  const index = controlIndices[block.type] + 1;
178
- const elements = block.type === "buttons" ? buildSlackPresentationButtonElements(block, index, options.questionOptionIndices, requireComplete) : buildSlackPresentationSelectElements(block, index, requireComplete);
179
- if (!elements) return;
179
+ let elements;
180
+ if (block.type === "buttons") {
181
+ let complete = true;
182
+ const buttons = block.buttons.flatMap((button, choiceIndex) => {
183
+ const questionOptionIndices = options.questionOptionIndices;
184
+ let target;
185
+ if (button.action !== void 0) {
186
+ const action = resolveMessagePresentationButtonAction(button);
187
+ target = action ? resolveSlackActionTarget(action, questionOptionIndices) : void 0;
188
+ } else {
189
+ const legacyUrl = normalizeOptionalString(button.url ?? button.webApp?.url ?? button.web_app?.url);
190
+ if (legacyUrl && legacyUrl.length <= SLACK_BUTTON_URL_MAX) target = {
191
+ kind: "link",
192
+ url: legacyUrl
193
+ };
194
+ else {
195
+ const legacyValue = normalizeOptionalString(button.value);
196
+ target = legacyValue ? {
197
+ kind: "reply",
198
+ value: legacyValue
199
+ } : legacyUrl ? {
200
+ kind: "link",
201
+ url: legacyUrl
202
+ } : void 0;
203
+ }
204
+ }
205
+ if (!target || (target.kind === "link" ? target.url.length > SLACK_BUTTON_URL_MAX : target.value.length > 2e3)) {
206
+ if (requireComplete && !isSlackTextFallbackButton(button)) complete = false;
207
+ return [];
208
+ }
209
+ if (button.label.length > 75) complete = false;
210
+ const style = button.style === "success" ? "primary" : button.style === "primary" || button.style === "danger" ? button.style : void 0;
211
+ return [{
212
+ type: "button",
213
+ action_id: `${SLACK_BUTTON_ACTION_IDS[target.kind]}:${index}:${choiceIndex + 1}`,
214
+ text: buildSlackPlainText(button.label, 75),
215
+ ...target.kind === "link" ? { url: target.url } : { value: target.value },
216
+ ...style ? { style } : {}
217
+ }];
218
+ });
219
+ if (requireComplete && (!complete || buttons.length > 25)) return;
220
+ elements = buttons.slice(0, 25);
221
+ } else {
222
+ const placeholder = normalizeOptionalString(block.placeholder) ?? "Choose an option";
223
+ const candidates = block.options.map((option) => {
224
+ if (option.action !== void 0) {
225
+ const action = resolveMessagePresentationOptionAction(option);
226
+ const target = action ? resolveSlackActionTarget(action) : void 0;
227
+ return target && target.kind !== "link" && target.kind !== "question" ? {
228
+ label: option.label,
229
+ ...target
230
+ } : void 0;
231
+ }
232
+ const value = normalizeOptionalString(option.value);
233
+ return value ? {
234
+ label: option.label,
235
+ kind: "reply",
236
+ value
237
+ } : void 0;
238
+ });
239
+ if (requireComplete && (placeholder.length > 75 || block.options.length > 100 || block.placeholder && block.placeholder.length > 75 || !candidates.every((option) => option && option.label.length <= 75 && option.value.length <= 150) || new Set(candidates.map((option) => option?.kind)).size !== 1)) return;
240
+ const selectOptions = candidates.flatMap((option) => option && option.value.length <= 150 ? [option] : []).slice(0, 100);
241
+ const optionKinds = new Set(selectOptions.map((option) => option.kind));
242
+ elements = selectOptions.length > 0 && optionKinds.size === 1 ? [{
243
+ type: "static_select",
244
+ action_id: `${SLACK_SELECT_ACTION_IDS[selectOptions[0].kind]}:${index}`,
245
+ placeholder: buildSlackPlainText(placeholder, 75),
246
+ options: selectOptions.map((option) => ({
247
+ text: buildSlackPlainText(option.label, 75),
248
+ value: option.value
249
+ }))
250
+ }] : [];
251
+ }
180
252
  if (elements.length > 0) {
181
253
  controlIndices[block.type] = index;
182
254
  blocks.push({
@@ -212,91 +284,6 @@ function compileSlackPresentationBlocks(presentation, options, requireComplete)
212
284
  }
213
285
  return blocks;
214
286
  }
215
- function buildSlackPresentationButtonElements(block, buttonIndex, questionOptionIndices, requireComplete) {
216
- let complete = true;
217
- const elements = block.buttons.flatMap((button, choiceIndex) => {
218
- const target = resolveSlackButtonTarget(button, questionOptionIndices);
219
- if (!target || (target.kind === "link" ? target.url.length > SLACK_BUTTON_URL_MAX : target.value.length > 2e3)) {
220
- if (requireComplete && !isSlackTextFallbackButton(button)) complete = false;
221
- return [];
222
- }
223
- if (button.label.length > 75) complete = false;
224
- const style = resolveSlackButtonStyle(button.style);
225
- return [{
226
- type: "button",
227
- action_id: `${SLACK_BUTTON_ACTION_IDS[target.kind]}:${buttonIndex}:${choiceIndex + 1}`,
228
- text: buildSlackPlainText(button.label, 75),
229
- ...target.kind === "link" ? { url: target.url } : { value: target.value },
230
- ...style ? { style } : {}
231
- }];
232
- });
233
- if (requireComplete && (!complete || elements.length > 25)) return;
234
- return elements.slice(0, 25);
235
- }
236
- /** Admit tables together: one invalid or over-budget table keeps every table on the text path. */
237
- function buildSlackPresentationTables(presentation, options = {}) {
238
- const tables = [];
239
- let cellCharacterCount = options.dataTableCellCharacterCountOffset ?? 0;
240
- for (const block of presentation.blocks) {
241
- if (block.type !== "table") continue;
242
- const table = buildSlackDataTableBlock(block, { cellCharacterCountOffset: cellCharacterCount });
243
- if (!table) return;
244
- cellCharacterCount += countSlackDataTableCellCharacters(table);
245
- tables.push(table);
246
- }
247
- return tables;
248
- }
249
- function buildSlackPresentationSelectElements(block, selectIndex, requireComplete) {
250
- const placeholder = normalizeOptionalString(block.placeholder) ?? "Choose an option";
251
- const candidates = block.options.map((option) => {
252
- const target = resolveSlackOptionTarget(option);
253
- return target ? {
254
- label: option.label,
255
- ...target
256
- } : void 0;
257
- });
258
- if (requireComplete && (placeholder.length > 75 || block.options.length > 100 || block.placeholder && block.placeholder.length > 75 || !candidates.every((option) => option && option.label.length <= 75 && option.value.length <= 150) || new Set(candidates.map((option) => option?.kind)).size !== 1)) return;
259
- const options = candidates.flatMap((option) => option && option.value.length <= 150 ? [option] : []).slice(0, 100);
260
- const optionKinds = new Set(options.map((option) => option.kind));
261
- return options.length > 0 && optionKinds.size === 1 ? [{
262
- type: "static_select",
263
- action_id: `${SLACK_SELECT_ACTION_IDS[options[0].kind]}:${selectIndex}`,
264
- placeholder: buildSlackPlainText(placeholder, 75),
265
- options: options.map((option) => ({
266
- text: buildSlackPlainText(option.label, 75),
267
- value: option.value
268
- }))
269
- }] : [];
270
- }
271
- // extensions/slack/src/authored-text.ts
272
- function normalizeComparableSlackText(text) {
273
- return text.trim().replace(/\s+/g, " ");
274
- }
275
- function isSlackAuthoredTextRepresentedInFragments(text, rawFragments) {
276
- const target = normalizeComparableSlackText(text);
277
- const fragments = rawFragments.map(normalizeComparableSlackText).filter(Boolean);
278
- let remainingLength = fragments.reduce((length, fragment) => length + fragment.length + 1, -1);
279
- for (const [start, firstFragment] of fragments.entries()) {
280
- if (remainingLength < target.length) break;
281
- remainingLength -= firstFragment.length + 1;
282
- let offset = 0;
283
- for (let end = start;; end += 1) {
284
- const fragment = fragments[end];
285
- if (fragment === void 0 || !target.startsWith(fragment, offset)) break;
286
- offset += fragment.length;
287
- if (offset === target.length) return true;
288
- if (target[offset] !== " ") break;
289
- offset += 1;
290
- }
291
- }
292
- return false;
293
- }
294
- /** Resolve placement from producer facts, before accessibility text changes the payload text. */
295
- function resolveSlackAuthoredTextPlacement(params) {
296
- const text = normalizeOptionalString(params.text);
297
- if (!text) return "none";
298
- return params.renderedInBlocks || isSlackAuthoredTextRepresentedInFragments(text, params.renderedTextFragments ?? []) || isSlackAuthoredTextRepresentedInFragments(text, params.interactive?.blocks.flatMap((block) => block.type === "text" ? [block.text] : []) ?? []) ? "blocks" : "outside-blocks";
299
- }
300
287
  // extensions/slack/src/reply-blocks.ts
301
288
  function normalizeSlackReplyPayload(payload) {
302
289
  const previousSlackData = asOptionalRecord(payload.channelData?.slack) ?? {};
@@ -319,27 +306,6 @@ function normalizeSlackReplyPayload(payload) {
319
306
  }
320
307
  };
321
308
  }
322
- function parseSlackReplyBlockSegments(value) {
323
- if (value === void 0) return;
324
- if (!Array.isArray(value)) throw new Error("Slack rendered presentation segments must be an array");
325
- return value.map((raw) => {
326
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("Slack rendered presentation segment must be an object");
327
- const segment = raw;
328
- if (segment.kind === "text" && typeof segment.text === "string" && segment.mrkdwn === false) return {
329
- kind: "text",
330
- text: segment.text,
331
- mrkdwn: false
332
- };
333
- if (segment.kind === "blocks") {
334
- const blocks = parseSlackBlocksInput(segment.blocks);
335
- if (blocks?.length) return {
336
- kind: "blocks",
337
- blocks
338
- };
339
- }
340
- throw new Error("Slack rendered presentation segment is invalid");
341
- });
342
- }
343
309
  /** Project each segment only when the caller is ready to deliver it. */
344
310
  function* iterateSlackReplyDeliveryMessages(params) {
345
311
  let outsideText = params.authoredTextPlacement === "outside-blocks" ? params.text?.trim() ?? "" : "";
@@ -372,35 +338,35 @@ function* iterateSlackReplyDeliveryMessages(params) {
372
338
  function resolveSlackReplyDeliveryMessages(params) {
373
339
  return Array.from(iterateSlackReplyDeliveryMessages(params));
374
340
  }
375
- function resolveSlackReplyRenderPlan(payload, text = payload.text) {
376
- return prepareSlackReply(payload).resolvePreview(text);
341
+ function resolveSlackReplyRenderPlan(payload, text = payload.text, options = {}) {
342
+ return prepareSlackReply(payload, options).resolvePreview(text);
377
343
  }
378
344
  /** One attempt owns its authored compilation; media captions retain a separate delivery policy. */
379
- function prepareSlackReply(payload) {
345
+ function prepareSlackReply(payload, options = {}) {
380
346
  const text = payload.text;
381
- const source = {
382
- ...payload,
383
- text
384
- };
385
347
  let authoredChunks;
386
348
  let structuredContent;
387
349
  let materialized;
388
350
  let unmaterialized;
389
351
  let preview;
390
- const resolveAuthoredTextChunks = () => authoredChunks ??= markdownToSlackMrkdwnChunks(text?.trim() ?? "", SLACK_SECTION_TEXT_MAX);
391
- const hasStructuredContent = () => structuredContent ??= hasSlackReplyStructuredContent(source);
392
- const resolve = (materializeAuthoredText) => materializeAuthoredText ? materialized ??= resolveSlackReplyBlockResolution(source, {
352
+ const resolveAuthoredTextChunks = () => authoredChunks ??= markdownToSlackMrkdwnChunks(text?.trim() ?? "", SLACK_SECTION_TEXT_MAX, options);
353
+ const hasStructuredContent = () => structuredContent ??= hasSlackReplyStructuredContent(payload);
354
+ const resolve = (materializeAuthoredText) => materializeAuthoredText ? materialized ??= resolveSlackReplyBlockResolution(payload, {
355
+ ...options,
393
356
  materializeAuthoredText: true,
394
357
  resolveAuthoredTextChunks
395
- }) : unmaterialized ??= resolveSlackReplyBlockResolution(source);
358
+ }) : unmaterialized ??= resolveSlackReplyBlockResolution(payload, {
359
+ ...options,
360
+ resolveAuthoredTextChunks
361
+ });
396
362
  return {
397
363
  payload,
398
- resolveDelivery: () => resolve(!resolveSendableOutboundReplyParts(source).hasMedia && hasStructuredContent()),
364
+ resolveDelivery: () => resolve(!resolveSendableOutboundReplyParts(payload).hasMedia && hasStructuredContent()),
399
365
  resolvePreview: (override = text) => {
400
366
  if (override !== text) return prepareSlackReply({
401
- ...source,
367
+ ...payload,
402
368
  text: override
403
- }).resolvePreview();
369
+ }, options).resolvePreview();
404
370
  return preview ??= projectSlackReplyRenderPlan(text, resolve(hasStructuredContent()), resolveAuthoredTextChunks);
405
371
  }
406
372
  };
@@ -450,11 +416,52 @@ function readSlackChannelBlocks(payload) {
450
416
  function hasSlackReplyStructuredContent(payload) {
451
417
  return Boolean(readSlackChannelBlocks(payload).length || normalizeMessagePresentation(payload.presentation) || payload.interactive?.blocks.length);
452
418
  }
419
+ function literalSlackComparisonText(text) {
420
+ return /[*_~`]/u.test(text) ? null : escapeSlackMrkdwn(text);
421
+ }
422
+ function renderSlackRichTextComparisonFragments(value) {
423
+ if (!Array.isArray(value)) return [null];
424
+ return value.map((raw) => {
425
+ const section = asOptionalRecord(raw);
426
+ if (section?.type !== "rich_text_section" && section?.type !== "rich_text_preformatted" || !Array.isArray(section.elements)) return null;
427
+ let text = "";
428
+ let style;
429
+ for (const rawElement of section.elements) {
430
+ const element = asOptionalRecord(rawElement);
431
+ if (element?.type !== "text" || typeof element.text !== "string") return null;
432
+ const styles = Object.entries(asOptionalRecord(element.style) ?? {}).filter(([, enabled]) => enabled !== false);
433
+ const nextStyle = styles[0]?.[0] ?? "";
434
+ if (styles.length > 1 || styles.some(([key, enabled]) => enabled !== true || ![
435
+ "bold",
436
+ "italic",
437
+ "strike",
438
+ "code"
439
+ ].includes(key)) || style !== void 0 && nextStyle !== style) return null;
440
+ style = nextStyle;
441
+ text += element.text;
442
+ }
443
+ if (section.type === "rich_text_preformatted") return style || text.includes("```") ? null : "```\n" + escapeSlackMrkdwn(text) + (text.endsWith("\n") ? "" : "\n") + "```";
444
+ if (style === "code") return /[`\r\n]/u.test(text) ? null : "`" + escapeSlackMrkdwn(text) + "`";
445
+ const literal = literalSlackComparisonText(text);
446
+ if (!style || literal === null) return literal;
447
+ if (text.trim() !== text) return null;
448
+ const marker = style === "bold" ? "*" : style === "italic" ? "_" : "~";
449
+ return marker + literal + marker;
450
+ });
451
+ }
453
452
  function renderSlackAuthoredTextFragments(blocks) {
453
+ const readTextObject = (value) => {
454
+ const record = asOptionalRecord(value);
455
+ const text = normalizeOptionalString(record?.text);
456
+ return text === void 0 ? void 0 : record?.type === "mrkdwn" ? text : literalSlackComparisonText(text);
457
+ };
454
458
  return blocks.flatMap((block) => {
455
- if (block.type === "actions") return [];
456
- const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
457
- return text ? [text] : [];
459
+ const record = asOptionalRecord(block);
460
+ if (block.type === "actions" || block.type === "divider") return [];
461
+ if (block.type === "section" || block.type === "context" || block.type === "header") return (block.type === "context" ? Array.isArray(record?.elements) ? record.elements : [] : [record?.text, ...Array.isArray(record?.fields) ? record.fields : []]).map(readTextObject).filter((text) => text !== void 0);
462
+ if (block.type === "rich_text") return renderSlackRichTextComparisonFragments(record?.elements);
463
+ const text = renderSlackBlockFallbackText(block);
464
+ return text ? [/[*_~`]/u.test(text) ? null : text] : [];
458
465
  });
459
466
  }
460
467
  function buildSlackAuthoredTextBlocks(chunks) {
@@ -499,8 +506,7 @@ function appendTextSegment(segments, text) {
499
506
  }
500
507
  segments.push({
501
508
  kind: "text",
502
- text: trimmed,
503
- mrkdwn: false
509
+ text: trimmed
504
510
  });
505
511
  }
506
512
  function appendBlockSegment(segments, blocks, startNew = false) {
@@ -568,37 +574,10 @@ function subtractMirroredSlackControlRows(params) {
568
574
  return false;
569
575
  });
570
576
  }
571
- /**
572
- * Resolve reply content into transport-order segments. Each blocks segment is
573
- * one Slack message; text segments carry complete fallback content between it.
574
- */
575
- function resolveSlackReplyBlockResolution(payload, options = {}) {
577
+ function compileSlackReplyBlockSegments(payload, channelBlocks, presentation) {
576
578
  const segments = [];
577
- const presentation = normalizeMessagePresentation(payload.presentation);
578
579
  const textIsFallback = presentation && payload.presentationTextMode === "fallback";
579
- const authoredText = textIsFallback ? void 0 : payload.text;
580
- const channelBlocks = readSlackChannelBlocks(payload);
581
- let compiledChannelBlocks = channelBlocks;
582
- let authoredTextKnownInBlocks = false;
583
- if (options.materializeAuthoredText) {
584
- const rawTextFragments = renderSlackAuthoredTextFragments(channelBlocks);
585
- const initialPlacement = resolveSlackAuthoredTextPlacement({
586
- text: authoredText,
587
- interactive: payload.interactive,
588
- renderedTextFragments: rawTextFragments
589
- });
590
- authoredTextKnownInBlocks = initialPlacement === "blocks";
591
- const text = normalizeOptionalString(authoredText);
592
- if (text && initialPlacement === "outside-blocks") {
593
- const textBlocks = buildSlackAuthoredTextBlocks(options.resolveAuthoredTextChunks?.() ?? markdownToSlackMrkdwnChunks(text, 3e3));
594
- if (resolveSlackAuthoredTextPlacement({
595
- text: renderSlackAuthoredTextFragments(textBlocks).join(" "),
596
- renderedTextFragments: rawTextFragments
597
- }) !== "blocks") compiledChannelBlocks = [...channelBlocks, ...textBlocks];
598
- authoredTextKnownInBlocks = true;
599
- }
600
- }
601
- if (compiledChannelBlocks.length > 0) appendBlockSegment(segments, compiledChannelBlocks);
580
+ if (channelBlocks.length > 0) appendBlockSegment(segments, channelBlocks);
602
581
  const questionOptionIndices = resolveAskUserQuestionOptionIndices(payload);
603
582
  const presentationBlockOffset = readAllNativeBlocks(segments).length;
604
583
  if (presentation?.title) appendPresentationPart(segments, {
@@ -619,30 +598,46 @@ function resolveSlackReplyBlockResolution(payload, options = {}) {
619
598
  "rich_text"
620
599
  ].includes(block.type) && !("accessory" in block && block.accessory))) {
621
600
  segments.length = 0;
622
- appendBlockSegment(segments, compiledChannelBlocks);
601
+ appendBlockSegment(segments, channelBlocks);
623
602
  appendTextSegment(segments, payload.text);
624
603
  }
625
604
  appendBlockSegment(segments, subtractMirroredSlackControlRows({
626
605
  interactiveBlocks,
627
606
  presentationBlocks: renderedPresentationBlocks
628
607
  }));
629
- const renderedTextFragments = segments.flatMap((segment) => {
630
- if (segment.kind === "text") return [segment.text];
631
- return renderSlackAuthoredTextFragments(segment.blocks);
608
+ return segments;
609
+ }
610
+ /**
611
+ * Resolve reply content into transport-order segments. Each blocks segment is
612
+ * one Slack message; text segments carry complete fallback content between it.
613
+ */
614
+ function resolveSlackReplyBlockResolution(payload, options = {}) {
615
+ const presentation = normalizeMessagePresentation(payload.presentation);
616
+ const authoredText = presentation && payload.presentationTextMode === "fallback" ? void 0 : normalizeOptionalString(payload.text);
617
+ const channelBlocks = readSlackChannelBlocks(payload);
618
+ let segments = compileSlackReplyBlockSegments(payload, channelBlocks, presentation);
619
+ const chunks = authoredText && (segments.length > 0 || options.materializeAuthoredText) ? options.resolveAuthoredTextChunks?.() ?? markdownToSlackMrkdwnChunks(authoredText, 3e3, options) : [];
620
+ let authoredTextPlacement = resolveSlackAuthoredTextPlacement({
621
+ text: authoredText,
622
+ authoredChunks: chunks,
623
+ renderedTextFragments: segments.flatMap((segment) => segment.kind === "text" ? [literalSlackComparisonText(segment.text)] : renderSlackAuthoredTextFragments(segment.blocks))
632
624
  });
633
- const authoredTextPlacement = resolveSlackAuthoredTextPlacement({
625
+ if (authoredTextPlacement === "outside-blocks" && !/[*_~`<[\]\\#>|]/u.test(authoredText ?? "")) authoredTextPlacement = resolveSlackAuthoredTextPlacement({
634
626
  text: authoredText,
635
- interactive: payload.interactive,
636
- renderedTextFragments
627
+ renderedTextFragments: segments.flatMap((segment) => segment.kind === "text" ? [segment.text] : segment.blocks.map((block) => hasSlackNativeDataBlock([block]) ? renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" }) ?? null : null))
637
628
  });
629
+ if (options.materializeAuthoredText && authoredTextPlacement === "outside-blocks") {
630
+ segments = compileSlackReplyBlockSegments(payload, [...channelBlocks, ...buildSlackAuthoredTextBlocks(chunks)], presentation);
631
+ authoredTextPlacement = "blocks";
632
+ }
638
633
  return {
639
- authoredTextPlacement: authoredTextKnownInBlocks ? "blocks" : authoredTextPlacement,
634
+ authoredTextPlacement,
640
635
  segments
641
636
  };
642
637
  }
643
638
  /** Return the single-message native shape when no ordered text fallback is required. */
644
639
  function resolveSlackReplyBlocks(payload) {
645
- const { segments } = resolveSlackReplyBlockResolution(payload);
640
+ const segments = compileSlackReplyBlockSegments(payload, readSlackChannelBlocks(payload), normalizeMessagePresentation(payload.presentation));
646
641
  return segments.length === 1 && segments[0]?.kind === "blocks" ? segments[0].blocks : void 0;
647
642
  }
648
- export { prepareSlackReply as a, resolveSlackReplyDeliveryMessages as c, buildSlackInteractiveBlocks as d, buildSlackPresentationBlocks as f, parseSlackReplyBlockSegments as i, resolveSlackReplyRenderPlan as l, iterateSlackReplyDeliveryMessages as n, resolveSlackReplyBlockResolution as o, buildSlackPresentationBlocksIfComplete as p, normalizeSlackReplyPayload as r, resolveSlackReplyBlocks as s, hasSlackReplyStructuredContent as t, resolveSlackAuthoredTextPlacement as u };
643
+ export { resolveSlackReplyBlockResolution as a, resolveSlackReplyRenderPlan as c, resolveSlackAuthoredTextPlacement as d, prepareSlackReply as i, buildSlackInteractiveBlocks as l, iterateSlackReplyDeliveryMessages as n, resolveSlackReplyBlocks as o, normalizeSlackReplyPayload as r, resolveSlackReplyDeliveryMessages as s, hasSlackReplyStructuredContent as t, buildSlackPresentationBlocks as u };
@@ -1,12 +1,11 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.mjs";
2
- import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-0pRZtahO.mjs";
3
- import { c as collectSlackCursorPages, l as fetchSlackChannelListPage, u as createSlackLookupClient } from "./probe-C5VWf3sz.mjs";
2
+ import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-DwYAP3ts.mjs";
3
+ import { n as fetchSlackChannelListPage, r as createSlackLookupClient, t as collectSlackCursorPages } from "./cursor-pages-jVn3Vkfi.mjs";
4
4
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  // extensions/slack/src/resolve-channels.ts
6
6
  var resolve_channels_exports = /* @__PURE__ */ __exportAll({ resolveSlackChannelAllowlist: () => resolveSlackChannelAllowlist });
7
7
  function parseSlackChannelMention(raw) {
8
8
  const trimmed = raw.trim();
9
- if (!trimmed) return {};
10
9
  const mention = trimmed.match(/^<#([A-Z0-9]+)(?:\|([^>]+))?>$/i);
11
10
  if (mention) return {
12
11
  id: mention[1]?.toUpperCase(),
@@ -14,7 +13,7 @@ function parseSlackChannelMention(raw) {
14
13
  };
15
14
  const prefixed = trimmed.replace(/^(slack:|channel:)/i, "");
16
15
  if (/^[CG][A-Z0-9]{8,}$/i.test(prefixed)) return { id: prefixed.toUpperCase() };
17
- const name = prefixed.replace(/^#/, "").trim();
16
+ const name = normalizeLowercaseStringOrEmpty(prefixed.replace(/^#/, ""));
18
17
  return name ? { name } : {};
19
18
  }
20
19
  async function listSlackChannels(client) {
@@ -34,9 +33,7 @@ async function listSlackChannels(client) {
34
33
  });
35
34
  }
36
35
  function resolveByName(name, channels) {
37
- const target = normalizeLowercaseStringOrEmpty(name);
38
- if (!target) return;
39
- const matches = channels.filter((channel) => normalizeLowercaseStringOrEmpty(channel.name) === target);
36
+ const matches = channels.filter((channel) => normalizeLowercaseStringOrEmpty(channel.name) === name);
40
37
  return matches.find((channel) => !channel.archived) ?? matches[0];
41
38
  }
42
39
  async function resolveSlackChannelAllowlist(params) {
@@ -1,18 +1,17 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.mjs";
2
- import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-0pRZtahO.mjs";
3
- import { c as collectSlackCursorPages, u as createSlackLookupClient } from "./probe-C5VWf3sz.mjs";
2
+ import { s as resolveWorkspaceQualifiedSlackTarget } from "./target-parsing-DwYAP3ts.mjs";
3
+ import { r as createSlackLookupClient, t as collectSlackCursorPages } from "./cursor-pages-jVn3Vkfi.mjs";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  // extensions/slack/src/resolve-users.ts
6
6
  var resolve_users_exports = /* @__PURE__ */ __exportAll({ resolveSlackUserAllowlist: () => resolveSlackUserAllowlist });
7
7
  function parseSlackUserInput(raw) {
8
8
  const trimmed = raw.trim();
9
- if (!trimmed) return {};
10
9
  const mention = trimmed.match(/^<@([A-Z0-9]+)>$/i);
11
10
  if (mention) return { id: mention[1]?.toUpperCase() };
12
11
  const prefixed = trimmed.replace(/^(slack:|user:)/i, "");
13
12
  if (/^[A-Z][A-Z0-9]+$/i.test(prefixed)) return { id: prefixed.toUpperCase() };
14
13
  if (trimmed.includes("@") && !trimmed.startsWith("@")) return { email: normalizeLowercaseStringOrEmpty(trimmed) };
15
- const name = trimmed.replace(/^@/, "").trim();
14
+ const name = normalizeLowercaseStringOrEmpty(trimmed.replace(/^@/, ""));
16
15
  return name ? { name } : {};
17
16
  }
18
17
  async function listSlackUsers(client) {
@@ -39,17 +38,6 @@ async function listSlackUsers(client) {
39
38
  }).filter((user) => user !== null)
40
39
  });
41
40
  }
42
- function matchesSlackUserName(user, name) {
43
- const target = normalizeLowercaseStringOrEmpty(name);
44
- return [
45
- user.name,
46
- user.displayName,
47
- user.realName
48
- ].some((value) => {
49
- const candidate = normalizeLowercaseStringOrEmpty(value);
50
- return Boolean(candidate) && candidate === target;
51
- });
52
- }
53
41
  function scoreSlackUser(user) {
54
42
  return (user.deleted ? 0 : 3) + (user.isBot || user.isAppUser ? 0 : 2);
55
43
  }
@@ -62,7 +50,11 @@ async function resolveSlackUserAllowlist(params) {
62
50
  const users = entries.some(({ workspace }) => !workspace) ? await listSlackUsers(params.client ?? createSlackLookupClient(params.token)) : [];
63
51
  return entries.map(({ input, workspace, parsed }) => {
64
52
  if (workspace) return workspace;
65
- const matches = users.filter((user) => parsed.id ? user.id === parsed.id : parsed.email ? user.email === parsed.email : parsed.name ? matchesSlackUserName(user, parsed.name) : false);
53
+ const matches = users.filter((user) => parsed.id ? user.id === parsed.id : parsed.email ? user.email === parsed.email : parsed.name ? [
54
+ user.name,
55
+ user.displayName,
56
+ user.realName
57
+ ].some((value) => normalizeLowercaseStringOrEmpty(value) === parsed.name) : false);
66
58
  const match = parsed.id ? matches[0] : matches.toSorted((a, b) => scoreSlackUser(b) - scoreSlackUser(a))[0];
67
59
  if (!parsed.id && !match) return {
68
60
  input,
@@ -1,4 +1,5 @@
1
- import { d as createSlackReadClient, o as formatSlackError } from "./probe-C5VWf3sz.mjs";
1
+ import { m as formatSlackError } from "./probe-B_Ax1vS1.mjs";
2
+ import { i as createSlackReadClient } from "./cursor-pages-jVn3Vkfi.mjs";
2
3
  import { isRecord, normalizeOptionalString, normalizeTrimmedStringList, sortUniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  // extensions/slack/src/scopes.ts
4
5
  function collectScopes(value, into) {
@@ -1,4 +1,5 @@
1
- import { collectConditionalChannelFieldAssignments, collectNestedChannelFieldAssignments, collectSimpleChannelFieldAssignments, createChannelSecretContract, hasOwnProperty } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
1
+ import { n as hasSlackAccountCredentialsFromConfig } from "./account-configured-35y0-Hso.mjs";
2
+ import { collectConditionalChannelFieldAssignments, collectNestedChannelFieldAssignments, collectSimpleChannelFieldAssignments, createChannelSecretContract, hasOwnProperty, isRecord } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
2
3
  // extensions/slack/src/secret-contract.ts
3
4
  const channelSecrets = createChannelSecretContract({
4
5
  channelKey: "slack",
@@ -16,6 +17,7 @@ const channelSecrets = createChannelSecretContract({
16
17
  "signingSecret",
17
18
  "userToken"
18
19
  ],
20
+ hasImplicitDefaultAccount: ({ context }) => hasSlackAccountCredentialsFromConfig(context.sourceConfig.channels?.slack, context.env),
19
21
  collect(params) {
20
22
  const { channel: slack, surface } = params;
21
23
  const resolveMode = (value) => value === "http" || value === "socket" || value === "relay" ? value : void 0;
@@ -29,7 +31,7 @@ const channelSecrets = createChannelSecretContract({
29
31
  const resolveAccountMode = (account) => resolveMode(account.mode) ?? baseMode;
30
32
  const hasNestedAuthTokenOverride = (account) => {
31
33
  const relay = account.relay;
32
- return relay !== null && typeof relay === "object" && !Array.isArray(relay) && hasOwnProperty(relay, "authToken");
34
+ return isRecord(relay) && hasOwnProperty(relay, "authToken");
33
35
  };
34
36
  for (const [field, mode, label] of [[
35
37
  "appToken",
@@ -1,2 +1,2 @@
1
- export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-D0UY2JWF.mjs";
1
+ export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-CqVqR7MP.mjs";
2
2
  import "../secret-contract-api.js";