@openclaw/discord 2026.9.4 → 2026.9.6

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 (818) hide show
  1. package/assets/activity.svg +40 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/{account-inspect-BY-ve3yH.js → .setup/account-inspect-BwQj24ht.mjs} +1 -1
  4. package/dist/{activities-api-w8j7Elou.js → .setup/activities-api-COU4-0nR.mjs} +93 -31
  5. package/dist/{api-LIV--eMq.js → .setup/api-CBK9zcq5.mjs} +7 -4
  6. package/dist/{approval-handler.runtime-BnPUU5NK.js → .setup/approval-handler.runtime-CbBktBb4.mjs} +8 -7
  7. package/dist/.setup/approval-message-updates-jf9zMaIC.mjs +17 -0
  8. package/dist/{audit-BgAgIzwo.js → .setup/audit-vKbh-LFR.mjs} +5 -5
  9. package/dist/{channel-C_OFFR5Y.js → .setup/channel-Dv4e3Jpc.mjs} +34 -29
  10. package/dist/{channel-actions.runtime-tShzmemq.js → .setup/channel-actions.runtime-leZuw01r.mjs} +25 -12
  11. package/dist/{allow-list-DWEio925.js → .setup/channel-type-DKnjV1XW.mjs} +161 -1
  12. package/dist/{channel.setup-CpAwAiS0.js → .setup/channel.setup-0NX6FFwi.mjs} +4 -4
  13. package/dist/{components-DBFTIN6P.js → .setup/components-yBEb75bB.mjs} +4 -5
  14. package/dist/{config-schema-r38UkM_J.js → .setup/config-schema-CiZz-mtA.mjs} +1 -1
  15. package/dist/{conversation-binding-route-CB9PRqgi.js → .setup/conversation-binding-route-B7qImK_b.mjs} +6 -3
  16. package/dist/{directory-config-D1uDGbWh.js → .setup/directory-config-BytTftz-.mjs} +2 -2
  17. package/dist/{directory-live-C5o1uKlw.js → .setup/directory-live--EGTH0DC.mjs} +4 -4
  18. package/dist/{discord-CmL3ati-.js → .setup/discord-BXpHW-cu.mjs} +89 -39
  19. package/dist/{doctor-DgKMH6N7.js → .setup/doctor-D1R-uFIu.mjs} +6 -6
  20. package/dist/{handle-action.guild-admin-CpEwox_X.js → .setup/handle-action.guild-admin-DcFa8NwA.mjs} +10 -5
  21. package/dist/{live-policy-config-BblutQAq.js → .setup/live-policy-config-eKQ-PLdy.mjs} +1 -1
  22. package/dist/{message-handler-C7FZGKa8.js → .setup/message-handler-X6ejmbtY.mjs} +25 -14
  23. package/dist/{message-handler.preflight-DFpwDW2W.js → .setup/message-handler.preflight-DE_POxFc.mjs} +35 -125
  24. package/dist/.setup/message-handler.preflight-pluralkit-8Xji34AF.mjs +143 -0
  25. package/dist/{message-handler.process-ZKrmmA9D.js → .setup/message-handler.process-CCmIVnxy.mjs} +438 -378
  26. package/dist/{outbound-adapter-C8PTt7_p.js → .setup/outbound-adapter-ClIgmu4F.mjs} +13 -9
  27. package/dist/{outbound-session-route-B0N6os97.js → .setup/outbound-session-route-VulUE0yV.mjs} +138 -11
  28. package/dist/{pluralkit-BiUW53Yn.js → .setup/pluralkit-CdAt1G0P.mjs} +2 -2
  29. package/dist/{preflight-audio-DrnqFA8U.js → .setup/preflight-audio-DHGIHEpv.mjs} +2 -1
  30. package/dist/{probe-BcoN44eK.js → .setup/probe-CupW4we4.mjs} +14 -10
  31. package/dist/{probe.runtime-BnuED0fI.js → .setup/probe.runtime-DBQ_AGPe.mjs} +1 -1
  32. package/dist/{provider-DmRHCZ_K.js → .setup/provider-iOf73HW-.mjs} +885 -557
  33. package/dist/{provider-session.runtime-U1M8_EYY.js → .setup/provider-session.runtime-DrGAYnZv.mjs} +4 -4
  34. package/dist/.setup/provider.runtime-BmjW_pIw.mjs +2 -0
  35. package/dist/{realtime-session.runtime-Bjsk9Q5t.js → .setup/realtime-session.runtime-Dz8uVutq.mjs} +977 -514
  36. package/dist/.setup/receive-recovery-DHst8WRx.mjs +517 -0
  37. package/dist/{resolve-allowlist-common-ChPf0Qy7.js → .setup/resolve-allowlist-common-CwMBzbx9.mjs} +3 -3
  38. package/dist/{resolve-channels-VbpLmUS8.js → .setup/resolve-channels-BbvsLQOZ.mjs} +4 -5
  39. package/dist/{resolve-users-D-wRFsd5.js → .setup/resolve-users-ByFlR7LQ.mjs} +3 -3
  40. package/dist/{retry-DKeoT7UO.js → .setup/retry-BEYkDy0P.mjs} +106 -19
  41. package/dist/{runtime-Dxl-ZOvg.js → .setup/runtime-B8lJfyrA.mjs} +113 -141
  42. package/dist/{runtime-CbknwoBH.js → .setup/runtime-DisDbixd.mjs} +2 -2
  43. package/dist/{security-audit-DKfK-iPY.js → .setup/security-audit-s5w50-Ly.mjs} +1 -1
  44. package/dist/{security-audit.runtime-sKZyKgpx.js → .setup/security-audit.runtime-DHtYenx9.mjs} +1 -1
  45. package/dist/{send-CLpzfzJe.js → .setup/send-CIBzvXjS.mjs} +80 -37
  46. package/dist/{send.components-BWnkX4QN.js → .setup/send.components-ChY21qr-.mjs} +87 -65
  47. package/dist/{send.outbound-BVTWrl_4.js → .setup/send.outbound-QTyuFupn.mjs} +30 -21
  48. package/dist/{send.shared-BHPM3CSl.js → .setup/send.shared-VNvWfX2T.mjs} +15 -12
  49. package/dist/{sender-identity-f3l5OYgV.js → .setup/sender-identity-0Ymgvmaj.mjs} +1 -1
  50. package/dist/.setup/setup-plugin-api-Dvr41dyx.mjs +3 -0
  51. package/dist/{shared-CPPR0Xo4.js → .setup/shared-DHPDaMSx.mjs} +11 -11
  52. package/dist/{subagent-hooks-DfsiwCec.js → .setup/subagent-hooks-CjW7r8Pe.mjs} +16 -4
  53. package/dist/{system-events-B6HkUhF_.js → .setup/system-events-B2YEEMbS.mjs} +2 -2
  54. package/dist/{target-resolver-CoFQ7iSX.js → .setup/target-resolver-BXpy6VT8.mjs} +4 -4
  55. package/dist/.setup/targets-CvemhN3i.mjs +3 -0
  56. package/dist/{thread-bindings-uudC_0TY.js → .setup/thread-bindings-CEh2dhqP.mjs} +6 -6
  57. package/dist/{thread-bindings.manager-BeUxc8nr.js → .setup/thread-bindings.manager-ve-i6oqt.mjs} +100 -46
  58. package/dist/{thread-bindings.session-updates-BwkXpcy0.js → .setup/thread-bindings.session-updates-DCQq1WZ5.mjs} +1 -1
  59. package/dist/{thread-bindings.state-dDn-dwBw.js → .setup/thread-bindings.state-BThFQEga.mjs} +46 -14
  60. package/dist/{transcripts-source-VkgenQv-.js → .setup/transcripts-source-DVegW0WI.mjs} +121 -30
  61. package/dist/{typing-DuBg1U8Q.js → .setup/typing-BKZL5fGj.mjs} +2 -2
  62. package/dist/{voice-runtime-DMYDMkJx.js → .setup/voice-runtime-elTtjEIG.mjs} +773 -773
  63. package/dist/account-inspect-api.js +1 -1
  64. package/dist/action-runtime-api.js +1 -1
  65. package/dist/activities-api.js +1 -1
  66. package/dist/api.js +19 -19
  67. package/dist/channel-config-api.js +1 -1
  68. package/dist/channel-plugin-api.js +1 -1
  69. package/dist/contract-api.js +1 -1
  70. package/dist/directory-contract-api.js +1 -1
  71. package/dist/doctor-contract-api.js +4 -4
  72. package/dist/index.js +1 -1
  73. package/dist/runtime-api.js +22 -22
  74. package/dist/runtime-setter-api.js +1 -1
  75. package/dist/secret-contract-api.js +1 -1
  76. package/dist/security-audit-contract-api.js +1 -1
  77. package/dist/security-contract-api.js +1 -1
  78. package/dist/session-key-api.js +1 -1
  79. package/dist/setup-entry.js +2 -1
  80. package/dist/setup-plugin-api.js +1 -1
  81. package/dist/src/voice/audio-worker.runtime.js +1065 -0
  82. package/dist/subagent-hooks-api.js +5 -4
  83. package/dist/thread-binding-api.js +1 -1
  84. package/dist/transcripts-source-api.js +1 -1
  85. package/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.cjs +8 -4
  86. package/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.js +8 -4
  87. package/node_modules/@napi-rs/wasm-runtime/dist/fs-proxy.cjs +1 -1
  88. package/node_modules/@napi-rs/wasm-runtime/dist/fs.js +770 -695
  89. package/node_modules/@napi-rs/wasm-runtime/fs-proxy.js +3 -2
  90. package/node_modules/@napi-rs/wasm-runtime/package.json +1 -1
  91. package/node_modules/@tybys/wasm-util/LICENSE +21 -0
  92. package/node_modules/@tybys/wasm-util/package.json +1 -1
  93. package/node_modules/@types/node/README.md +1 -1
  94. package/node_modules/@types/node/buffer.d.ts +1 -0
  95. package/node_modules/@types/node/diagnostics_channel.d.ts +4 -4
  96. package/node_modules/@types/node/ffi.d.ts +1 -1
  97. package/node_modules/@types/node/http.d.ts +1 -1
  98. package/node_modules/@types/node/package.json +3 -3
  99. package/node_modules/@types/node/perf_hooks.d.ts +31 -19
  100. package/node_modules/@types/node/quic.d.ts +6 -4
  101. package/node_modules/@types/node/stream/web.d.ts +20 -0
  102. package/node_modules/@types/node/tls.d.ts +26 -15
  103. package/node_modules/@types/node/vfs.d.ts +7 -6
  104. package/node_modules/@types/node/web-globals/streams.d.ts +4 -0
  105. package/node_modules/@types/node/zlib.d.ts +17 -0
  106. package/node_modules/discord-api-types/README.md +3 -2
  107. package/node_modules/discord-api-types/package.json +46 -46
  108. package/node_modules/discord-api-types/rest/v10/interactions.d.ts +1 -0
  109. package/node_modules/discord-api-types/rest/v10/interactions.d.ts.map +1 -1
  110. package/node_modules/discord-api-types/rest/v9/interactions.d.ts +1 -0
  111. package/node_modules/discord-api-types/rest/v9/interactions.d.ts.map +1 -1
  112. package/node_modules/libopus-wasm/CHANGELOG.md +15 -0
  113. package/node_modules/libopus-wasm/README.md +1 -1
  114. package/node_modules/libopus-wasm/dist/discordjs.d.ts.map +1 -1
  115. package/node_modules/libopus-wasm/dist/generated/libopus.generated.mjs +0 -0
  116. package/node_modules/libopus-wasm/dist/index.d.ts.map +1 -1
  117. package/node_modules/libopus-wasm/dist/index.js +37 -18
  118. package/node_modules/libopus-wasm/package.json +13 -13
  119. package/node_modules/typebox/build/compile/validator.d.mts +1 -1
  120. package/node_modules/typebox/build/compile/validator.mjs +1 -1
  121. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +7 -5
  122. package/node_modules/typebox/build/format/iri.mjs +5 -1
  123. package/node_modules/typebox/build/guard/emit.mjs +2 -4
  124. package/node_modules/typebox/build/guard/guard.mjs +6 -18
  125. package/node_modules/typebox/build/guard/string.mjs +16 -24
  126. package/node_modules/typebox/build/schema/build.mjs +2 -2
  127. package/node_modules/typebox/build/schema/check.mjs +1 -1
  128. package/node_modules/typebox/build/schema/compile.d.mts +3 -2
  129. package/node_modules/typebox/build/schema/compile.mjs +8 -8
  130. package/node_modules/typebox/build/schema/engine/_context.d.mts +6 -7
  131. package/node_modules/typebox/build/schema/engine/_context.mjs +23 -15
  132. package/node_modules/typebox/build/schema/engine/_functions.d.mts +2 -2
  133. package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -1
  134. package/node_modules/typebox/build/schema/engine/_reducer.d.mts +3 -3
  135. package/node_modules/typebox/build/schema/engine/_refine.d.mts +5 -5
  136. package/node_modules/typebox/build/schema/engine/_refine.mjs +4 -7
  137. package/node_modules/typebox/build/schema/engine/_stack.d.mts +34 -16
  138. package/node_modules/typebox/build/schema/engine/_stack.mjs +148 -104
  139. package/node_modules/typebox/build/schema/engine/additionalItems.d.mts +4 -4
  140. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +8 -8
  141. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +26 -18
  142. package/node_modules/typebox/build/schema/engine/allOf.d.mts +4 -4
  143. package/node_modules/typebox/build/schema/engine/allOf.mjs +3 -3
  144. package/node_modules/typebox/build/schema/engine/anyOf.d.mts +4 -4
  145. package/node_modules/typebox/build/schema/engine/anyOf.mjs +5 -10
  146. package/node_modules/typebox/build/schema/engine/boolean.d.mts +4 -4
  147. package/node_modules/typebox/build/schema/engine/boolean.mjs +2 -6
  148. package/node_modules/typebox/build/schema/engine/const.d.mts +4 -4
  149. package/node_modules/typebox/build/schema/engine/const.mjs +2 -6
  150. package/node_modules/typebox/build/schema/engine/contains.d.mts +4 -4
  151. package/node_modules/typebox/build/schema/engine/contains.mjs +2 -6
  152. package/node_modules/typebox/build/schema/engine/dependencies.d.mts +4 -4
  153. package/node_modules/typebox/build/schema/engine/dependencies.mjs +3 -6
  154. package/node_modules/typebox/build/schema/engine/dependentRequired.d.mts +4 -4
  155. package/node_modules/typebox/build/schema/engine/dependentRequired.mjs +2 -6
  156. package/node_modules/typebox/build/schema/engine/dependentSchemas.d.mts +4 -4
  157. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +4 -4
  158. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +11 -7
  159. package/node_modules/typebox/build/schema/engine/enum.d.mts +4 -4
  160. package/node_modules/typebox/build/schema/engine/enum.mjs +2 -6
  161. package/node_modules/typebox/build/schema/engine/exclusiveMaximum.d.mts +4 -4
  162. package/node_modules/typebox/build/schema/engine/exclusiveMaximum.mjs +2 -6
  163. package/node_modules/typebox/build/schema/engine/exclusiveMinimum.d.mts +4 -4
  164. package/node_modules/typebox/build/schema/engine/exclusiveMinimum.mjs +2 -6
  165. package/node_modules/typebox/build/schema/engine/format.d.mts +4 -4
  166. package/node_modules/typebox/build/schema/engine/format.mjs +2 -6
  167. package/node_modules/typebox/build/schema/engine/if.d.mts +4 -4
  168. package/node_modules/typebox/build/schema/engine/if.mjs +7 -15
  169. package/node_modules/typebox/build/schema/engine/items.d.mts +4 -4
  170. package/node_modules/typebox/build/schema/engine/items.mjs +1 -1
  171. package/node_modules/typebox/build/schema/engine/maxContains.d.mts +4 -4
  172. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -6
  173. package/node_modules/typebox/build/schema/engine/maxItems.d.mts +4 -4
  174. package/node_modules/typebox/build/schema/engine/maxItems.mjs +2 -6
  175. package/node_modules/typebox/build/schema/engine/maxLength.d.mts +4 -4
  176. package/node_modules/typebox/build/schema/engine/maxLength.mjs +2 -6
  177. package/node_modules/typebox/build/schema/engine/maxProperties.d.mts +4 -4
  178. package/node_modules/typebox/build/schema/engine/maxProperties.mjs +2 -6
  179. package/node_modules/typebox/build/schema/engine/maximum.d.mts +4 -4
  180. package/node_modules/typebox/build/schema/engine/maximum.mjs +2 -6
  181. package/node_modules/typebox/build/schema/engine/minContains.d.mts +4 -4
  182. package/node_modules/typebox/build/schema/engine/minContains.mjs +2 -6
  183. package/node_modules/typebox/build/schema/engine/minItems.d.mts +5 -5
  184. package/node_modules/typebox/build/schema/engine/minItems.mjs +2 -6
  185. package/node_modules/typebox/build/schema/engine/minLength.d.mts +4 -4
  186. package/node_modules/typebox/build/schema/engine/minLength.mjs +2 -6
  187. package/node_modules/typebox/build/schema/engine/minProperties.d.mts +4 -4
  188. package/node_modules/typebox/build/schema/engine/minProperties.mjs +2 -6
  189. package/node_modules/typebox/build/schema/engine/minimum.d.mts +4 -4
  190. package/node_modules/typebox/build/schema/engine/minimum.mjs +2 -6
  191. package/node_modules/typebox/build/schema/engine/multipleOf.d.mts +4 -4
  192. package/node_modules/typebox/build/schema/engine/multipleOf.mjs +2 -6
  193. package/node_modules/typebox/build/schema/engine/not.d.mts +4 -4
  194. package/node_modules/typebox/build/schema/engine/not.mjs +4 -8
  195. package/node_modules/typebox/build/schema/engine/oneOf.d.mts +4 -4
  196. package/node_modules/typebox/build/schema/engine/oneOf.mjs +6 -11
  197. package/node_modules/typebox/build/schema/engine/pattern.d.mts +4 -4
  198. package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -7
  199. package/node_modules/typebox/build/schema/engine/patternProperties.d.mts +4 -4
  200. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +1 -1
  201. package/node_modules/typebox/build/schema/engine/prefixItems.d.mts +4 -4
  202. package/node_modules/typebox/build/schema/engine/prefixItems.mjs +1 -1
  203. package/node_modules/typebox/build/schema/engine/properties.d.mts +4 -4
  204. package/node_modules/typebox/build/schema/engine/properties.mjs +1 -1
  205. package/node_modules/typebox/build/schema/engine/propertyNames.d.mts +4 -4
  206. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +4 -10
  207. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +4 -4
  208. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +11 -7
  209. package/node_modules/typebox/build/schema/engine/ref.d.mts +4 -4
  210. package/node_modules/typebox/build/schema/engine/ref.mjs +19 -15
  211. package/node_modules/typebox/build/schema/engine/required.d.mts +4 -4
  212. package/node_modules/typebox/build/schema/engine/required.mjs +2 -6
  213. package/node_modules/typebox/build/schema/engine/schema.d.mts +7 -7
  214. package/node_modules/typebox/build/schema/engine/schema.mjs +137 -133
  215. package/node_modules/typebox/build/schema/engine/type.d.mts +4 -4
  216. package/node_modules/typebox/build/schema/engine/type.mjs +2 -6
  217. package/node_modules/typebox/build/schema/engine/unevaluatedItems.d.mts +4 -4
  218. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +5 -9
  219. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.d.mts +4 -4
  220. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +5 -9
  221. package/node_modules/typebox/build/schema/engine/uniqueItems.d.mts +4 -4
  222. package/node_modules/typebox/build/schema/engine/uniqueItems.mjs +2 -6
  223. package/node_modules/typebox/build/schema/errors.d.mts +2 -2
  224. package/node_modules/typebox/build/schema/errors.mjs +8 -14
  225. package/node_modules/typebox/build/schema/intern/index.d.mts +1 -0
  226. package/node_modules/typebox/build/schema/intern/index.mjs +1 -0
  227. package/node_modules/typebox/build/schema/intern/intern.d.mts +11 -0
  228. package/node_modules/typebox/build/schema/intern/intern.mjs +293 -0
  229. package/node_modules/typebox/build/schema/meta/draft_2019_09.d.mts +2 -0
  230. package/node_modules/typebox/build/schema/meta/draft_2019_09.mjs +288 -0
  231. package/node_modules/typebox/build/schema/meta/draft_2020_12.d.mts +2 -0
  232. package/node_modules/typebox/build/schema/meta/draft_2020_12.mjs +300 -0
  233. package/node_modules/typebox/build/schema/meta/draft_3.d.mts +2 -0
  234. package/node_modules/typebox/build/schema/meta/draft_3.mjs +143 -0
  235. package/node_modules/typebox/build/schema/meta/draft_4.d.mts +2 -0
  236. package/node_modules/typebox/build/schema/meta/draft_4.mjs +149 -0
  237. package/node_modules/typebox/build/schema/meta/draft_6.d.mts +2 -0
  238. package/node_modules/typebox/build/schema/meta/draft_6.mjs +155 -0
  239. package/node_modules/typebox/build/schema/meta/draft_7.d.mts +2 -0
  240. package/node_modules/typebox/build/schema/meta/draft_7.mjs +172 -0
  241. package/node_modules/typebox/build/schema/meta/index.d.mts +2 -0
  242. package/node_modules/typebox/build/schema/meta/index.mjs +2 -0
  243. package/node_modules/typebox/build/schema/meta/meta.d.mts +9 -0
  244. package/node_modules/typebox/build/schema/meta/meta.mjs +15 -0
  245. package/node_modules/typebox/build/schema/meta/schema.d.mts +6 -0
  246. package/node_modules/typebox/build/schema/meta/schema.mjs +1 -0
  247. package/node_modules/typebox/build/schema/parse.d.mts +1 -0
  248. package/node_modules/typebox/build/schema/parse.mjs +10 -5
  249. package/node_modules/typebox/build/schema/resolve/resolve.d.mts +8 -3
  250. package/node_modules/typebox/build/schema/resolve/resolve.mjs +268 -139
  251. package/node_modules/typebox/build/schema/schema.d.mts +2 -0
  252. package/node_modules/typebox/build/schema/schema.mjs +2 -0
  253. package/node_modules/typebox/build/value/errors/errors.d.mts +2 -12
  254. package/node_modules/typebox/build/value/errors/errors.mjs +2 -7
  255. package/node_modules/typebox/package.json +1 -1
  256. package/node_modules/typebox/readme.md +59 -89
  257. package/node_modules/undici-types/client.d.ts +8 -3
  258. package/node_modules/undici-types/connector.d.ts +1 -0
  259. package/node_modules/undici-types/cookies.d.ts +1 -1
  260. package/node_modules/undici-types/dispatcher.d.ts +3 -3
  261. package/node_modules/undici-types/errors.d.ts +10 -0
  262. package/node_modules/undici-types/fetch.d.ts +5 -1
  263. package/node_modules/undici-types/handlers.d.ts +2 -0
  264. package/node_modules/undici-types/interceptors.d.ts +1 -1
  265. package/node_modules/undici-types/mock-interceptor.d.ts +5 -1
  266. package/node_modules/undici-types/package.json +1 -1
  267. package/node_modules/undici-types/proxy-agent.d.ts +7 -0
  268. package/node_modules/zod/README.md +29 -2
  269. package/node_modules/zod/compile.cjs +96 -0
  270. package/node_modules/zod/compile.d.cts +1 -0
  271. package/node_modules/zod/compile.d.ts +1 -0
  272. package/node_modules/zod/compile.js +52 -0
  273. package/node_modules/zod/index.cjs +21 -2
  274. package/node_modules/zod/index.d.cts +1 -2
  275. package/node_modules/zod/index.d.ts +1 -2
  276. package/node_modules/zod/index.js +5 -2
  277. package/node_modules/zod/locales/index.cjs +19 -0
  278. package/node_modules/zod/mini/index.cjs +19 -0
  279. package/node_modules/zod/package.json +20 -8
  280. package/node_modules/zod/src/compile.ts +56 -0
  281. package/node_modules/zod/src/index.ts +5 -2
  282. package/node_modules/zod/src/v3/ZodError.ts +22 -12
  283. package/node_modules/zod/src/v3/helpers/errorUtil.ts +1 -1
  284. package/node_modules/zod/src/v3/tests/error.test.ts +35 -0
  285. package/node_modules/zod/src/v3/tests/intersection.test.ts +18 -0
  286. package/node_modules/zod/src/v3/tests/language-server.test.ts +1 -2
  287. package/node_modules/zod/src/v3/tests/object.test.ts +3 -6
  288. package/node_modules/zod/src/v3/tests/readonly.test.ts +0 -80
  289. package/node_modules/zod/src/v3/tests/string.test.ts +6 -0
  290. package/node_modules/zod/src/v3/types.ts +5 -5
  291. package/node_modules/zod/src/v4/classic/checks.ts +1 -0
  292. package/node_modules/zod/src/v4/classic/compat.ts +26 -18
  293. package/node_modules/zod/src/v4/classic/deep-partial.ts +76 -0
  294. package/node_modules/zod/src/v4/classic/errors.ts +59 -44
  295. package/node_modules/zod/src/v4/classic/external.ts +14 -9
  296. package/node_modules/zod/src/v4/classic/from-json-schema.ts +363 -78
  297. package/node_modules/zod/src/v4/classic/in-out.ts +45 -0
  298. package/node_modules/zod/src/v4/classic/index.ts +2 -2
  299. package/node_modules/zod/src/v4/classic/iso.ts +2 -72
  300. package/node_modules/zod/src/v4/classic/parse.ts +10 -4
  301. package/node_modules/zod/src/v4/classic/schemas.ts +640 -375
  302. package/node_modules/zod/src/v4/classic/tests/apply.test.ts +27 -0
  303. package/node_modules/zod/src/v4/classic/tests/array.test.ts +2 -2
  304. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +186 -0
  305. package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +36 -1
  306. package/node_modules/zod/src/v4/classic/tests/catch.test.ts +278 -0
  307. package/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts +1 -2
  308. package/node_modules/zod/src/v4/classic/tests/codec.test.ts +2 -1
  309. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +3 -3
  310. package/node_modules/zod/src/v4/classic/tests/credit-card.test.ts +76 -0
  311. package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +985 -0
  312. package/node_modules/zod/src/v4/classic/tests/date.test.ts +30 -0
  313. package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +32 -18
  314. package/node_modules/zod/src/v4/classic/tests/deep-partial.test.ts +380 -0
  315. package/node_modules/zod/src/v4/classic/tests/default-locale.test.ts +32 -0
  316. package/node_modules/zod/src/v4/classic/tests/default.test.ts +46 -0
  317. package/node_modules/zod/src/v4/classic/tests/detached-methods.test.ts +31 -7
  318. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +261 -13
  319. package/node_modules/zod/src/v4/classic/tests/enum.test.ts +20 -0
  320. package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +112 -2
  321. package/node_modules/zod/src/v4/classic/tests/error.test.ts +403 -6
  322. package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +582 -10
  323. package/node_modules/zod/src/v4/classic/tests/function.test.ts +31 -0
  324. package/node_modules/zod/src/v4/classic/tests/global-config.test.ts +2 -9
  325. package/node_modules/zod/src/v4/classic/tests/hash.test.ts +1 -2
  326. package/node_modules/zod/src/v4/classic/tests/iban.test.ts +81 -0
  327. package/node_modules/zod/src/v4/classic/tests/in-out.test.ts +159 -0
  328. package/node_modules/zod/src/v4/classic/tests/index.test.ts +21 -2
  329. package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +319 -0
  330. package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +67 -0
  331. package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +136 -0
  332. package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +215 -0
  333. package/node_modules/zod/src/v4/classic/tests/jitless-allows-eval.test.ts +3 -10
  334. package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +36 -1
  335. package/node_modules/zod/src/v4/classic/tests/literal.test.ts +12 -1
  336. package/node_modules/zod/src/v4/classic/tests/map.test.ts +12 -0
  337. package/node_modules/zod/src/v4/classic/tests/number.test.ts +85 -9
  338. package/node_modules/zod/src/v4/classic/tests/object.test.ts +301 -12
  339. package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +235 -0
  340. package/node_modules/zod/src/v4/classic/tests/optional.test.ts +49 -16
  341. package/node_modules/zod/src/v4/classic/tests/partial.test.ts +51 -4
  342. package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +70 -0
  343. package/node_modules/zod/src/v4/classic/tests/preprocess-types.test.ts +20 -2
  344. package/node_modules/zod/src/v4/classic/tests/properties.test.ts +141 -0
  345. package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +0 -68
  346. package/node_modules/zod/src/v4/classic/tests/record.test.ts +186 -18
  347. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +79 -3
  348. package/node_modules/zod/src/v4/classic/tests/redos.test.ts +68 -0
  349. package/node_modules/zod/src/v4/classic/tests/refine.test.ts +60 -0
  350. package/node_modules/zod/src/v4/classic/tests/set.test.ts +9 -0
  351. package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +19 -0
  352. package/node_modules/zod/src/v4/classic/tests/string.test.ts +222 -6
  353. package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +18 -0
  354. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +44 -3
  355. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +1812 -204
  356. package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +45 -30
  357. package/node_modules/zod/src/v4/classic/tests/union.test.ts +39 -2
  358. package/node_modules/zod/src/v4/classic/tests/validate.test.ts +645 -0
  359. package/node_modules/zod/src/v4/classic/tests/validations.test.ts +2 -2
  360. package/node_modules/zod/src/v4/core/api.ts +87 -35
  361. package/node_modules/zod/src/v4/core/checks.ts +119 -146
  362. package/node_modules/zod/src/v4/core/compile.ts +2313 -0
  363. package/node_modules/zod/src/v4/core/core.ts +99 -22
  364. package/node_modules/zod/src/v4/core/doc.ts +17 -9
  365. package/node_modules/zod/src/v4/core/errors.ts +113 -25
  366. package/node_modules/zod/src/v4/core/index.ts +3 -0
  367. package/node_modules/zod/src/v4/core/json-schema-generator.ts +8 -3
  368. package/node_modules/zod/src/v4/core/json-schema-processors.ts +424 -156
  369. package/node_modules/zod/src/v4/core/json-schema.ts +2 -1
  370. package/node_modules/zod/src/v4/core/memoizer.ts +331 -0
  371. package/node_modules/zod/src/v4/core/parse.ts +164 -50
  372. package/node_modules/zod/src/v4/core/regexes.ts +42 -15
  373. package/node_modules/zod/src/v4/core/registries.ts +2 -2
  374. package/node_modules/zod/src/v4/core/schemas.ts +1000 -538
  375. package/node_modules/zod/src/v4/core/tests/cached.test.ts +54 -0
  376. package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +1004 -0
  377. package/node_modules/zod/src/v4/core/tests/compile-generative.test.ts +445 -0
  378. package/node_modules/zod/src/v4/core/tests/compile-global.test.ts +89 -0
  379. package/node_modules/zod/src/v4/core/tests/compile-off-by-default.test.ts +26 -0
  380. package/node_modules/zod/src/v4/core/tests/compile-stats.test.ts +34 -0
  381. package/node_modules/zod/src/v4/core/tests/compile.test.ts +2036 -0
  382. package/node_modules/zod/src/v4/core/tests/email-regex.test.ts +140 -0
  383. package/node_modules/zod/src/v4/core/tests/locales/el.test.ts +1 -2
  384. package/node_modules/zod/src/v4/core/tests/locales/es.test.ts +1 -2
  385. package/node_modules/zod/src/v4/core/tests/locales/fr.test.ts +3 -3
  386. package/node_modules/zod/src/v4/core/tests/locales/parity.test.ts +42 -0
  387. package/node_modules/zod/src/v4/core/tests/locales/tg.test.ts +85 -0
  388. package/node_modules/zod/src/v4/core/tests/locales/tk.test.ts +69 -0
  389. package/node_modules/zod/src/v4/core/tests/polyfill-collision.test.ts +46 -0
  390. package/node_modules/zod/src/v4/core/tests/treeshake.test.ts +51 -0
  391. package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +133 -0
  392. package/node_modules/zod/src/v4/core/to-json-schema.ts +283 -48
  393. package/node_modules/zod/src/v4/core/util.ts +454 -157
  394. package/node_modules/zod/src/v4/core/versions.ts +2 -2
  395. package/node_modules/zod/src/v4/core/visit.ts +193 -0
  396. package/node_modules/zod/src/v4/index.ts +3 -3
  397. package/node_modules/zod/src/v4/locales/ar.ts +5 -0
  398. package/node_modules/zod/src/v4/locales/az.ts +5 -0
  399. package/node_modules/zod/src/v4/locales/be.ts +12 -0
  400. package/node_modules/zod/src/v4/locales/bg.ts +5 -0
  401. package/node_modules/zod/src/v4/locales/bn.ts +123 -0
  402. package/node_modules/zod/src/v4/locales/ca.ts +5 -0
  403. package/node_modules/zod/src/v4/locales/ckb.ts +140 -0
  404. package/node_modules/zod/src/v4/locales/cs.ts +5 -0
  405. package/node_modules/zod/src/v4/locales/da.ts +7 -2
  406. package/node_modules/zod/src/v4/locales/de.ts +5 -0
  407. package/node_modules/zod/src/v4/locales/el.ts +3 -0
  408. package/node_modules/zod/src/v4/locales/en.ts +17 -4
  409. package/node_modules/zod/src/v4/locales/eo.ts +5 -0
  410. package/node_modules/zod/src/v4/locales/es.ts +4 -0
  411. package/node_modules/zod/src/v4/locales/fa.ts +5 -0
  412. package/node_modules/zod/src/v4/locales/fi.ts +5 -0
  413. package/node_modules/zod/src/v4/locales/fr-CA.ts +5 -0
  414. package/node_modules/zod/src/v4/locales/fr.ts +21 -14
  415. package/node_modules/zod/src/v4/locales/gu.ts +123 -0
  416. package/node_modules/zod/src/v4/locales/he.ts +8 -1
  417. package/node_modules/zod/src/v4/locales/hi.ts +126 -0
  418. package/node_modules/zod/src/v4/locales/hr.ts +4 -0
  419. package/node_modules/zod/src/v4/locales/hu.ts +5 -0
  420. package/node_modules/zod/src/v4/locales/hy.ts +11 -0
  421. package/node_modules/zod/src/v4/locales/id.ts +5 -0
  422. package/node_modules/zod/src/v4/locales/index.ts +11 -0
  423. package/node_modules/zod/src/v4/locales/is.ts +5 -0
  424. package/node_modules/zod/src/v4/locales/it.ts +5 -0
  425. package/node_modules/zod/src/v4/locales/ja.ts +5 -0
  426. package/node_modules/zod/src/v4/locales/ka.ts +5 -0
  427. package/node_modules/zod/src/v4/locales/km.ts +5 -0
  428. package/node_modules/zod/src/v4/locales/kn.ts +126 -0
  429. package/node_modules/zod/src/v4/locales/ko.ts +5 -0
  430. package/node_modules/zod/src/v4/locales/lt.ts +4 -0
  431. package/node_modules/zod/src/v4/locales/mk.ts +5 -0
  432. package/node_modules/zod/src/v4/locales/ms.ts +5 -0
  433. package/node_modules/zod/src/v4/locales/ne.ts +128 -0
  434. package/node_modules/zod/src/v4/locales/nl.ts +5 -0
  435. package/node_modules/zod/src/v4/locales/nn.ts +121 -0
  436. package/node_modules/zod/src/v4/locales/no.ts +7 -2
  437. package/node_modules/zod/src/v4/locales/ota.ts +5 -0
  438. package/node_modules/zod/src/v4/locales/pl.ts +5 -0
  439. package/node_modules/zod/src/v4/locales/ps.ts +5 -0
  440. package/node_modules/zod/src/v4/locales/pt-BR.ts +161 -0
  441. package/node_modules/zod/src/v4/locales/pt.ts +101 -58
  442. package/node_modules/zod/src/v4/locales/ro.ts +3 -0
  443. package/node_modules/zod/src/v4/locales/ru.ts +12 -0
  444. package/node_modules/zod/src/v4/locales/sk.ts +123 -0
  445. package/node_modules/zod/src/v4/locales/sl.ts +5 -0
  446. package/node_modules/zod/src/v4/locales/sv.ts +7 -2
  447. package/node_modules/zod/src/v4/locales/ta.ts +5 -0
  448. package/node_modules/zod/src/v4/locales/tg.ts +135 -0
  449. package/node_modules/zod/src/v4/locales/th.ts +5 -0
  450. package/node_modules/zod/src/v4/locales/tk.ts +113 -0
  451. package/node_modules/zod/src/v4/locales/tr.ts +5 -0
  452. package/node_modules/zod/src/v4/locales/uk.ts +5 -0
  453. package/node_modules/zod/src/v4/locales/ur.ts +5 -0
  454. package/node_modules/zod/src/v4/locales/uz.ts +3 -0
  455. package/node_modules/zod/src/v4/locales/vi.ts +5 -0
  456. package/node_modules/zod/src/v4/locales/yo.ts +5 -0
  457. package/node_modules/zod/src/v4/locales/zh-CN.ts +5 -0
  458. package/node_modules/zod/src/v4/locales/zh-TW.ts +5 -0
  459. package/node_modules/zod/src/v4/mini/checks.ts +1 -0
  460. package/node_modules/zod/src/v4/mini/deep-partial.ts +73 -0
  461. package/node_modules/zod/src/v4/mini/external.ts +12 -1
  462. package/node_modules/zod/src/v4/mini/in-out.ts +45 -0
  463. package/node_modules/zod/src/v4/mini/parse.ts +2 -0
  464. package/node_modules/zod/src/v4/mini/schemas.ts +167 -63
  465. package/node_modules/zod/src/v4/mini/tests/apply.test.ts +33 -0
  466. package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +62 -1
  467. package/node_modules/zod/src/v4/mini/tests/checks.test.ts +14 -0
  468. package/node_modules/zod/src/v4/mini/tests/codec.test.ts +35 -1
  469. package/node_modules/zod/src/v4/mini/tests/computed.test.ts +11 -17
  470. package/node_modules/zod/src/v4/mini/tests/cyclic-data.test.ts +84 -0
  471. package/node_modules/zod/src/v4/mini/tests/deep-partial.test.ts +54 -0
  472. package/node_modules/zod/src/v4/mini/tests/error.test.ts +23 -4
  473. package/node_modules/zod/src/v4/mini/tests/functions.test.ts +9 -0
  474. package/node_modules/zod/src/v4/mini/tests/index.test.ts +158 -5
  475. package/node_modules/zod/src/v4/mini/tests/number.test.ts +14 -0
  476. package/node_modules/zod/src/v4/mini/tests/object.test.ts +65 -0
  477. package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +16 -0
  478. package/node_modules/zod/src/v4/mini/tests/string.test.ts +44 -0
  479. package/node_modules/zod/v3/ZodError.cjs +41 -12
  480. package/node_modules/zod/v3/ZodError.d.cts +1 -1
  481. package/node_modules/zod/v3/ZodError.d.ts +1 -1
  482. package/node_modules/zod/v3/ZodError.js +22 -12
  483. package/node_modules/zod/v3/errors.cjs +19 -0
  484. package/node_modules/zod/v3/external.cjs +19 -0
  485. package/node_modules/zod/v3/helpers/enumUtil.cjs +19 -0
  486. package/node_modules/zod/v3/helpers/errorUtil.cjs +20 -1
  487. package/node_modules/zod/v3/helpers/errorUtil.js +1 -1
  488. package/node_modules/zod/v3/helpers/parseUtil.cjs +19 -0
  489. package/node_modules/zod/v3/helpers/partialUtil.cjs +19 -0
  490. package/node_modules/zod/v3/helpers/typeAliases.cjs +19 -0
  491. package/node_modules/zod/v3/helpers/util.cjs +19 -0
  492. package/node_modules/zod/v3/index.cjs +19 -0
  493. package/node_modules/zod/v3/standard-schema.cjs +19 -0
  494. package/node_modules/zod/v3/types.cjs +26 -5
  495. package/node_modules/zod/v3/types.js +7 -5
  496. package/node_modules/zod/v4/classic/checks.cjs +21 -1
  497. package/node_modules/zod/v4/classic/checks.d.cts +1 -1
  498. package/node_modules/zod/v4/classic/checks.d.ts +1 -1
  499. package/node_modules/zod/v4/classic/checks.js +1 -1
  500. package/node_modules/zod/v4/classic/coerce.cjs +19 -0
  501. package/node_modules/zod/v4/classic/compat.cjs +19 -0
  502. package/node_modules/zod/v4/classic/compat.d.cts +9 -11
  503. package/node_modules/zod/v4/classic/compat.d.ts +9 -11
  504. package/node_modules/zod/v4/classic/deep-partial.cjs +58 -0
  505. package/node_modules/zod/v4/classic/deep-partial.d.cts +14 -0
  506. package/node_modules/zod/v4/classic/deep-partial.d.ts +14 -0
  507. package/node_modules/zod/v4/classic/deep-partial.js +13 -0
  508. package/node_modules/zod/v4/classic/errors.cjs +62 -34
  509. package/node_modules/zod/v4/classic/errors.d.cts +3 -4
  510. package/node_modules/zod/v4/classic/errors.d.ts +3 -4
  511. package/node_modules/zod/v4/classic/errors.js +43 -34
  512. package/node_modules/zod/v4/classic/external.cjs +51 -27
  513. package/node_modules/zod/v4/classic/external.d.cts +5 -2
  514. package/node_modules/zod/v4/classic/external.d.ts +5 -2
  515. package/node_modules/zod/v4/classic/external.js +5 -8
  516. package/node_modules/zod/v4/classic/from-json-schema.cjs +376 -75
  517. package/node_modules/zod/v4/classic/from-json-schema.js +357 -75
  518. package/node_modules/zod/v4/classic/in-out.cjs +82 -0
  519. package/node_modules/zod/v4/classic/in-out.d.cts +8 -0
  520. package/node_modules/zod/v4/classic/in-out.d.ts +8 -0
  521. package/node_modules/zod/v4/classic/in-out.js +36 -0
  522. package/node_modules/zod/v4/classic/index.cjs +21 -2
  523. package/node_modules/zod/v4/classic/index.d.cts +1 -2
  524. package/node_modules/zod/v4/classic/index.d.ts +1 -2
  525. package/node_modules/zod/v4/classic/index.js +2 -2
  526. package/node_modules/zod/v4/classic/iso.cjs +30 -22
  527. package/node_modules/zod/v4/classic/iso.d.cts +2 -17
  528. package/node_modules/zod/v4/classic/iso.d.ts +2 -17
  529. package/node_modules/zod/v4/classic/iso.js +2 -17
  530. package/node_modules/zod/v4/classic/parse.cjs +23 -1
  531. package/node_modules/zod/v4/classic/parse.d.cts +17 -4
  532. package/node_modules/zod/v4/classic/parse.d.ts +17 -4
  533. package/node_modules/zod/v4/classic/parse.js +1 -0
  534. package/node_modules/zod/v4/classic/schemas.cjs +591 -426
  535. package/node_modules/zod/v4/classic/schemas.d.cts +68 -19
  536. package/node_modules/zod/v4/classic/schemas.d.ts +68 -19
  537. package/node_modules/zod/v4/classic/schemas.js +564 -424
  538. package/node_modules/zod/v4/core/api.cjs +66 -24
  539. package/node_modules/zod/v4/core/api.d.cts +22 -12
  540. package/node_modules/zod/v4/core/api.d.ts +22 -12
  541. package/node_modules/zod/v4/core/api.js +44 -24
  542. package/node_modules/zod/v4/core/checks.cjs +88 -128
  543. package/node_modules/zod/v4/core/checks.d.cts +29 -13
  544. package/node_modules/zod/v4/core/checks.d.ts +29 -13
  545. package/node_modules/zod/v4/core/checks.js +68 -127
  546. package/node_modules/zod/v4/core/compile.cjs +1908 -0
  547. package/node_modules/zod/v4/core/compile.d.cts +65 -0
  548. package/node_modules/zod/v4/core/compile.d.ts +65 -0
  549. package/node_modules/zod/v4/core/compile.js +1858 -0
  550. package/node_modules/zod/v4/core/core.cjs +101 -19
  551. package/node_modules/zod/v4/core/core.d.cts +16 -4
  552. package/node_modules/zod/v4/core/core.d.ts +16 -4
  553. package/node_modules/zod/v4/core/core.js +83 -20
  554. package/node_modules/zod/v4/core/doc.cjs +31 -9
  555. package/node_modules/zod/v4/core/doc.d.cts +3 -1
  556. package/node_modules/zod/v4/core/doc.d.ts +3 -1
  557. package/node_modules/zod/v4/core/doc.js +12 -9
  558. package/node_modules/zod/v4/core/errors.cjs +126 -25
  559. package/node_modules/zod/v4/core/errors.d.cts +4 -0
  560. package/node_modules/zod/v4/core/errors.d.ts +4 -0
  561. package/node_modules/zod/v4/core/errors.js +107 -25
  562. package/node_modules/zod/v4/core/index.cjs +24 -1
  563. package/node_modules/zod/v4/core/index.d.cts +3 -0
  564. package/node_modules/zod/v4/core/index.d.ts +3 -0
  565. package/node_modules/zod/v4/core/index.js +3 -0
  566. package/node_modules/zod/v4/core/json-schema-generator.cjs +24 -1
  567. package/node_modules/zod/v4/core/json-schema-generator.d.cts +2 -2
  568. package/node_modules/zod/v4/core/json-schema-generator.d.ts +2 -2
  569. package/node_modules/zod/v4/core/json-schema-generator.js +6 -2
  570. package/node_modules/zod/v4/core/json-schema-processors.cjs +441 -156
  571. package/node_modules/zod/v4/core/json-schema-processors.d.cts +16 -0
  572. package/node_modules/zod/v4/core/json-schema-processors.d.ts +16 -0
  573. package/node_modules/zod/v4/core/json-schema-processors.js +400 -158
  574. package/node_modules/zod/v4/core/json-schema.cjs +19 -0
  575. package/node_modules/zod/v4/core/json-schema.d.cts +2 -1
  576. package/node_modules/zod/v4/core/json-schema.d.ts +2 -1
  577. package/node_modules/zod/v4/core/memoizer.cjs +360 -0
  578. package/node_modules/zod/v4/core/memoizer.d.cts +15 -0
  579. package/node_modules/zod/v4/core/memoizer.d.ts +15 -0
  580. package/node_modules/zod/v4/core/memoizer.js +311 -0
  581. package/node_modules/zod/v4/core/parse.cjs +148 -46
  582. package/node_modules/zod/v4/core/parse.d.cts +14 -11
  583. package/node_modules/zod/v4/core/parse.d.ts +14 -11
  584. package/node_modules/zod/v4/core/parse.js +127 -45
  585. package/node_modules/zod/v4/core/regexes.cjs +54 -17
  586. package/node_modules/zod/v4/core/regexes.d.cts +5 -0
  587. package/node_modules/zod/v4/core/regexes.d.ts +5 -0
  588. package/node_modules/zod/v4/core/regexes.js +32 -15
  589. package/node_modules/zod/v4/core/registries.cjs +19 -0
  590. package/node_modules/zod/v4/core/registries.js +2 -2
  591. package/node_modules/zod/v4/core/schemas.cjs +785 -386
  592. package/node_modules/zod/v4/core/schemas.d.cts +123 -34
  593. package/node_modules/zod/v4/core/schemas.d.ts +123 -34
  594. package/node_modules/zod/v4/core/schemas.js +753 -386
  595. package/node_modules/zod/v4/core/standard-schema.cjs +19 -0
  596. package/node_modules/zod/v4/core/to-json-schema.cjs +269 -45
  597. package/node_modules/zod/v4/core/to-json-schema.d.cts +45 -5
  598. package/node_modules/zod/v4/core/to-json-schema.d.ts +45 -5
  599. package/node_modules/zod/v4/core/to-json-schema.js +247 -44
  600. package/node_modules/zod/v4/core/util.cjs +372 -157
  601. package/node_modules/zod/v4/core/util.d.cts +79 -1
  602. package/node_modules/zod/v4/core/util.d.ts +79 -1
  603. package/node_modules/zod/v4/core/util.js +341 -156
  604. package/node_modules/zod/v4/core/versions.cjs +21 -2
  605. package/node_modules/zod/v4/core/versions.d.cts +1 -1
  606. package/node_modules/zod/v4/core/versions.d.ts +1 -1
  607. package/node_modules/zod/v4/core/versions.js +2 -2
  608. package/node_modules/zod/v4/core/visit.cjs +214 -0
  609. package/node_modules/zod/v4/core/visit.d.cts +30 -0
  610. package/node_modules/zod/v4/core/visit.d.ts +30 -0
  611. package/node_modules/zod/v4/core/visit.js +169 -0
  612. package/node_modules/zod/v4/index.cjs +34 -5
  613. package/node_modules/zod/v4/index.d.cts +2 -2
  614. package/node_modules/zod/v4/index.d.ts +2 -2
  615. package/node_modules/zod/v4/index.js +3 -2
  616. package/node_modules/zod/v4/locales/ar.cjs +5 -0
  617. package/node_modules/zod/v4/locales/ar.js +5 -0
  618. package/node_modules/zod/v4/locales/az.cjs +5 -0
  619. package/node_modules/zod/v4/locales/az.js +5 -0
  620. package/node_modules/zod/v4/locales/be.cjs +12 -0
  621. package/node_modules/zod/v4/locales/be.js +12 -0
  622. package/node_modules/zod/v4/locales/bg.cjs +5 -0
  623. package/node_modules/zod/v4/locales/bg.js +5 -0
  624. package/node_modules/zod/v4/locales/bn.cjs +140 -0
  625. package/node_modules/zod/v4/locales/bn.d.cts +5 -0
  626. package/node_modules/zod/v4/locales/bn.d.ts +4 -0
  627. package/node_modules/zod/v4/locales/bn.js +113 -0
  628. package/node_modules/zod/v4/locales/ca.cjs +5 -0
  629. package/node_modules/zod/v4/locales/ca.js +5 -0
  630. package/node_modules/zod/v4/locales/ckb.cjs +160 -0
  631. package/node_modules/zod/v4/locales/ckb.d.cts +5 -0
  632. package/node_modules/zod/v4/locales/ckb.d.ts +4 -0
  633. package/node_modules/zod/v4/locales/ckb.js +133 -0
  634. package/node_modules/zod/v4/locales/cs.cjs +5 -0
  635. package/node_modules/zod/v4/locales/cs.js +5 -0
  636. package/node_modules/zod/v4/locales/da.cjs +7 -2
  637. package/node_modules/zod/v4/locales/da.js +7 -2
  638. package/node_modules/zod/v4/locales/de.cjs +5 -0
  639. package/node_modules/zod/v4/locales/de.js +5 -0
  640. package/node_modules/zod/v4/locales/el.cjs +3 -0
  641. package/node_modules/zod/v4/locales/el.js +3 -0
  642. package/node_modules/zod/v4/locales/en.cjs +16 -4
  643. package/node_modules/zod/v4/locales/en.js +16 -4
  644. package/node_modules/zod/v4/locales/eo.cjs +5 -0
  645. package/node_modules/zod/v4/locales/eo.js +5 -0
  646. package/node_modules/zod/v4/locales/es.cjs +4 -0
  647. package/node_modules/zod/v4/locales/es.js +4 -0
  648. package/node_modules/zod/v4/locales/fa.cjs +5 -0
  649. package/node_modules/zod/v4/locales/fa.js +5 -0
  650. package/node_modules/zod/v4/locales/fi.cjs +5 -0
  651. package/node_modules/zod/v4/locales/fi.js +5 -0
  652. package/node_modules/zod/v4/locales/fr-CA.cjs +5 -0
  653. package/node_modules/zod/v4/locales/fr-CA.js +5 -0
  654. package/node_modules/zod/v4/locales/fr.cjs +18 -14
  655. package/node_modules/zod/v4/locales/fr.js +18 -14
  656. package/node_modules/zod/v4/locales/gu.cjs +140 -0
  657. package/node_modules/zod/v4/locales/gu.d.cts +5 -0
  658. package/node_modules/zod/v4/locales/gu.d.ts +4 -0
  659. package/node_modules/zod/v4/locales/gu.js +113 -0
  660. package/node_modules/zod/v4/locales/he.cjs +7 -0
  661. package/node_modules/zod/v4/locales/he.js +7 -0
  662. package/node_modules/zod/v4/locales/hi.cjs +138 -0
  663. package/node_modules/zod/v4/locales/hi.d.cts +5 -0
  664. package/node_modules/zod/v4/locales/hi.d.ts +4 -0
  665. package/node_modules/zod/v4/locales/hi.js +111 -0
  666. package/node_modules/zod/v4/locales/hr.cjs +4 -0
  667. package/node_modules/zod/v4/locales/hr.js +4 -0
  668. package/node_modules/zod/v4/locales/hu.cjs +5 -0
  669. package/node_modules/zod/v4/locales/hu.js +5 -0
  670. package/node_modules/zod/v4/locales/hy.cjs +11 -0
  671. package/node_modules/zod/v4/locales/hy.js +11 -0
  672. package/node_modules/zod/v4/locales/id.cjs +5 -0
  673. package/node_modules/zod/v4/locales/id.js +5 -0
  674. package/node_modules/zod/v4/locales/index.cjs +43 -2
  675. package/node_modules/zod/v4/locales/index.d.cts +11 -0
  676. package/node_modules/zod/v4/locales/index.d.ts +11 -0
  677. package/node_modules/zod/v4/locales/index.js +11 -0
  678. package/node_modules/zod/v4/locales/is.cjs +5 -0
  679. package/node_modules/zod/v4/locales/is.js +5 -0
  680. package/node_modules/zod/v4/locales/it.cjs +5 -0
  681. package/node_modules/zod/v4/locales/it.js +5 -0
  682. package/node_modules/zod/v4/locales/ja.cjs +5 -0
  683. package/node_modules/zod/v4/locales/ja.js +5 -0
  684. package/node_modules/zod/v4/locales/ka.cjs +5 -0
  685. package/node_modules/zod/v4/locales/ka.js +5 -0
  686. package/node_modules/zod/v4/locales/km.cjs +5 -0
  687. package/node_modules/zod/v4/locales/km.js +5 -0
  688. package/node_modules/zod/v4/locales/kn.cjs +143 -0
  689. package/node_modules/zod/v4/locales/kn.d.cts +5 -0
  690. package/node_modules/zod/v4/locales/kn.d.ts +4 -0
  691. package/node_modules/zod/v4/locales/kn.js +116 -0
  692. package/node_modules/zod/v4/locales/ko.cjs +5 -0
  693. package/node_modules/zod/v4/locales/ko.js +5 -0
  694. package/node_modules/zod/v4/locales/lt.cjs +4 -0
  695. package/node_modules/zod/v4/locales/lt.js +4 -0
  696. package/node_modules/zod/v4/locales/mk.cjs +5 -0
  697. package/node_modules/zod/v4/locales/mk.js +5 -0
  698. package/node_modules/zod/v4/locales/ms.cjs +5 -0
  699. package/node_modules/zod/v4/locales/ms.js +5 -0
  700. package/node_modules/zod/v4/locales/ne.cjs +138 -0
  701. package/node_modules/zod/v4/locales/ne.d.cts +5 -0
  702. package/node_modules/zod/v4/locales/ne.d.ts +4 -0
  703. package/node_modules/zod/v4/locales/ne.js +111 -0
  704. package/node_modules/zod/v4/locales/nl.cjs +5 -0
  705. package/node_modules/zod/v4/locales/nl.js +5 -0
  706. package/node_modules/zod/v4/locales/nn.cjs +140 -0
  707. package/node_modules/zod/v4/locales/nn.d.cts +5 -0
  708. package/node_modules/zod/v4/locales/nn.d.ts +4 -0
  709. package/node_modules/zod/v4/locales/nn.js +113 -0
  710. package/node_modules/zod/v4/locales/no.cjs +7 -2
  711. package/node_modules/zod/v4/locales/no.js +7 -2
  712. package/node_modules/zod/v4/locales/ota.cjs +5 -0
  713. package/node_modules/zod/v4/locales/ota.js +5 -0
  714. package/node_modules/zod/v4/locales/pl.cjs +5 -0
  715. package/node_modules/zod/v4/locales/pl.js +5 -0
  716. package/node_modules/zod/v4/locales/ps.cjs +5 -0
  717. package/node_modules/zod/v4/locales/ps.js +5 -0
  718. package/node_modules/zod/v4/locales/pt-BR.cjs +170 -0
  719. package/node_modules/zod/v4/locales/pt-BR.d.cts +5 -0
  720. package/node_modules/zod/v4/locales/pt-BR.d.ts +4 -0
  721. package/node_modules/zod/v4/locales/pt-BR.js +143 -0
  722. package/node_modules/zod/v4/locales/pt.cjs +89 -55
  723. package/node_modules/zod/v4/locales/pt.js +89 -55
  724. package/node_modules/zod/v4/locales/ro.cjs +3 -0
  725. package/node_modules/zod/v4/locales/ro.js +3 -0
  726. package/node_modules/zod/v4/locales/ru.cjs +12 -0
  727. package/node_modules/zod/v4/locales/ru.js +12 -0
  728. package/node_modules/zod/v4/locales/sk.cjs +143 -0
  729. package/node_modules/zod/v4/locales/sk.d.cts +5 -0
  730. package/node_modules/zod/v4/locales/sk.d.ts +4 -0
  731. package/node_modules/zod/v4/locales/sk.js +116 -0
  732. package/node_modules/zod/v4/locales/sl.cjs +5 -0
  733. package/node_modules/zod/v4/locales/sl.js +5 -0
  734. package/node_modules/zod/v4/locales/sv.cjs +7 -2
  735. package/node_modules/zod/v4/locales/sv.js +7 -2
  736. package/node_modules/zod/v4/locales/ta.cjs +5 -0
  737. package/node_modules/zod/v4/locales/ta.js +5 -0
  738. package/node_modules/zod/v4/locales/tg.cjs +144 -0
  739. package/node_modules/zod/v4/locales/tg.d.cts +5 -0
  740. package/node_modules/zod/v4/locales/tg.d.ts +4 -0
  741. package/node_modules/zod/v4/locales/tg.js +117 -0
  742. package/node_modules/zod/v4/locales/th.cjs +5 -0
  743. package/node_modules/zod/v4/locales/th.js +5 -0
  744. package/node_modules/zod/v4/locales/tk.cjs +134 -0
  745. package/node_modules/zod/v4/locales/tk.d.cts +5 -0
  746. package/node_modules/zod/v4/locales/tk.d.ts +4 -0
  747. package/node_modules/zod/v4/locales/tk.js +107 -0
  748. package/node_modules/zod/v4/locales/tr.cjs +5 -0
  749. package/node_modules/zod/v4/locales/tr.js +5 -0
  750. package/node_modules/zod/v4/locales/uk.cjs +5 -0
  751. package/node_modules/zod/v4/locales/uk.js +5 -0
  752. package/node_modules/zod/v4/locales/ur.cjs +5 -0
  753. package/node_modules/zod/v4/locales/ur.js +5 -0
  754. package/node_modules/zod/v4/locales/uz.cjs +3 -0
  755. package/node_modules/zod/v4/locales/uz.js +3 -0
  756. package/node_modules/zod/v4/locales/vi.cjs +5 -0
  757. package/node_modules/zod/v4/locales/vi.js +5 -0
  758. package/node_modules/zod/v4/locales/yo.cjs +5 -0
  759. package/node_modules/zod/v4/locales/yo.js +5 -0
  760. package/node_modules/zod/v4/locales/zh-CN.cjs +5 -0
  761. package/node_modules/zod/v4/locales/zh-CN.js +5 -0
  762. package/node_modules/zod/v4/locales/zh-TW.cjs +5 -0
  763. package/node_modules/zod/v4/locales/zh-TW.js +5 -0
  764. package/node_modules/zod/v4/mini/checks.cjs +21 -1
  765. package/node_modules/zod/v4/mini/checks.d.cts +1 -1
  766. package/node_modules/zod/v4/mini/checks.d.ts +1 -1
  767. package/node_modules/zod/v4/mini/checks.js +1 -1
  768. package/node_modules/zod/v4/mini/coerce.cjs +19 -0
  769. package/node_modules/zod/v4/mini/deep-partial.cjs +58 -0
  770. package/node_modules/zod/v4/mini/deep-partial.d.cts +14 -0
  771. package/node_modules/zod/v4/mini/deep-partial.d.ts +14 -0
  772. package/node_modules/zod/v4/mini/deep-partial.js +13 -0
  773. package/node_modules/zod/v4/mini/external.cjs +33 -1
  774. package/node_modules/zod/v4/mini/external.d.cts +5 -2
  775. package/node_modules/zod/v4/mini/external.d.ts +5 -2
  776. package/node_modules/zod/v4/mini/external.js +3 -1
  777. package/node_modules/zod/v4/mini/in-out.cjs +82 -0
  778. package/node_modules/zod/v4/mini/in-out.d.cts +8 -0
  779. package/node_modules/zod/v4/mini/in-out.d.ts +8 -0
  780. package/node_modules/zod/v4/mini/in-out.js +36 -0
  781. package/node_modules/zod/v4/mini/index.cjs +19 -0
  782. package/node_modules/zod/v4/mini/iso.cjs +19 -0
  783. package/node_modules/zod/v4/mini/parse.cjs +22 -1
  784. package/node_modules/zod/v4/mini/parse.d.cts +1 -1
  785. package/node_modules/zod/v4/mini/parse.d.ts +1 -1
  786. package/node_modules/zod/v4/mini/parse.js +1 -1
  787. package/node_modules/zod/v4/mini/schemas.cjs +117 -53
  788. package/node_modules/zod/v4/mini/schemas.d.cts +49 -14
  789. package/node_modules/zod/v4/mini/schemas.d.ts +49 -14
  790. package/node_modules/zod/v4/mini/schemas.js +92 -51
  791. package/node_modules/zod/v4-mini/index.cjs +19 -0
  792. package/openclaw.plugin.json +3 -4
  793. package/package.json +13 -8
  794. package/dist/channel-type-CVLZyGYS.js +0 -7
  795. package/dist/message-handler.history-CJOsN9w5.js +0 -28
  796. package/dist/outbound-components-DrlHcWfM.js +0 -100
  797. package/dist/provider.runtime-CqfE-RvC.js +0 -2
  798. package/dist/targets-Cm6aV9nJ.js +0 -3
  799. package/node_modules/discord-api-types/CHANGELOG.md +0 -2514
  800. package/node_modules/discord-api-types/scripts/versions.mjs +0 -46
  801. package/node_modules/zod/src/v4/core/config.ts +0 -15
  802. /package/dist/{accounts-CwJQoLjM.js → .setup/accounts-CwJQoLjM.mjs} +0 -0
  803. /package/dist/{active-turn-thread-route-fmHl1HNd.js → .setup/active-turn-thread-route-fmHl1HNd.mjs} +0 -0
  804. /package/dist/{agent-components.runtime-CEPrf2SY.js → .setup/agent-components.runtime-CEPrf2SY.mjs} +0 -0
  805. /package/dist/{channel-access-C12aDZ0p.js → .setup/channel-access-C12aDZ0p.mjs} +0 -0
  806. /package/dist/{command-deploy-store-DFkBTViB.js → .setup/command-deploy-store-DFkBTViB.mjs} +0 -0
  807. /package/dist/{command-owners-D78sAoOz.js → .setup/command-owners-D78sAoOz.mjs} +0 -0
  808. /package/dist/{doctor-contract-Co5vRCZ6.js → .setup/doctor-contract-Co5vRCZ6.mjs} +0 -0
  809. /package/dist/{model-picker-preference-primitives-BHT1LkR_.js → .setup/model-picker-preference-primitives-BHT1LkR_.mjs} +0 -0
  810. /package/dist/{presence-cache-dYSHPWMx.js → .setup/presence-cache-dYSHPWMx.mjs} +0 -0
  811. /package/dist/{runtime-DgnVQ7zW.js → .setup/runtime-DgnVQ7zW.mjs} +0 -0
  812. /package/dist/{secret-config-contract-DFu9hfU8.js → .setup/secret-config-contract-DFu9hfU8.mjs} +0 -0
  813. /package/dist/{security-contract-DSHk7I2w.js → .setup/security-contract-DSHk7I2w.mjs} +0 -0
  814. /package/dist/{security-doctor-nGgPm65L.js → .setup/security-doctor-nGgPm65L.mjs} +0 -0
  815. /package/dist/{session-contract-BO5tlIdl.js → .setup/session-contract-BO5tlIdl.mjs} +0 -0
  816. /package/dist/{session-key-normalization-wJgsKPNF.js → .setup/session-key-normalization-wJgsKPNF.mjs} +0 -0
  817. /package/dist/{thread-binding-api-BDZJD4na.js → .setup/thread-binding-api-BDZJD4na.mjs} +0 -0
  818. /package/dist/{timeouts-D86uWLt_.js → .setup/timeouts-D86uWLt_.mjs} +0 -0
@@ -1,47 +1,48 @@
1
- import { C as Command, D as User, E as Message, I as Button, J as TextDisplay, K as Separator, N as Modal, O as hasDiscordV2Components, R as Container, T as Guild, W as Row, Z as BaseMessageInteractiveComponent, a as MessageCreateListener, c as PresenceUpdateListener, d as ThreadDeleteListener, f as ThreadUpdateListener, h as Plugin, i as InteractionCreateListener, l as ReadyListener, m as Client, n as GuildCreateListener, o as MessageReactionAddListener, q as StringSelectMenu, r as GuildDeleteListener, s as MessageReactionRemoveListener, t as discord_exports, v as RateLimitError, w as CommandWithSubcommands } from "./discord-CmL3ati-.js";
2
- import { C as parseDiscordActivityCustomIdForInteraction, D as parseDiscordModalCustomIdForInteraction, E as parseDiscordModalCustomId, O as decodeCustomIdComponent, T as parseDiscordComponentCustomIdForInteraction, c as parseExecApprovalData, k as encodeCustomIdComponent, o as parseDiscordQuestionData, w as parseDiscordComponentCustomId, y as buildDiscordActivityCustomId } from "./components-DBFTIN6P.js";
3
- import { S as resolveTimestampMs, _ as resolveGroupDmAllow, a as normalizeDiscordSlug, b as formatDiscordUserTag, c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordGuildEntry, f as resolveDiscordMemberAccessState, h as resolveDiscordOwnerAllowFrom, i as normalizeDiscordDisplaySlug, l as resolveDiscordChannelPolicyCommandAuthorizer, m as resolveDiscordOwnerAccess, n as isDiscordGroupAllowedByPolicy, o as resolveDiscordAllowListMatch, p as resolveDiscordMemberAllowed, r as normalizeDiscordAllowList, s as resolveDiscordChannelConfig, v as shouldEmitDiscordReactionNotification, y as formatDiscordReactionEmoji } from "./allow-list-DWEio925.js";
4
- import { c as resolveDiscordAccount, f as resolveDiscordAccountDmPolicy, h as resolveDiscordToken, l as resolveDiscordAccountAllowFrom, m as normalizeDiscordToken, o as mergeDiscordAccountConfig, p as resolveDiscordMaxLinesPerMessage } from "./accounts-CwJQoLjM.js";
5
- import { a as resolveDiscordComponentEntryWithPersistence, o as resolveDiscordModalEntryWithPersistence, t as editDiscordComponentMessage } from "./send.components-BWnkX4QN.js";
6
- import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.js";
7
- import { a as isDiscordRateLimitResponseBody, o as summarizeDiscordResponseBody } from "./api-LIV--eMq.js";
8
- import { o as chunkDiscordTextWithMode } from "./retry-DKeoT7UO.js";
9
- import { B as validateDiscordProxyUrl, G as unregisterGateway, P as createDiscordRestClient, R as DISCORD_REST_TIMEOUT_MS, V as withValidatedDiscordProxy, W as registerGateway, b as canViewDiscordGuildChannel, w as hasAnyChannelPermissionDiscord } from "./send.shared-BHPM3CSl.js";
10
- import { o as formatMention, t as sendMessageDiscord } from "./send.outbound-BVTWrl_4.js";
11
- import { t as isDiscordThreadChannelType } from "./channel-type-CVLZyGYS.js";
12
- import { n as getDiscordActivitiesRuntime } from "./runtime-CbknwoBH.js";
13
- import { t as resolveDiscordCommandOwnerAllowFrom } from "./command-owners-D78sAoOz.js";
14
- import { n as resolveDiscordChannelInfoSafe, o as resolveDiscordChannelTopicSafe, r as resolveDiscordChannelNameSafe } from "./channel-access-C12aDZ0p.js";
15
- import { T as resolveDiscordMessageStickers, a as authorizeDiscordVoiceIngress, c as resolveDiscordThreadLikeChannelContext, i as resolveDiscordVoiceEnabled, l as resolveFetchedDiscordThreadLikeChannelContext, o as resolveDiscordVoiceAccess, r as setDiscordTranscriptsVoiceManager } from "./transcripts-source-VkgenQv-.js";
16
- import { i as setPresence, t as clearPresences } from "./presence-cache-dYSHPWMx.js";
17
- import { _ as readMessagesDiscord, s as sendVoiceMessageDiscord } from "./send-CLpzfzJe.js";
18
- import { c as raceWithTimeout, u as withAbortTimeout } from "./timeouts-D86uWLt_.js";
19
- import { S as isDiscordExecApprovalClientEnabled, b as getDiscordExecApprovalApprovers, c as resolveDiscordEffectiveRoute, i as buildDiscordConversationRouteContext, n as DISCORD_APPROVAL_ALLOWED_MENTIONS, o as resolveDiscordBoundConversationRoute, r as formatDiscordApprovalDisplayValue, u as resolveDiscordConversationIdentity } from "./outbound-session-route-B0N6os97.js";
20
- import { n as discordIngressIdentity, t as selectDiscordLivePolicyConfig } from "./live-policy-config-BblutQAq.js";
21
- import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-VbpLmUS8.js";
22
- import { t as resolveDiscordUserAllowlist } from "./resolve-users-D-wRFsd5.js";
23
- import { a as isThreadArchived, l as formatThreadBindingDurationLabel, r as getThreadBindingManager } from "./thread-bindings.manager-BeUxc8nr.js";
24
- import { a as probeDiscordApplicationId, r as parseApplicationIdFromToken } from "./probe-BcoN44eK.js";
25
- import { i as sanitizeRecentModels, n as normalizeModelRef, r as preferenceTimestampMs, t as buildPreferenceModelKey } from "./model-picker-preference-primitives-BHT1LkR_.js";
26
- import { t as resolveDiscordSenderIdentity } from "./sender-identity-f3l5OYgV.js";
1
+ import { D as Message, E as Guild, G as Row, J as StringSelectMenu, L as Button, O as User, P as Modal, Q as BaseMessageInteractiveComponent, T as CommandWithSubcommands, Y as TextDisplay, a as MessageCreateListener, c as PresenceUpdateListener, d as ThreadDeleteListener, f as ThreadUpdateListener, h as Plugin, i as InteractionCreateListener, k as hasDiscordV2Components, l as ReadyListener, m as Client, n as GuildCreateListener, o as MessageReactionAddListener, q as Separator, r as GuildDeleteListener, s as MessageReactionRemoveListener, t as discord_exports, v as RateLimitError, w as Command, z as Container } from "./discord-BXpHW-cu.mjs";
2
+ import { C as parseDiscordActivityCustomIdForInteraction, D as parseDiscordModalCustomIdForInteraction, E as parseDiscordModalCustomId, O as decodeCustomIdComponent, T as parseDiscordComponentCustomIdForInteraction, c as parseExecApprovalData, d as buildDiscordComponentMessage, k as encodeCustomIdComponent, o as parseDiscordQuestionData, w as parseDiscordComponentCustomId, y as buildDiscordActivityCustomId } from "./components-yBEb75bB.mjs";
3
+ import { C as resolveTimestampMs, E as getDiscordEndpointRuntime, T as assertDiscordEndpointGatewayUrl, a as normalizeDiscordDisplaySlug, b as formatDiscordReactionEmoji, c as resolveDiscordChannelConfig, f as resolveDiscordGuildEntry, g as resolveDiscordOwnerAllowFrom, h as resolveDiscordOwnerAccess, i as normalizeDiscordAllowList, l as resolveDiscordChannelConfigWithFallback, m as resolveDiscordMemberAllowed, o as normalizeDiscordSlug, p as resolveDiscordMemberAccessState, r as isDiscordGroupAllowedByPolicy, s as resolveDiscordAllowListMatch, t as isDiscordThreadChannelType, u as resolveDiscordChannelPolicyCommandAuthorizer, v as resolveGroupDmAllow, x as formatDiscordUserTag, y as shouldEmitDiscordReactionNotification } from "./channel-type-DKnjV1XW.mjs";
4
+ import { c as resolveDiscordAccount, f as resolveDiscordAccountDmPolicy, h as resolveDiscordToken, l as resolveDiscordAccountAllowFrom, m as normalizeDiscordToken, o as mergeDiscordAccountConfig, p as resolveDiscordMaxLinesPerMessage } from "./accounts-CwJQoLjM.mjs";
5
+ import { a as registerDiscordComponentEntries, o as resolveDiscordComponentEntryWithPersistence, s as resolveDiscordModalEntryWithPersistence, t as editDiscordComponentMessage } from "./send.components-ChY21qr-.mjs";
6
+ import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.mjs";
7
+ import { a as isDiscordRateLimitResponseBody, o as summarizeDiscordResponseBody } from "./api-CBK9zcq5.mjs";
8
+ import { o as chunkDiscordTextWithMode } from "./retry-BEYkDy0P.mjs";
9
+ import { B as validateDiscordProxyUrl, G as unregisterGateway, P as createDiscordRestClient, R as DISCORD_REST_TIMEOUT_MS, V as withValidatedDiscordProxy, W as registerGateway, b as canViewDiscordGuildChannel, w as hasAnyChannelPermissionDiscord } from "./send.shared-VNvWfX2T.mjs";
10
+ import { o as formatMention, t as sendMessageDiscord } from "./send.outbound-QTyuFupn.mjs";
11
+ import { n as getDiscordActivitiesRuntime } from "./runtime-DisDbixd.mjs";
12
+ import { t as resolveDiscordCommandOwnerAllowFrom } from "./command-owners-D78sAoOz.mjs";
13
+ import { n as resolveDiscordChannelInfoSafe, o as resolveDiscordChannelTopicSafe, r as resolveDiscordChannelNameSafe } from "./channel-access-C12aDZ0p.mjs";
14
+ import { O as resolveDiscordMessageStickers, c as authorizeDiscordVoiceIngress, d as resolveDiscordThreadLikeChannelContext, f as resolveFetchedDiscordThreadLikeChannelContext, i as setDiscordTranscriptsVoiceManager, l as resolveDiscordVoiceAccess, s as resolveDiscordVoiceEnabled } from "./transcripts-source-DVegW0WI.mjs";
15
+ import { i as setPresence, t as clearPresences } from "./presence-cache-dYSHPWMx.mjs";
16
+ import { _ as readMessagesDiscord, s as sendVoiceMessageDiscord } from "./send-CIBzvXjS.mjs";
17
+ import { c as raceWithTimeout, u as withAbortTimeout } from "./timeouts-D86uWLt_.mjs";
18
+ import { D as isDiscordExecApprovalClientEnabled, T as getDiscordExecApprovalApprovers, a as resolveDiscordComponentSpec, c as formatDiscordApprovalDisplayValue, d as resolveDiscordBoundConversationRoute, h as resolveDiscordConversationIdentity, l as buildDiscordConversationRouteContext, n as DISCORD_PRESENTATION_CAPABILITIES, p as resolveDiscordEffectiveRoute, r as buildDiscordPresentationPayload, s as DISCORD_APPROVAL_ALLOWED_MENTIONS, u as buildDiscordRoutePeer } from "./outbound-session-route-VulUE0yV.mjs";
19
+ import { n as discordIngressIdentity, t as selectDiscordLivePolicyConfig } from "./live-policy-config-eKQ-PLdy.mjs";
20
+ import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-BbvsLQOZ.mjs";
21
+ import { t as resolveDiscordUserAllowlist } from "./resolve-users-ByFlR7LQ.mjs";
22
+ import { o as isThreadArchived, r as getThreadBindingManager, u as formatThreadBindingDurationLabel } from "./thread-bindings.manager-ve-i6oqt.mjs";
23
+ import { a as probeDiscordApplicationId, r as parseApplicationIdFromToken } from "./probe-CupW4we4.mjs";
24
+ import { i as sanitizeRecentModels, n as normalizeModelRef, r as preferenceTimestampMs, t as buildPreferenceModelKey } from "./model-picker-preference-primitives-BHT1LkR_.mjs";
25
+ import { t as resolveDiscordSenderIdentity } from "./sender-identity-0Ymgvmaj.mjs";
26
+ import { n as hasDiscordApprovalControl, t as discordApprovalMessageUpdates } from "./approval-message-updates-jf9zMaIC.mjs";
27
27
  import { createRequire } from "node:module";
28
28
  import { logDebug, logError } from "openclaw/plugin-sdk/logging-core";
29
29
  import { ApplicationCommandOptionType, ButtonStyle, ChannelType, ComponentType, GatewayCloseCodes, GatewayCloseCodes as GatewayCloseCodes$1, GatewayDispatchEvents, GatewayIntentBits, GatewayOpcodes, PermissionFlagsBits } from "discord-api-types/v10";
30
30
  import { Type } from "typebox";
31
31
  import { Check, Errors } from "typebox/value";
32
32
  import { createHash, randomUUID } from "node:crypto";
33
- import { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, asSafeIntegerInRange, parseFiniteNumber, parseStrictInteger, parseStrictPositiveInteger, resolveDateTimestampMs, resolveTimestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
33
+ import { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, asSafeIntegerInRange, parseFiniteNumber, parseStrictInteger, parseStrictPositiveInteger, resolveDateTimestampMs, resolvePromptHistoryLimit, resolveTimestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
34
34
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
35
35
  import { inspect } from "node:util";
36
+ import { createHttp1EnvHttpProxyAgent, createHttp1ProxyAgent, createNodeProxyAgent, resolveEnvHttpProxyAgentOptions, wrapFetchWithAbortSignal } from "openclaw/plugin-sdk/fetch-runtime";
36
37
  import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
37
- import { PlatformMessageNotDispatchedError, formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
38
- import { fetchWithSsrFGuard, formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/ssrf-runtime";
38
+ import { fetchWithSsrFGuard, formatErrorMessage, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
39
+ import { PlatformMessageNotDispatchedError, formatErrorMessage as formatErrorMessage$1, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
39
40
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
40
41
  import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
41
42
  import { asFiniteNumber, asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, parseFiniteNumber as parseFiniteNumber$1, parseStrictNonNegativeInteger as parseStrictNonNegativeInteger$1, summarizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
42
43
  import { createRuntimeConfigReader, getRuntimeConfig, getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
43
- import { resolveSendableOutboundReplyParts, resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
44
- import { createHttp1EnvHttpProxyAgent, createHttp1ProxyAgent, createNodeProxyAgent, resolveEnvHttpProxyAgentOptions, wrapFetchWithAbortSignal } from "openclaw/plugin-sdk/fetch-runtime";
44
+ import { renderPresentationForDelivery } from "openclaw/plugin-sdk/interactive-runtime";
45
+ import { hasOutboundReplyContent, resolveSendableOutboundReplyParts, resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
45
46
  import { createNonExitingRuntime, createSubsystemLogger, danger, formatDurationSeconds, isVerbose, logVerbose, shouldLogVerbose, sleepWithAbort, warn } from "openclaw/plugin-sdk/runtime-env";
46
47
  import { sliceUtf16Safe, truncateUtf16Safe, withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
47
48
  import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary, canonicalizeAllowlistWithResolvedIds, patchAllowlistUsersInConfigEntries, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
@@ -52,23 +53,23 @@ import { buildOutboundSessionContext, listMessageReceiptPlatformIds, resolveChan
52
53
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
53
54
  import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
54
55
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
55
- import { buildCommandTextFromArgs, findCommandByNativeName, formatCommandArgMenuTitle, listChatCommands, listNativeCommandSpecsForConfig, listSkillCommandsForAgents, resolveCommandAuthorizedFromAuthorizers, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride, serializeCommandArgs } from "openclaw/plugin-sdk/command-auth-native";
56
+ import { buildCommandTextFromArgs, findCommandByNativeName, formatCommandArgMenuTitle, listChatCommands, listNativeCommandSpecsForConfig, listSkillCommandsForAgents, resolveCommandAuthorization, resolveCommandAuthorizedFromAuthorizers, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride, serializeCommandArgs } from "openclaw/plugin-sdk/command-auth-native";
56
57
  import { GROUP_POLICY_BLOCKED_LABEL, resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
57
- import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime";
58
- import { createChannelPartialDeliveryError, dispatchChannelInboundTurn, formatInboundEnvelope, hasVisibleInboundReplyDispatch, isChannelPartialDeliveryError, resolveEnvelopeFormatOptions, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent } from "openclaw/plugin-sdk/channel-inbound";
58
+ import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
59
+ import { buildChannelInboundEventContext, createChannelPartialDeliveryError, createCommandTurnContext, dispatchChannelInboundTurn, formatInboundEnvelope, hasVisibleInboundReplyDispatch, isChannelPartialDeliveryError, resolveEnvelopeFormatOptions, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent } from "openclaw/plugin-sdk/channel-inbound";
59
60
  import path from "node:path";
60
61
  import { resolvePinnedMainDmOwnerFromAllowlist as resolvePinnedMainDmOwnerFromAllowlist$1 } from "openclaw/plugin-sdk/security-runtime";
61
62
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
62
63
  import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
63
64
  import { buildPairingReply, upsertChannelPairingRequest, upsertChannelPairingRequest as upsertChannelPairingRequest$1 } from "openclaw/plugin-sdk/conversation-runtime";
64
- import * as conversationRuntime from "openclaw/plugin-sdk/conversation-binding-runtime";
65
+ import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute } from "openclaw/plugin-sdk/conversation-binding-runtime";
65
66
  import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
66
- import { createChannelIngressResolver, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
67
- import { clearExpiredCooldowns, ensureAuthProfileStore, formatReasoningMessage, getPreparedModelCatalogSnapshot, isProfileInCooldown, listAgentIds, loadPreparedModelCatalog, resolveAgentAvatar, resolveAgentDir, resolveDefaultModelForAgent, resolveHumanDelayConfig, resolveProfilesUnavailableReason } from "openclaw/plugin-sdk/agent-runtime";
67
+ import { readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
68
68
  import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
69
69
  import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "openclaw/plugin-sdk/native-command-config-runtime";
70
70
  import { requestHeartbeat } from "openclaw/plugin-sdk/heartbeat-runtime";
71
71
  import { enqueueRoutedSystemEvent, enqueueRoutedSystemEvent as enqueueRoutedSystemEvent$1 } from "openclaw/plugin-sdk/system-event-runtime";
72
+ import { clearExpiredCooldowns, ensureAuthProfileStore, formatReasoningMessage, getPreparedModelCatalogSnapshot, isProfileInCooldown, listAgentIds, loadPreparedModelCatalog, resolveAgentAvatar, resolveAgentDir, resolveDefaultModelForAgent, resolveHumanDelayConfig, resolveProfilesUnavailableReason } from "openclaw/plugin-sdk/agent-runtime";
72
73
  import { deleteSessionEntry, getSessionEntry, listSessionEntries, readSessionUpdatedAt as readSessionUpdatedAt$1, resolveStorePath, resolveStorePath as resolveStorePath$1 } from "openclaw/plugin-sdk/session-store-runtime";
73
74
  import { captureHttpExchange, captureWsEvent, resolveDebugProxySettings, resolveEffectiveDebugProxyUrl } from "openclaw/plugin-sdk/proxy-capture";
74
75
  import { resolveRequestUrl } from "openclaw/plugin-sdk/request-url";
@@ -78,6 +79,7 @@ import * as dns from "node:dns";
78
79
  import { buildCommandTextFromArgs as buildCommandTextFromArgs$1, findCommandByNativeName as findCommandByNativeName$1, mergeNativeCommandSpecs, parseCommandArgs, resolveCommandArgChoices, resolveCommandArgMenu, serializeCommandArgs as serializeCommandArgs$1 } from "openclaw/plugin-sdk/native-command-registry";
79
80
  import { PLUGIN_COMMAND_DISPATCH } from "openclaw/plugin-sdk/plugin-command-runtime";
80
81
  import { resolveDirectStatusReplyForSession } from "openclaw/plugin-sdk/command-status-runtime";
82
+ import * as modelsProviderRuntime from "openclaw/plugin-sdk/models-provider-runtime";
81
83
  import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
82
84
  import { EventEmitter } from "node:events";
83
85
  import { Agent as Agent$1 } from "node:https";
@@ -176,7 +178,7 @@ function resolveDiscordOnlinePresenceEvent(params) {
176
178
  //#region extensions/discord/src/monitor/presence-cooldown-store.ts
177
179
  const DISCORD_PRESENCE_COOLDOWN_MAX_ENTRIES = 25e3;
178
180
  function openDiscordPresenceCooldownStore() {
179
- return getDiscordRuntime().state.openSyncKeyedStore({
181
+ return getDiscordRuntime().state.openKeyedStore({
180
182
  namespace: "presence-greeting-cooldowns",
181
183
  maxEntries: DISCORD_PRESENCE_COOLDOWN_MAX_ENTRIES,
182
184
  overflowPolicy: "reject-new",
@@ -379,7 +381,7 @@ function createDiscordDynamicAccessGroupResolver(params) {
379
381
  };
380
382
  }
381
383
  function createDiscordIngressResolver(params) {
382
- return createChannelIngressResolver({
384
+ return getDiscordRuntime().channel.inbound.ingress.createResolver({
383
385
  channelId: DISCORD_CHANNEL_ID,
384
386
  accountId: params.accountId,
385
387
  identity: discordIngressIdentity,
@@ -909,11 +911,14 @@ var DiscordPresenceListener = class extends PresenceUpdateListener {
909
911
  this.pendingGuildSeeds = /* @__PURE__ */ new Map();
910
912
  this.guildPresenceState = /* @__PURE__ */ new Map();
911
913
  this.gatewayGeneration = 0;
914
+ this.stopped = false;
915
+ this.activeRuns = /* @__PURE__ */ new Set();
912
916
  this.cooldownStore = params.cooldownStore ?? openDiscordPresenceCooldownStore();
913
917
  this.presenceBaseline = params.presenceBaseline ?? new DiscordPresenceBaselineCache();
914
918
  this.emissionGate = params.emissionGate ?? new DiscordPresenceEmissionGate();
915
919
  }
916
920
  async seedGuildSnapshot(data) {
921
+ if (this.stopped) return;
917
922
  if (data.unavailable !== true && "presences" in data && Array.isArray(data.presences)) for (const presence of data.presences) {
918
923
  const userId = presence.user?.id;
919
924
  if (userId) setPresence(this.params.accountId, userId, {
@@ -970,23 +975,31 @@ var DiscordPresenceListener = class extends PresenceUpdateListener {
970
975
  }
971
976
  async handle(data, client) {
972
977
  const userId = data.user?.id;
973
- if (!userId) return;
978
+ if (!userId || this.stopped) return;
974
979
  setPresence(this.params.accountId, userId, data);
975
980
  const pendingSeed = this.pendingGuildSeeds.get(data.guild_id);
976
981
  if (pendingSeed && !await pendingSeed) return;
982
+ if (this.stopped) return;
977
983
  const presenceKey = `${this.params.accountId}:${data.guild_id}:${userId}`;
978
984
  const gatewayGeneration = this.gatewayGeneration;
979
985
  const guildGeneration = this.guildPresenceState.get(data.guild_id)?.generation ?? 0;
980
986
  const run = (this.pendingByGuildUser.get(presenceKey) ?? Promise.resolve()).then(() => this.handleSerial(data, client, userId, presenceKey, gatewayGeneration, guildGeneration), () => this.handleSerial(data, client, userId, presenceKey, gatewayGeneration, guildGeneration));
981
987
  this.pendingByGuildUser.set(presenceKey, run);
988
+ this.activeRuns.add(run);
982
989
  try {
983
990
  await run;
984
991
  } catch (err) {
985
992
  (this.params.logger ?? discordEventQueueLog).error(danger(`discord presence handler failed: ${String(err)}`));
986
993
  } finally {
994
+ this.activeRuns.delete(run);
987
995
  if (this.pendingByGuildUser.get(presenceKey) === run) this.pendingByGuildUser.delete(presenceKey);
988
996
  }
989
997
  }
998
+ async stop() {
999
+ this.stopped = true;
1000
+ this.resetGatewaySession();
1001
+ await Promise.allSettled(this.activeRuns);
1002
+ }
990
1003
  resetGatewaySession() {
991
1004
  this.gatewayGeneration += 1;
992
1005
  this.emissionGate.noteGatewaySessionReset(this.params.nowMs?.() ?? Date.now());
@@ -1021,6 +1034,8 @@ var DiscordPresenceListener = class extends PresenceUpdateListener {
1021
1034
  })?.presenceEvents;
1022
1035
  if (!config || config.enabled === false) return;
1023
1036
  if (config.users !== void 0 && !config.users.includes(userId)) return;
1037
+ const lastEmittedAtMs = await this.cooldownStore.lookup(presenceKey);
1038
+ if (!this.isCurrentGeneration(data.guild_id, gatewayGeneration, guildGeneration) || policy?.isCurrent() === false) return;
1024
1039
  const nowMs = this.params.nowMs?.() ?? Date.now();
1025
1040
  const presenceScope = data.guild_id;
1026
1041
  const presenceEvent = resolveDiscordOnlinePresenceEvent({
@@ -1029,7 +1044,7 @@ var DiscordPresenceListener = class extends PresenceUpdateListener {
1029
1044
  availabilityKind: this.presenceBaseline.isOffline(presenceScope, presenceKey) ? "observed-offline" : this.guildPresenceState.get(data.guild_id)?.inferUnknownAsNewlyAvailable === true && !this.presenceBaseline.isOnline(presenceScope, presenceKey) ? "first-seen-after-snapshot" : null,
1030
1045
  botUserId: this.params.botUserId,
1031
1046
  nowMs,
1032
- lastEmittedAtMs: this.cooldownStore.lookup(presenceKey)
1047
+ lastEmittedAtMs
1033
1048
  });
1034
1049
  if (!presenceEvent) {
1035
1050
  if (isDiscordOfflineStatus(data.status)) this.recordPresenceBaseline(data.guild_id, presenceKey, "offline");
@@ -1090,7 +1105,8 @@ var DiscordPresenceListener = class extends PresenceUpdateListener {
1090
1105
  }
1091
1106
  });
1092
1107
  try {
1093
- cooldownReserved = this.cooldownStore.registerIfAbsent(presenceKey, nowMs, { ttlMs: DISCORD_PRESENCE_GREETING_COOLDOWN_MS });
1108
+ cooldownReserved = await this.cooldownStore.registerIfAbsent(presenceKey, nowMs, { ttlMs: DISCORD_PRESENCE_GREETING_COOLDOWN_MS });
1109
+ if (!this.isCurrentGeneration(data.guild_id, gatewayGeneration, guildGeneration) || policy?.isCurrent() === false) return;
1094
1110
  if (!cooldownReserved) {
1095
1111
  this.recordPresenceBaseline(data.guild_id, presenceKey, "online");
1096
1112
  return;
@@ -1124,11 +1140,11 @@ var DiscordPresenceListener = class extends PresenceUpdateListener {
1124
1140
  });
1125
1141
  } finally {
1126
1142
  if (!burstCommitted) this.emissionGate.releaseBurst(data.guild_id, burstReservation);
1127
- if (cooldownReserved && !burstCommitted && this.cooldownStore.lookup(presenceKey) === nowMs) this.cooldownStore.delete(presenceKey);
1143
+ if (cooldownReserved && !burstCommitted) await this.cooldownStore.deleteIfEqual?.(presenceKey, nowMs);
1128
1144
  }
1129
1145
  }
1130
1146
  isCurrentGeneration(guildId, gatewayGeneration, guildGeneration) {
1131
- return gatewayGeneration === this.gatewayGeneration && guildGeneration === (this.guildPresenceState.get(guildId)?.generation ?? 0);
1147
+ return !this.stopped && gatewayGeneration === this.gatewayGeneration && guildGeneration === (this.guildPresenceState.get(guildId)?.generation ?? 0);
1132
1148
  }
1133
1149
  recordPresenceBaseline(guildId, key, status) {
1134
1150
  const evictedGuildId = status === "offline" ? this.presenceBaseline.observeOffline(guildId, key) : this.presenceBaseline.observeOnline(guildId, key);
@@ -1164,30 +1180,49 @@ var DiscordPresenceReadyListener = class extends ReadyListener {
1164
1180
  this.presenceListener.resetGatewaySession();
1165
1181
  }
1166
1182
  };
1183
+ const DISCORD_THREAD_REJOIN_CLAIM_MAX_ENTRIES = 1e4;
1167
1184
  var DiscordThreadUpdateListener = class extends ThreadUpdateListener {
1168
1185
  constructor(cfg, logger) {
1169
1186
  super();
1170
1187
  this.cfg = cfg;
1171
1188
  this.logger = logger;
1189
+ this.rejoinClaims = /* @__PURE__ */ new Map();
1172
1190
  }
1173
- async handle(data) {
1191
+ resetGatewaySession() {
1192
+ this.rejoinClaims.clear();
1193
+ }
1194
+ async handle(data, client) {
1174
1195
  await runDiscordListenerWithSlowLog({
1175
1196
  logger: this.logger,
1176
1197
  listener: this.constructor.name,
1177
1198
  event: this.type,
1178
1199
  run: async () => {
1179
- if (!isThreadArchived(data)) return;
1180
1200
  const threadId = "id" in data && typeof data.id === "string" ? data.id : void 0;
1181
1201
  if (!threadId) return;
1182
1202
  const logger = this.logger ?? discordEventQueueLog;
1183
- const count = await closeDiscordThreadSessions({
1184
- cfg: this.cfg,
1185
- threadId
1186
- });
1187
- if (count > 0) logger.info("Discord thread archived — reset sessions", {
1188
- threadId,
1189
- count
1190
- });
1203
+ if (isThreadArchived(data)) {
1204
+ this.rejoinClaims.delete(threadId);
1205
+ const count = await closeDiscordThreadSessions({
1206
+ cfg: this.cfg,
1207
+ threadId
1208
+ });
1209
+ if (count > 0) logger.info("Discord thread archived — reset sessions", {
1210
+ threadId,
1211
+ count
1212
+ });
1213
+ return;
1214
+ }
1215
+ if (this.rejoinClaims.has(threadId)) return;
1216
+ const claim = Symbol(threadId);
1217
+ this.rejoinClaims.set(threadId, claim);
1218
+ pruneMapToMaxSize(this.rejoinClaims, DISCORD_THREAD_REJOIN_CLAIM_MAX_ENTRIES);
1219
+ try {
1220
+ await client.rest.put(`/channels/${threadId}/thread-members/@me`);
1221
+ logger.info("Discord active thread — rejoined thread", { threadId });
1222
+ } catch (err) {
1223
+ if (this.rejoinClaims.get(threadId) === claim) this.rejoinClaims.delete(threadId);
1224
+ logger.warn(danger(`discord thread rejoin failed: ${String(err)}`), { threadId });
1225
+ }
1191
1226
  },
1192
1227
  onError: (err) => {
1193
1228
  (this.logger ?? discordEventQueueLog).error(danger(`discord thread-update handler failed: ${String(err)}`));
@@ -1195,6 +1230,15 @@ var DiscordThreadUpdateListener = class extends ThreadUpdateListener {
1195
1230
  });
1196
1231
  }
1197
1232
  };
1233
+ var DiscordThreadReadyListener = class extends ReadyListener {
1234
+ constructor(threadUpdateListener) {
1235
+ super();
1236
+ this.threadUpdateListener = threadUpdateListener;
1237
+ }
1238
+ handle() {
1239
+ this.threadUpdateListener.resetGatewaySession();
1240
+ }
1241
+ };
1198
1242
  var DiscordThreadDeleteListener = class extends ThreadDeleteListener {
1199
1243
  constructor(cfg, accountId, logger) {
1200
1244
  super();
@@ -1438,7 +1482,7 @@ async function resolveGuildEntriesByChannelAllowlist(params) {
1438
1482
  summarizeMapping("discord channels", mapping, unresolved, params.runtime);
1439
1483
  return nextGuilds;
1440
1484
  } catch (err) {
1441
- params.runtime.log?.(`discord channel resolve failed; using config entries. ${formatErrorMessage$1(err)}`);
1485
+ params.runtime.log?.(`discord channel resolve failed; using config entries. ${formatErrorMessage(err)}`);
1442
1486
  return params.guildEntries;
1443
1487
  }
1444
1488
  }
@@ -1462,7 +1506,7 @@ async function resolveAllowFromByUserAllowlist(params) {
1462
1506
  summarizeMapping("discord users", mapping, unresolved, params.runtime);
1463
1507
  return allowFrom;
1464
1508
  } catch (err) {
1465
- params.runtime.log?.(`discord user resolve failed; using config entries. ${formatErrorMessage$1(err)}`);
1509
+ params.runtime.log?.(`discord user resolve failed; using config entries. ${formatErrorMessage(err)}`);
1466
1510
  return params.allowFrom;
1467
1511
  }
1468
1512
  }
@@ -1509,7 +1553,7 @@ async function resolveGuildEntriesByUserAllowlist(params) {
1509
1553
  summarizeMapping("discord channel users", mapping, unresolved, params.runtime);
1510
1554
  return nextGuilds;
1511
1555
  } catch (err) {
1512
- params.runtime.log?.(`discord channel user resolve failed; using config entries. ${formatErrorMessage$1(err)}`);
1556
+ params.runtime.log?.(`discord channel user resolve failed; using config entries. ${formatErrorMessage(err)}`);
1513
1557
  return params.guildEntries;
1514
1558
  }
1515
1559
  }
@@ -1595,6 +1639,19 @@ function createDiscordDnsLookup() {
1595
1639
  });
1596
1640
  };
1597
1641
  }
1642
+ function createDiscordEndpointDnsLookup(endpointHostname) {
1643
+ const normalizedEndpointHostname = normalizeHostname(endpointHostname);
1644
+ if (!normalizedEndpointHostname) throw new Error("Discord endpoint Gateway hostname is required");
1645
+ const policy = {
1646
+ allowedHostnames: [normalizedEndpointHostname],
1647
+ hostnameAllowlist: [normalizedEndpointHostname]
1648
+ };
1649
+ return (hostname, options, callback) => {
1650
+ resolvePinnedHostnameWithPolicy(hostname, { policy }).then((pinned) => pinned.lookup(pinned.hostname, options, callback), (error) => {
1651
+ callback(error instanceof Error ? error : new Error(String(error)), "", 4);
1652
+ });
1653
+ };
1654
+ }
1598
1655
  //#endregion
1599
1656
  //#region extensions/discord/src/monitor/rest-fetch.ts
1600
1657
  const discordDnsLookup$1 = createDiscordDnsLookup();
@@ -1613,7 +1670,7 @@ function createEnvProxyDiscordRestDispatcher(runtime) {
1613
1670
  connect: { lookup: discordDnsLookup$1 }
1614
1671
  });
1615
1672
  } catch (err) {
1616
- runtime.error?.(danger(`discord: env proxy unavailable for REST fetch; using direct dispatcher: ${formatErrorMessage(err)}`));
1673
+ runtime.error?.(danger(`discord: env proxy unavailable for REST fetch; using direct dispatcher: ${formatErrorMessage$1(err)}`));
1617
1674
  return;
1618
1675
  }
1619
1676
  }
@@ -1807,7 +1864,7 @@ function resolveDiscordInteractionMessageParts(payload) {
1807
1864
  }
1808
1865
  function hasRenderableReplyPayload(payload) {
1809
1866
  const { components, embeds } = resolveDiscordInteractionMessageParts(payload);
1810
- return resolveSendableOutboundReplyParts(payload).hasContent || Boolean(components || embeds);
1867
+ return hasOutboundReplyContent(payload) || Boolean(components || embeds);
1811
1868
  }
1812
1869
  async function safeDiscordInteractionCall(label, fn) {
1813
1870
  try {
@@ -1825,9 +1882,24 @@ async function settleDiscordInteractionWithoutVisibleReply(interaction) {
1825
1882
  await safeDiscordInteractionCall("interaction delete deferred reply", () => interaction.deleteReply());
1826
1883
  }
1827
1884
  async function deliverDiscordInteractionReply(params) {
1828
- const { interaction, payload, textLimit, maxLinesPerMessage, preferFollowUp, chunkMode } = params;
1885
+ const { interaction, textLimit, maxLinesPerMessage, preferFollowUp, chunkMode } = params;
1886
+ const nativeParts = resolveDiscordInteractionMessageParts(params.payload);
1887
+ const preserveNativeParts = resolveSendableOutboundReplyParts(params.payload).hasMedia || Boolean(nativeParts.components || nativeParts.embeds);
1888
+ const payload = await renderPresentationForDelivery({
1889
+ presentationCapabilities: DISCORD_PRESENTATION_CAPABILITIES,
1890
+ renderPresentation: (adapted) => preserveNativeParts ? null : buildDiscordPresentationPayload({
1891
+ payload: adapted,
1892
+ presentation: adapted.presentation
1893
+ })
1894
+ }, params.payload);
1895
+ const componentSpec = preserveNativeParts ? void 0 : await resolveDiscordComponentSpec(payload);
1896
+ let componentBuild = componentSpec ? buildDiscordComponentMessage({
1897
+ spec: componentSpec,
1898
+ ...params.componentRoute
1899
+ }) : void 0;
1829
1900
  const reply = resolveSendableOutboundReplyParts(payload);
1830
1901
  let { components: firstMessageComponents, embeds: firstMessageEmbeds } = resolveDiscordInteractionMessageParts(payload);
1902
+ if (componentBuild) firstMessageComponents = componentBuild.components;
1831
1903
  let payloadDelivered = false;
1832
1904
  const sendMessage = async (content, files, components, embeds) => {
1833
1905
  const hasV2 = hasDiscordV2Components(components);
@@ -1841,11 +1913,19 @@ async function deliverDiscordInteractionReply(params) {
1841
1913
  let result;
1842
1914
  try {
1843
1915
  result = await safeDiscordInteractionCall("interaction send", async () => {
1844
- if (!preferFollowUp && !payloadDelivered) await interaction.reply(payloadLocal);
1845
- else await interaction.followUp(payloadLocal);
1916
+ const sent = !preferFollowUp && !payloadDelivered ? await interaction.reply(payloadLocal) : await interaction.followUp(payloadLocal);
1846
1917
  payloadDelivered = true;
1847
1918
  firstMessageComponents = void 0;
1848
1919
  firstMessageEmbeds = void 0;
1920
+ if (componentBuild) {
1921
+ const messageId = sent && typeof sent === "object" && "id" in sent && typeof sent.id === "string" ? sent.id : void 0;
1922
+ await registerDiscordComponentEntries({
1923
+ entries: componentBuild.entries,
1924
+ modals: componentBuild.modals,
1925
+ messageId
1926
+ });
1927
+ componentBuild = void 0;
1928
+ }
1849
1929
  });
1850
1930
  } catch (error) {
1851
1931
  if (!payloadDelivered) throw error;
@@ -1892,7 +1972,7 @@ async function deliverDiscordInteractionReply(params) {
1892
1972
  }
1893
1973
  //#endregion
1894
1974
  //#region extensions/discord/src/monitor/native-command-route.ts
1895
- async function resolveDiscordNativeInteractionRouteState(params) {
1975
+ function resolveDiscordNativeInteractionRouteState(params) {
1896
1976
  const route = resolveDiscordBoundConversationRoute({
1897
1977
  cfg: params.cfg,
1898
1978
  accountId: params.accountId,
@@ -1904,7 +1984,7 @@ async function resolveDiscordNativeInteractionRouteState(params) {
1904
1984
  conversationId: params.conversationId,
1905
1985
  parentConversationId: params.parentConversationId
1906
1986
  });
1907
- const configuredRoute = params.threadBinding == null ? conversationRuntime.resolveConfiguredBindingRoute({
1987
+ const configuredRoute = params.threadBinding == null ? resolveConfiguredBindingRoute({
1908
1988
  cfg: params.cfg,
1909
1989
  route,
1910
1990
  conversation: {
@@ -1927,17 +2007,14 @@ async function resolveDiscordNativeInteractionRouteState(params) {
1927
2007
  }),
1928
2008
  boundSessionKey,
1929
2009
  configuredRoute,
1930
- configuredBinding,
1931
- bindingReadiness: params.enforceConfiguredBindingReadiness && configuredBinding ? await conversationRuntime.ensureConfiguredBindingRouteReady({
1932
- cfg: params.cfg,
1933
- bindingResolution: configuredBinding
1934
- }) : null
2010
+ configuredBinding
1935
2011
  };
1936
2012
  }
1937
2013
  //#endregion
1938
2014
  //#region extensions/discord/src/monitor/native-command.runtime.ts
1939
2015
  const nativeCommandRuntime = {
1940
2016
  dispatchChannelInboundTurn,
2017
+ ensureConfiguredBindingRouteReady,
1941
2018
  resolveDirectStatusReplyForSession,
1942
2019
  resolveDiscordNativeInteractionRouteState,
1943
2020
  getSessionEntry
@@ -1968,6 +2045,11 @@ async function dispatchDiscordNativeAgentReply(params) {
1968
2045
  const payloadDelivered = await deliverDiscordInteractionReply({
1969
2046
  interaction: params.interaction,
1970
2047
  payload,
2048
+ componentRoute: {
2049
+ accountId: params.effectiveRoute.accountId,
2050
+ agentId: params.effectiveRoute.agentId,
2051
+ sessionKey: params.ctxPayload.CommandTargetSessionKey ?? params.effectiveRoute.sessionKey
2052
+ },
1971
2053
  mediaLocalRoots: params.mediaLocalRoots,
1972
2054
  textLimit: resolveTextChunkLimit(params.cfg, "discord", params.accountId, { fallbackLimit: 2e3 }),
1973
2055
  maxLinesPerMessage: resolveDiscordMaxLinesPerMessage({
@@ -2108,6 +2190,7 @@ async function handleDiscordCommandArgInteraction(params) {
2108
2190
  preferFollowUp: true,
2109
2191
  threadBindings: ctx.threadBindings,
2110
2192
  responseEphemeral: resolveDiscordSlashCommandConfig(ctx.discordConfig?.slashCommand).ephemeral,
2193
+ buildContext: ctx.buildContext,
2111
2194
  dispatchReplyFromConfig: ctx.dispatchReplyFromConfig,
2112
2195
  pluginCommandDispatch: { kind: "non-plugin" }
2113
2196
  });
@@ -2177,6 +2260,200 @@ function createDiscordCommandArgFallbackButton$1(params) {
2177
2260
  return new DiscordCommandArgFallbackButton(params);
2178
2261
  }
2179
2262
  //#endregion
2263
+ //#region extensions/discord/src/monitor/inbound-context.ts
2264
+ function createDiscordSupplementalContextAccessChecker(params) {
2265
+ const userAllowList = params.channelConfig?.users ?? params.guildInfo?.users ?? [];
2266
+ const roleAllowList = params.channelConfig?.roles ?? params.guildInfo?.roles ?? [];
2267
+ const allowFrom = [...userAllowList, ...roleAllowList];
2268
+ return (sender) => {
2269
+ return resolveInboundSupplementalSenderAllowed({
2270
+ isGroup: params.isGuild,
2271
+ groupPolicy: allowFrom.length === 0 ? "open" : "allowlist",
2272
+ allowFrom,
2273
+ isSenderAllowed: () => resolveDiscordMemberAllowed({
2274
+ userAllowList,
2275
+ roleAllowList,
2276
+ memberRoleIds: [...sender.memberRoleIds ?? []],
2277
+ userId: sender.id ?? "",
2278
+ userName: sender.name,
2279
+ userTag: sender.tag,
2280
+ allowNameMatching: params.allowNameMatching
2281
+ })
2282
+ });
2283
+ };
2284
+ }
2285
+ function buildDiscordGroupSystemPrompt(channelConfig) {
2286
+ return channelConfig?.systemPrompt?.trim() || void 0;
2287
+ }
2288
+ function buildDiscordChannelStructuredContext(params) {
2289
+ if (!params.isGuild) return;
2290
+ const entries = [];
2291
+ if (typeof params.channelTopic === "string" && params.channelTopic.trim().length > 0) entries.push({
2292
+ label: "Discord channel metadata",
2293
+ source: "discord",
2294
+ type: "channel_metadata",
2295
+ payload: { topic: params.channelTopic.trim() }
2296
+ });
2297
+ return entries.length > 0 ? entries : void 0;
2298
+ }
2299
+ function buildDiscordInboundAccessContext(params) {
2300
+ return {
2301
+ groupSystemPrompt: params.isGuild ? buildDiscordGroupSystemPrompt(params.channelConfig) : void 0,
2302
+ channelStructuredContext: buildDiscordChannelStructuredContext({
2303
+ isGuild: params.isGuild,
2304
+ channelTopic: params.channelTopic
2305
+ }),
2306
+ ownerAllowFrom: resolveDiscordOwnerAllowFrom({
2307
+ channelConfig: params.channelConfig,
2308
+ guildInfo: params.guildInfo,
2309
+ sender: params.sender,
2310
+ allowNameMatching: params.allowNameMatching
2311
+ })
2312
+ };
2313
+ }
2314
+ //#endregion
2315
+ //#region extensions/discord/src/monitor/native-command-context.ts
2316
+ async function buildDiscordNativeCommandContext(params) {
2317
+ const conversationLabel = params.isDirectMessage ? params.user.globalName ?? params.user.username : params.channelId;
2318
+ const { groupSystemPrompt, ownerAllowFrom, channelStructuredContext } = buildDiscordInboundAccessContext({
2319
+ channelConfig: params.channelConfig,
2320
+ guildInfo: params.guildInfo,
2321
+ sender: params.sender,
2322
+ allowNameMatching: params.allowNameMatching,
2323
+ isGuild: params.isGuild,
2324
+ channelTopic: params.channelTopic
2325
+ });
2326
+ const conversation = {
2327
+ kind: params.isDirectMessage ? "direct" : params.isGroupDm ? "group" : "channel",
2328
+ id: params.channelId,
2329
+ parentId: params.isThreadChannel ? params.threadParentId : void 0,
2330
+ threadId: params.isThreadChannel ? params.channelId : void 0
2331
+ };
2332
+ const allowFrom = params.commandAuthorized ? [`user:${params.user.id}`] : [];
2333
+ const channelIngress = await getDiscordRuntime().channel.inbound.ingress.createResolver({
2334
+ channelId: "discord",
2335
+ accountId: params.accountId,
2336
+ identity: discordIngressIdentity,
2337
+ useDefaultPairingStore: false
2338
+ }).command({
2339
+ subject: {
2340
+ stableId: params.user.id,
2341
+ aliases: { participantKind: "user" }
2342
+ },
2343
+ conversation,
2344
+ contextBinding: {
2345
+ agentId: params.agentId,
2346
+ sessionKey: params.sessionKey,
2347
+ nativeChannelId: params.channelId,
2348
+ messageId: params.interactionId,
2349
+ inboundEventKind: "user_request"
2350
+ },
2351
+ event: {
2352
+ kind: "native-command",
2353
+ mayPair: false
2354
+ },
2355
+ dmPolicy: "allowlist",
2356
+ groupPolicy: "allowlist",
2357
+ allowFrom,
2358
+ groupAllowFrom: allowFrom,
2359
+ command: { modeWhenAccessGroupsOff: "configured" }
2360
+ });
2361
+ return await (params.buildContext ?? buildChannelInboundEventContext)({
2362
+ channel: "discord",
2363
+ channelIngress,
2364
+ accountId: params.accountId,
2365
+ messageId: params.interactionId,
2366
+ timestamp: params.timestampMs ?? Date.now(),
2367
+ from: params.isDirectMessage ? `discord:${params.user.id}` : params.isGroupDm ? `discord:group:${params.channelId}` : `discord:channel:${params.channelId}`,
2368
+ sender: {
2369
+ id: params.user.id,
2370
+ name: params.user.globalName ?? params.user.username,
2371
+ username: params.user.username,
2372
+ tag: params.sender.tag,
2373
+ roles: params.memberRoleIds
2374
+ },
2375
+ conversation: {
2376
+ ...conversation,
2377
+ nativeChannelId: params.channelId,
2378
+ routePeer: buildDiscordRoutePeer({
2379
+ isDirectMessage: params.isDirectMessage,
2380
+ isGroupDm: params.isGroupDm,
2381
+ directUserId: params.user.id,
2382
+ conversationId: params.channelId
2383
+ }),
2384
+ label: conversationLabel,
2385
+ spaceId: params.isGuild ? params.guildInfo?.id ?? params.guildInfo?.slug ?? params.guildId : void 0
2386
+ },
2387
+ route: {
2388
+ agentId: params.agentId,
2389
+ accountId: params.accountId,
2390
+ routeSessionKey: params.commandTargetSessionKey,
2391
+ dispatchSessionKey: params.sessionKey
2392
+ },
2393
+ reply: {
2394
+ to: `slash:${params.user.id}`,
2395
+ originatingTo: resolveDiscordConversationIdentity({
2396
+ isDirectMessage: params.isDirectMessage,
2397
+ userId: params.user.id,
2398
+ channelId: params.channelId
2399
+ }) ?? (params.isDirectMessage ? `user:${params.user.id}` : `channel:${params.channelId}`)
2400
+ },
2401
+ message: { rawBody: params.prompt },
2402
+ access: {
2403
+ mentions: {
2404
+ canDetectMention: true,
2405
+ wasMentioned: true
2406
+ },
2407
+ commands: { authorized: params.commandAuthorized }
2408
+ },
2409
+ commandTurn: {
2410
+ kind: "native",
2411
+ source: "native",
2412
+ authorized: params.commandAuthorized,
2413
+ body: params.prompt
2414
+ },
2415
+ supplemental: { groupSystemPrompt },
2416
+ extra: {
2417
+ CommandArgs: params.commandArgs,
2418
+ CommandTargetSessionKey: params.commandTargetSessionKey,
2419
+ CommandSource: "native",
2420
+ GroupSubject: params.isGuild ? params.guildName : void 0,
2421
+ ChannelStructuredContext: channelStructuredContext,
2422
+ OwnerAllowFrom: ownerAllowFrom
2423
+ }
2424
+ });
2425
+ }
2426
+ async function buildDiscordNativeInteractionContext(params) {
2427
+ const { interaction, route, boundSessionKey, sessionPrefix, channelContext, ...context } = params;
2428
+ const targets = resolveNativeCommandSessionTargets({
2429
+ agentId: route.agentId,
2430
+ sessionPrefix,
2431
+ userId: context.user.id,
2432
+ targetSessionKey: route.sessionKey,
2433
+ boundSessionKey
2434
+ });
2435
+ return {
2436
+ ctxPayload: await buildDiscordNativeCommandContext({
2437
+ ...context,
2438
+ ...targets,
2439
+ agentId: route.agentId,
2440
+ accountId: route.accountId,
2441
+ interactionId: interaction.rawData.id,
2442
+ channelId: channelContext.rawChannelId || "unknown",
2443
+ threadParentId: channelContext.threadParentId,
2444
+ memberRoleIds: Array.isArray(interaction.rawData.member?.roles) ? interaction.rawData.member.roles : [],
2445
+ guildId: interaction.guild?.id,
2446
+ guildName: interaction.guild?.name,
2447
+ channelTopic: resolveDiscordChannelTopicSafe(interaction.channel),
2448
+ isGuild: Boolean(interaction.guild),
2449
+ isDirectMessage: channelContext.isDirectMessage,
2450
+ isGroupDm: channelContext.isGroupDm,
2451
+ isThreadChannel: channelContext.isThreadChannel
2452
+ }),
2453
+ ...targets
2454
+ };
2455
+ }
2456
+ //#endregion
2180
2457
  //#region extensions/discord/src/monitor/native-interaction-channel-context.ts
2181
2458
  async function resolveDiscordNativeInteractionChannelContext(params) {
2182
2459
  const channelContext = await resolveDiscordThreadLikeChannelContext({
@@ -2200,6 +2477,62 @@ async function resolveDiscordNativeInteractionChannelContext(params) {
2200
2477
  }
2201
2478
  //#endregion
2202
2479
  //#region extensions/discord/src/monitor/native-command-auth.ts
2480
+ function resolveDiscordNativePolicyReader(params) {
2481
+ return params.readPolicy ?? createDiscordLivePolicyReader({
2482
+ ...params,
2483
+ readConfig: () => getRuntimeConfigSnapshot() ?? params.cfg,
2484
+ resolvedAllowlist: {
2485
+ guildEntries: params.discordConfig?.guilds,
2486
+ allowFrom: params.discordConfig?.allowFrom ?? resolveDiscordAccountAllowFrom(params)
2487
+ }
2488
+ });
2489
+ }
2490
+ function createDiscordNativeCommandAuthority(params) {
2491
+ const assertAdmittedOwner = resolveCommandAuthorization(params).assertOwnerCurrent;
2492
+ const readAuthorization = () => {
2493
+ const cfg = getRuntimeConfigSnapshot() ?? params.cfg;
2494
+ const owners = resolveDiscordCommandOwnerAllowFrom(cfg);
2495
+ const senderIsOwner = params.isPolicyCurrent?.() !== false && (resolveDiscordOwnerAccess({
2496
+ allowFrom: owners,
2497
+ sender: params.sender,
2498
+ allowNameMatching: params.allowNameMatching
2499
+ }).ownerAllowed || resolveCommandAuthorization({
2500
+ ...params,
2501
+ cfg
2502
+ }).senderIsOwner);
2503
+ const commands = resolveDiscordNativeCommandAllowlistAccess({
2504
+ cfg,
2505
+ accountId: params.accountId,
2506
+ sender: params.sender,
2507
+ chatType: params.ctx.ChatType === "direct" ? "direct" : "channel",
2508
+ guildId: params.guildId
2509
+ });
2510
+ return {
2511
+ senderIsOwner,
2512
+ allowed: (!commands.configured || commands.allowed) && (!owners || owners.includes("*") || senderIsOwner || commands.allowed || params.commandName === "status" || params.pluginCommand)
2513
+ };
2514
+ };
2515
+ const assertActive = () => {
2516
+ assertAdmittedOwner?.();
2517
+ if (params.isPolicyCurrent?.() === false || !readAuthorization().allowed) throw new Error("Discord command authority changed; send a new request.");
2518
+ };
2519
+ return {
2520
+ assertActive,
2521
+ assertOwnerCurrent: () => {
2522
+ assertActive();
2523
+ if (!readAuthorization().senderIsOwner) throw new Error("Discord owner authority changed; send a new request.");
2524
+ },
2525
+ senderIsOwner: () => readAuthorization().senderIsOwner,
2526
+ isAllowed: () => {
2527
+ try {
2528
+ assertActive();
2529
+ return true;
2530
+ } catch {
2531
+ return false;
2532
+ }
2533
+ }
2534
+ };
2535
+ }
2203
2536
  function resolveDiscordNativeCommandAllowlistAccess(params) {
2204
2537
  const commandsAllowFrom = params.cfg.commands?.allowFrom;
2205
2538
  if (!commandsAllowFrom || typeof commandsAllowFrom !== "object") return {
@@ -2339,12 +2672,13 @@ async function resolveDiscordNativeAutocompleteAuthorized(params) {
2339
2672
  author: user,
2340
2673
  pluralkitInfo: null
2341
2674
  });
2342
- const { isDirectMessage, isGroupDm, isThreadChannel, channelName, channelSlug, rawChannelId, threadParentId, threadParentName, threadParentSlug } = await resolveDiscordNativeInteractionChannelContext({
2675
+ const channelContext = await resolveDiscordNativeInteractionChannelContext({
2343
2676
  channel: interaction.channel,
2344
2677
  client: interaction.client,
2345
2678
  hasGuild: Boolean(interaction.guild),
2346
- channelIdFallback: ""
2679
+ channelIdFallback: interaction.rawData.channel_id ?? ""
2347
2680
  });
2681
+ const { isDirectMessage, isGroupDm, isThreadChannel, channelName, channelSlug, rawChannelId, threadParentId, threadParentName, threadParentSlug } = channelContext;
2348
2682
  if (params.isPolicyCurrent?.() === false) return false;
2349
2683
  const memberRoleIds = Array.isArray(interaction.rawData.member?.roles) ? interaction.rawData.member.roles.map((roleId) => roleId) : [];
2350
2684
  const allowNameMatching = isDangerousNameMatchingEnabled(discordConfig);
@@ -2421,162 +2755,75 @@ async function resolveDiscordNativeAutocompleteAuthorized(params) {
2421
2755
  channelName,
2422
2756
  channelSlug
2423
2757
  }).allowed) return false;
2424
- if (params.skipCommandOwnerAllowFrom !== true) {
2425
- const commandOwnerAllowFrom = resolveDiscordCommandOwnerAllowFrom(cfg);
2426
- const { ownerAllowed: commandOwnerOk } = resolveDiscordOwnerAccess({
2427
- allowFrom: commandOwnerAllowFrom,
2428
- sender: {
2429
- id: sender.id,
2430
- name: sender.name,
2431
- tag: sender.tag
2432
- },
2433
- allowNameMatching
2434
- });
2435
- const commandOwnerAllowAll = commandOwnerAllowFrom?.includes("*") === true;
2436
- if (commandOwnerAllowFrom && !(commandOwnerOk || commandOwnerAllowAll) && !commandsAllowFromAccess.allowed) return false;
2758
+ if (!isDirectMessage) {
2759
+ if (!await resolveDiscordGuildNativeCommandAuthorized({
2760
+ cfg,
2761
+ accountId,
2762
+ discordConfig,
2763
+ useAccessGroups,
2764
+ commandsAllowFromAccess,
2765
+ guildInfo,
2766
+ channelConfig,
2767
+ memberRoleIds,
2768
+ sender,
2769
+ allowNameMatching,
2770
+ ownerAllowListConfigured: ownerAllowList != null,
2771
+ ownerAllowed: ownerOk
2772
+ })) return false;
2437
2773
  }
2438
- if (!isDirectMessage) return await resolveDiscordGuildNativeCommandAuthorized({
2439
- cfg,
2440
- accountId,
2441
- discordConfig,
2442
- useAccessGroups,
2443
- commandsAllowFromAccess,
2444
- guildInfo,
2445
- channelConfig,
2446
- memberRoleIds,
2774
+ const commandOwnerAllowFrom = resolveDiscordCommandOwnerAllowFrom(cfg);
2775
+ if (params.skipCommandOwnerAllowFrom !== true && commandOwnerAllowFrom && !commandOwnerAllowFrom.includes("*") && !commandsAllowFromAccess.allowed && !resolveDiscordOwnerAccess({
2776
+ allowFrom: commandOwnerAllowFrom,
2447
2777
  sender,
2448
- allowNameMatching,
2449
- ownerAllowListConfigured: ownerAllowList != null,
2450
- ownerAllowed: ownerOk
2451
- }) && params.isPolicyCurrent?.() !== false;
2778
+ allowNameMatching
2779
+ }).ownerAllowed) {
2780
+ const routeState = resolveDiscordNativeInteractionRouteState({
2781
+ cfg,
2782
+ accountId,
2783
+ guildId: interaction.guild?.id,
2784
+ memberRoleIds,
2785
+ isDirectMessage,
2786
+ isGroupDm,
2787
+ directUserId: user.id,
2788
+ conversationId: rawChannelId,
2789
+ parentConversationId: threadParentId,
2790
+ threadBinding: isThreadChannel ? params.threadBindings?.getByThreadId(rawChannelId) : void 0
2791
+ });
2792
+ const { ctxPayload } = await buildDiscordNativeInteractionContext({
2793
+ buildContext: params.buildContext,
2794
+ interaction,
2795
+ channelContext,
2796
+ route: routeState.effectiveRoute,
2797
+ boundSessionKey: routeState.boundSessionKey,
2798
+ sessionPrefix: params.sessionPrefix ?? "discord:slash",
2799
+ channelConfig,
2800
+ guildInfo,
2801
+ allowNameMatching,
2802
+ commandAuthorized: true,
2803
+ user,
2804
+ sender,
2805
+ prompt: "",
2806
+ commandArgs: {}
2807
+ });
2808
+ if (!resolveCommandAuthorization({
2809
+ ctx: ctxPayload,
2810
+ cfg,
2811
+ commandAuthorized: true
2812
+ }).senderIsOwner) return false;
2813
+ }
2452
2814
  return params.isPolicyCurrent?.() !== false;
2453
2815
  }
2454
2816
  //#endregion
2455
2817
  //#region extensions/discord/src/monitor/native-command-bypass.ts
2456
2818
  function shouldBypassConfiguredAcpEnsure(commandName) {
2457
- return commandName.trim().toLowerCase() === "acp";
2819
+ const command = commandName.trim().toLowerCase();
2820
+ return command === "acp" || command === "status";
2458
2821
  }
2459
2822
  function shouldBypassConfiguredAcpGuildGuards(commandName) {
2460
2823
  const command = commandName.trim().toLowerCase();
2461
2824
  return command === "new" || command === "reset";
2462
2825
  }
2463
2826
  //#endregion
2464
- //#region extensions/discord/src/monitor/inbound-context.ts
2465
- function createDiscordSupplementalContextAccessChecker(params) {
2466
- const userAllowList = params.channelConfig?.users ?? params.guildInfo?.users ?? [];
2467
- const roleAllowList = params.channelConfig?.roles ?? params.guildInfo?.roles ?? [];
2468
- const allowFrom = [...userAllowList, ...roleAllowList];
2469
- return (sender) => {
2470
- return resolveInboundSupplementalSenderAllowed({
2471
- isGroup: params.isGuild,
2472
- groupPolicy: allowFrom.length === 0 ? "open" : "allowlist",
2473
- allowFrom,
2474
- isSenderAllowed: () => resolveDiscordMemberAllowed({
2475
- userAllowList,
2476
- roleAllowList,
2477
- memberRoleIds: [...sender.memberRoleIds ?? []],
2478
- userId: sender.id ?? "",
2479
- userName: sender.name,
2480
- userTag: sender.tag,
2481
- allowNameMatching: params.allowNameMatching
2482
- })
2483
- });
2484
- };
2485
- }
2486
- function buildDiscordGroupSystemPrompt(channelConfig) {
2487
- return channelConfig?.systemPrompt?.trim() || void 0;
2488
- }
2489
- function buildDiscordChannelStructuredContext(params) {
2490
- if (!params.isGuild) return;
2491
- const entries = [];
2492
- if (typeof params.channelTopic === "string" && params.channelTopic.trim().length > 0) entries.push({
2493
- label: "Discord channel metadata",
2494
- source: "discord",
2495
- type: "channel_metadata",
2496
- payload: { topic: params.channelTopic.trim() }
2497
- });
2498
- return entries.length > 0 ? entries : void 0;
2499
- }
2500
- function buildDiscordInboundAccessContext(params) {
2501
- return {
2502
- groupSystemPrompt: params.isGuild ? buildDiscordGroupSystemPrompt(params.channelConfig) : void 0,
2503
- channelStructuredContext: buildDiscordChannelStructuredContext({
2504
- isGuild: params.isGuild,
2505
- channelTopic: params.channelTopic
2506
- }),
2507
- ownerAllowFrom: resolveDiscordOwnerAllowFrom({
2508
- channelConfig: params.channelConfig,
2509
- guildInfo: params.guildInfo,
2510
- sender: params.sender,
2511
- allowNameMatching: params.allowNameMatching
2512
- })
2513
- };
2514
- }
2515
- //#endregion
2516
- //#region extensions/discord/src/monitor/native-command-context.ts
2517
- function buildDiscordNativeCommandContext(params) {
2518
- const conversationLabel = params.isDirectMessage ? params.user.globalName ?? params.user.username : params.channelId;
2519
- const { groupSystemPrompt, ownerAllowFrom, channelStructuredContext } = buildDiscordInboundAccessContext({
2520
- channelConfig: params.channelConfig,
2521
- guildInfo: params.guildInfo,
2522
- sender: params.sender,
2523
- allowNameMatching: params.allowNameMatching,
2524
- isGuild: params.isGuild,
2525
- channelTopic: params.channelTopic
2526
- });
2527
- return finalizeInboundContext({
2528
- Body: params.prompt,
2529
- BodyForAgent: params.prompt,
2530
- RawBody: params.prompt,
2531
- CommandBody: params.prompt,
2532
- CommandArgs: params.commandArgs,
2533
- From: params.isDirectMessage ? `discord:${params.user.id}` : params.isGroupDm ? `discord:group:${params.channelId}` : `discord:channel:${params.channelId}`,
2534
- To: `slash:${params.user.id}`,
2535
- SessionKey: params.sessionKey,
2536
- CommandTargetSessionKey: params.commandTargetSessionKey,
2537
- AccountId: params.accountId ?? void 0,
2538
- ChatType: params.isDirectMessage ? "direct" : params.isGroupDm ? "group" : "channel",
2539
- ...buildDiscordConversationRouteContext({
2540
- isDirectMessage: params.isDirectMessage,
2541
- isGroupDm: params.isGroupDm,
2542
- directUserId: params.user.id,
2543
- conversationId: params.channelId,
2544
- isThread: params.isThreadChannel,
2545
- parentConversationId: params.threadParentId
2546
- }),
2547
- ConversationLabel: conversationLabel,
2548
- GroupSubject: params.isGuild ? params.guildName : void 0,
2549
- GroupSpace: params.isGuild ? params.guildInfo?.id ?? params.guildInfo?.slug ?? params.guildId : void 0,
2550
- MemberRoleIds: params.memberRoleIds,
2551
- GroupSystemPrompt: groupSystemPrompt,
2552
- ChannelStructuredContext: channelStructuredContext,
2553
- OwnerAllowFrom: ownerAllowFrom,
2554
- SenderName: params.user.globalName ?? params.user.username,
2555
- SenderId: params.user.id,
2556
- SenderUsername: params.user.username,
2557
- SenderTag: params.sender.tag,
2558
- Provider: "discord",
2559
- Surface: "discord",
2560
- WasMentioned: true,
2561
- MessageSid: params.interactionId,
2562
- Timestamp: params.timestampMs ?? Date.now(),
2563
- CommandAuthorized: params.commandAuthorized,
2564
- CommandTurn: {
2565
- kind: "native",
2566
- source: "native",
2567
- authorized: params.commandAuthorized,
2568
- body: params.prompt
2569
- },
2570
- CommandSource: "native",
2571
- OriginatingChannel: "discord",
2572
- OriginatingTo: resolveDiscordConversationIdentity({
2573
- isDirectMessage: params.isDirectMessage,
2574
- userId: params.user.id,
2575
- channelId: params.channelId
2576
- }) ?? (params.isDirectMessage ? `user:${params.user.id}` : `channel:${params.channelId}`)
2577
- });
2578
- }
2579
- //#endregion
2580
2827
  //#region extensions/discord/src/monitor/model-picker-preferences.ts
2581
2828
  const DEFAULT_RECENT_LIMIT = 5;
2582
2829
  const PREFERENCE_MAX_ENTRIES = 2e3;
@@ -2665,6 +2912,16 @@ async function recordDiscordModelPickerRecentModel(params) {
2665
2912
  } catch {}
2666
2913
  }
2667
2914
  //#endregion
2915
+ //#region extensions/discord/src/monitor/model-picker.runtime.ts
2916
+ const hostSdk = modelsProviderRuntime;
2917
+ const MODEL_PICKER_CHANGED_MESSAGE = hostSdk.MODEL_PICKER_CHANGED_MESSAGE ?? "Available models changed. Open /models and choose again.";
2918
+ function supportsDiscordModelPickerRuntimeChoices() {
2919
+ return hostSdk.getModelsRuntimeChoices !== void 0;
2920
+ }
2921
+ function getDiscordModelPickerRuntimeChoices(...args) {
2922
+ return hostSdk.getModelsRuntimeChoices?.(...args);
2923
+ }
2924
+ //#endregion
2668
2925
  //#region extensions/discord/src/monitor/model-picker.state.ts
2669
2926
  const DISCORD_MODEL_PICKER_CUSTOM_ID_KEY = "mdlpk";
2670
2927
  const DISCORD_CUSTOM_ID_MAX_CHARS = 100;
@@ -2701,10 +2958,13 @@ const PICKER_VIEWS = [
2701
2958
  const DISCORD_MODEL_PICKER_BUCKET_THRESHOLD = DISCORD_COMPONENT_MAX_SELECT_OPTIONS;
2702
2959
  /** Target items per alpha bucket. Discord caps selects at 25 options. */
2703
2960
  const DISCORD_MODEL_PICKER_BUCKET_TARGET_SIZE = 20;
2704
- const DISCORD_MODEL_PICKER_MODEL_TOKEN_PATTERN = /^[A-Za-z0-9_-]{8}$/u;
2961
+ const DISCORD_MODEL_PICKER_TOKEN_PATTERN = /^[A-Za-z0-9_-]{8}$/u;
2705
2962
  function createDiscordModelPickerModelToken(provider, model) {
2706
2963
  return createHash("sha256").update(JSON.stringify([normalizeProviderId(provider), model]), "utf8").digest("base64url").slice(0, 8);
2707
2964
  }
2965
+ function createDiscordModelPickerRuntimeToken(runtime) {
2966
+ return createHash("sha256").update(runtime, "utf8").digest("base64url").slice(0, 8);
2967
+ }
2708
2968
  const loadModelsProviderRuntime = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/models-provider-runtime"));
2709
2969
  function isValidCommandContext(value) {
2710
2970
  return COMMAND_CONTEXTS.includes(value);
@@ -2754,9 +3014,9 @@ function paginateItems(params) {
2754
3014
  hasNext: page < totalPages
2755
3015
  };
2756
3016
  }
2757
- async function loadDiscordModelPickerData(cfg, agentId) {
3017
+ async function loadDiscordModelPickerData(cfg, agentId, options) {
2758
3018
  const { buildPreparedModelsProviderData } = await loadModelsProviderRuntime();
2759
- return buildPreparedModelsProviderData(cfg, agentId);
3019
+ return buildPreparedModelsProviderData(cfg, agentId, options);
2760
3020
  }
2761
3021
  function buildDiscordModelPickerCustomId(params) {
2762
3022
  const userId = params.userId.trim();
@@ -2767,7 +3027,7 @@ function buildDiscordModelPickerCustomId(params) {
2767
3027
  const modelIndex = normalizeOptionalModelPickerIndex(params.modelIndex);
2768
3028
  const recentSlot = normalizeOptionalModelPickerIndex(params.recentSlot);
2769
3029
  const modelToken = params.modelToken?.trim();
2770
- if (modelToken && !DISCORD_MODEL_PICKER_MODEL_TOKEN_PATTERN.test(modelToken)) throw new Error("Discord model picker model token is invalid");
3030
+ if (modelToken && !DISCORD_MODEL_PICKER_TOKEN_PATTERN.test(modelToken)) throw new Error("Discord model picker model token is invalid");
2771
3031
  const parts = [
2772
3032
  `${DISCORD_MODEL_PICKER_CUSTOM_ID_KEY}:c=${encodeCustomIdComponent(params.command)}`,
2773
3033
  `a=${encodeCustomIdComponent(params.action)}`,
@@ -2778,6 +3038,9 @@ function buildDiscordModelPickerCustomId(params) {
2778
3038
  if (normalizedProvider) parts.push(`p=${encodeCustomIdComponent(normalizedProvider)}`);
2779
3039
  const runtime = params.runtime?.trim();
2780
3040
  if (runtime) parts.push(`r=${encodeCustomIdComponent(runtime)}`);
3041
+ const runtimeToken = params.runtimeToken?.trim();
3042
+ if (runtimeToken && !DISCORD_MODEL_PICKER_TOKEN_PATTERN.test(runtimeToken)) throw new Error("Discord model picker runtime token is invalid");
3043
+ if (runtimeToken) parts.push(`rt=${runtimeToken}`);
2781
3044
  const runtimeIndex = normalizeOptionalModelPickerIndex(params.runtimeIndex);
2782
3045
  if (runtimeIndex) parts.push(`ri=${String(runtimeIndex)}`);
2783
3046
  if (providerPage) parts.push(`pp=${String(providerPage)}`);
@@ -2790,6 +3053,13 @@ function buildDiscordModelPickerCustomId(params) {
2790
3053
  if (providerBucket) parts.push(`pb=${encodeCustomIdComponent(providerBucket)}`);
2791
3054
  const modelBucket = params.modelBucket?.trim().toLowerCase();
2792
3055
  if (modelBucket) parts.push(`mb=${encodeCustomIdComponent(modelBucket)}`);
3056
+ if (parts.join(";").length > DISCORD_CUSTOM_ID_MAX_CHARS) {
3057
+ for (let index = parts.length - 1; index >= 0; index -= 1) if (parts[index] === "g=1" || parts[index] === "pp=1") parts.splice(index, 1);
3058
+ }
3059
+ if (modelToken && parts.join(";").length > DISCORD_CUSTOM_ID_MAX_CHARS) {
3060
+ const providerPart = parts.findIndex((part) => part.startsWith("p="));
3061
+ if (providerPart >= 0) parts.splice(providerPart, 1);
3062
+ }
2793
3063
  const customId = parts.join(";");
2794
3064
  if (customId.length > DISCORD_CUSTOM_ID_MAX_CHARS) throw new Error(`Discord model picker custom_id exceeds ${DISCORD_CUSTOM_ID_MAX_CHARS} chars (${customId.length})`);
2795
3065
  return customId;
@@ -2803,11 +3073,18 @@ function parseDiscordModelPickerData(data) {
2803
3073
  const providerRaw = decodeCustomIdComponent(coerceString(data.p));
2804
3074
  const runtimeRaw = decodeCustomIdComponent(coerceString(data.r));
2805
3075
  const runtimeIndex = parseStrictPositiveInteger(data.ri);
3076
+ const runtimeTokenRaw = coerceString(data.rt).trim();
3077
+ if (runtimeTokenRaw && !DISCORD_MODEL_PICKER_TOKEN_PATTERN.test(runtimeTokenRaw)) return null;
3078
+ if ([
3079
+ runtimeRaw.trim(),
3080
+ runtimeTokenRaw,
3081
+ runtimeIndex
3082
+ ].filter(Boolean).length > 1) return null;
2806
3083
  const page = parseRawPage(data.g ?? data.pg);
2807
3084
  const providerPage = parseStrictPositiveInteger(data.pp);
2808
3085
  const modelIndex = parseStrictPositiveInteger(data.mi);
2809
3086
  const modelTokenRaw = coerceString(data.m).trim();
2810
- const modelToken = DISCORD_MODEL_PICKER_MODEL_TOKEN_PATTERN.test(modelTokenRaw) ? modelTokenRaw : void 0;
3087
+ const modelToken = DISCORD_MODEL_PICKER_TOKEN_PATTERN.test(modelTokenRaw) ? modelTokenRaw : void 0;
2811
3088
  const recentSlot = parseStrictPositiveInteger(data.rs);
2812
3089
  const providerBucketRaw = decodeCustomIdComponent(coerceString(data.pb)).trim().toLowerCase();
2813
3090
  const modelBucketRaw = decodeCustomIdComponent(coerceString(data.mb)).trim().toLowerCase();
@@ -2821,6 +3098,7 @@ function parseDiscordModelPickerData(data) {
2821
3098
  userId: trimmedUserId,
2822
3099
  provider: providerRaw ? normalizeProviderId(providerRaw) : void 0,
2823
3100
  runtime: runtimeRaw.trim() || void 0,
3101
+ ...runtimeTokenRaw ? { runtimeToken: runtimeTokenRaw } : {},
2824
3102
  ...typeof runtimeIndex === "number" ? { runtimeIndex } : {},
2825
3103
  page,
2826
3104
  ...typeof providerPage === "number" ? { providerPage } : {},
@@ -3063,7 +3341,7 @@ function buildBucketSelectRow(params) {
3063
3341
  page: 1,
3064
3342
  provider: params.provider,
3065
3343
  runtime: params.runtime,
3066
- runtimeIndex: params.runtimeIndex,
3344
+ runtimeToken: params.runtimeToken,
3067
3345
  providerPage: params.providerPage,
3068
3346
  modelIndex: params.modelIndex
3069
3347
  }),
@@ -3073,54 +3351,29 @@ function buildBucketSelectRow(params) {
3073
3351
  return new Row([select]);
3074
3352
  }
3075
3353
  function getRuntimeChoices(params) {
3076
- const choices = params.data.runtimeChoicesByProvider?.get(normalizeProviderId(params.provider));
3077
- if (choices?.length) return choices;
3078
- return [{
3079
- id: "openclaw",
3080
- label: "OpenClaw Default",
3081
- description: "Use the built-in OpenClaw runtime."
3082
- }];
3083
- }
3084
- function resolveSelectedRuntime(params) {
3085
- const choices = getRuntimeChoices({
3086
- data: params.data,
3087
- provider: params.provider
3088
- });
3089
- const allowed = new Set(choices.map((choice) => choice.id));
3090
- const pending = params.pendingRuntime?.trim();
3091
- if (pending && allowed.has(pending)) return pending;
3092
- const current = params.currentRuntime?.trim();
3093
- if (current && allowed.has(current)) return current;
3094
- return choices[0]?.id ?? "openclaw";
3354
+ const model = parseCurrentModelRef(params.modelRef);
3355
+ return getDiscordModelPickerRuntimeChoices(params.data, params.provider, model?.provider === normalizeProviderId(params.provider) ? model.model : void 0);
3095
3356
  }
3096
3357
  function resolveExplicitRuntimeState(params) {
3097
- const allowed = new Set(params.choices.map((choice) => choice.id));
3098
- const pending = params.pendingRuntime?.trim();
3099
- if (pending && allowed.has(pending)) return pending;
3100
- const current = params.currentRuntime?.trim();
3101
- if (current && current !== "auto" && current !== "default" && allowed.has(current)) return current;
3358
+ const runtime = params.pendingRuntime?.trim() || params.currentRuntime?.trim();
3359
+ return runtime && runtime !== "auto" && runtime !== "default" ? runtime : void 0;
3360
+ }
3361
+ function resolveSelectedRuntime(params) {
3362
+ const choices = getRuntimeChoices(params);
3363
+ const explicit = resolveExplicitRuntimeState(params);
3364
+ return explicit ? choices?.find((choice) => choice.id === explicit)?.id : choices?.[0]?.id;
3102
3365
  }
3103
3366
  function getActiveBucketId(bucket) {
3104
3367
  return bucket && bucket.id !== "all" ? bucket.id : void 0;
3105
3368
  }
3106
3369
  function resolveCompactRuntimeState(params) {
3107
- const stateRuntime = resolveExplicitRuntimeState(params);
3108
- const stateRuntimeIndex = stateRuntime ? params.choices.findIndex((choice) => choice.id === stateRuntime) : -1;
3109
- if (stateRuntimeIndex >= 0) return { runtimeIndex: stateRuntimeIndex + 1 };
3110
- return stateRuntime ? { runtime: stateRuntime } : {};
3370
+ if (!supportsDiscordModelPickerRuntimeChoices()) return {};
3371
+ const runtime = resolveExplicitRuntimeState(params);
3372
+ return runtime ? { runtimeToken: createDiscordModelPickerRuntimeToken(runtime) } : {};
3111
3373
  }
3112
3374
  function buildRenderedShell(params) {
3113
- if (params.layout === "classic") return {
3114
- layout: "classic",
3115
- content: [
3116
- params.title,
3117
- ...params.detailLines,
3118
- "",
3119
- params.footer
3120
- ].filter(Boolean).join("\n"),
3121
- components: params.rows
3122
- };
3123
3375
  const containerComponents = [new TextDisplay(`## ${params.title}`)];
3376
+ if (params.refreshWarning) containerComponents.push(new TextDisplay(params.refreshWarning));
3124
3377
  if (params.detailLines.length > 0) containerComponents.push(new TextDisplay(params.detailLines.join("\n")));
3125
3378
  containerComponents.push(new Separator({
3126
3379
  divider: true,
@@ -3142,10 +3395,7 @@ function buildRenderedShell(params) {
3142
3395
  }));
3143
3396
  containerComponents.push(new TextDisplay(`-# ${params.footer}`));
3144
3397
  }
3145
- return {
3146
- layout: "v2",
3147
- components: [new Container(containerComponents)]
3148
- };
3398
+ return { components: [new Container(containerComponents)] };
3149
3399
  }
3150
3400
  function buildProviderSelectRow(params) {
3151
3401
  if (params.page.items.length === 0) return null;
@@ -3226,20 +3476,22 @@ function buildModelRows(params) {
3226
3476
  })]));
3227
3477
  const runtimeChoices = getRuntimeChoices({
3228
3478
  data: params.data,
3229
- provider: params.modelPage.provider
3479
+ provider: params.modelPage.provider,
3480
+ modelRef: params.pendingModel ?? params.currentModel
3230
3481
  });
3482
+ const currentRuntime = parsedCurrentModel?.provider === params.modelPage.provider ? params.currentRuntime : void 0;
3231
3483
  const selectedRuntime = resolveSelectedRuntime({
3232
3484
  data: params.data,
3233
3485
  provider: params.modelPage.provider,
3234
- currentRuntime: params.currentRuntime,
3486
+ modelRef: params.pendingModel ?? params.currentModel,
3487
+ currentRuntime,
3235
3488
  pendingRuntime: params.pendingRuntime
3236
3489
  });
3237
3490
  const compactRuntime = resolveCompactRuntimeState({
3238
- choices: runtimeChoices,
3239
- currentRuntime: params.currentRuntime,
3491
+ currentRuntime,
3240
3492
  pendingRuntime: params.pendingRuntime
3241
3493
  });
3242
- if (runtimeChoices.length > 1) rows.push(new Row([createModelSelect({
3494
+ if (runtimeChoices && (runtimeChoices.length > 1 || runtimeChoices.length === 1 && selectedRuntime === void 0)) rows.push(new Row([createModelSelect({
3243
3495
  customId: buildDiscordModelPickerCustomId({
3244
3496
  command: params.command,
3245
3497
  action: "runtime",
@@ -3261,7 +3513,7 @@ function buildModelRows(params) {
3261
3513
  if (choice.description) option.description = choice.description;
3262
3514
  return option;
3263
3515
  }),
3264
- placeholder: "Select runtime"
3516
+ placeholder: "Choose how to run this model"
3265
3517
  })]));
3266
3518
  const selectedModelRef = parsedPendingModel ?? parsedCurrentModel;
3267
3519
  const modelOptions = params.modelPage.items.map((model) => ({
@@ -3352,7 +3604,7 @@ function buildModelRows(params) {
3352
3604
  buttonRowItems.push(createModelPickerButton({
3353
3605
  label: "Submit",
3354
3606
  style: ButtonStyle.Primary,
3355
- disabled: !hasPendingSelection,
3607
+ disabled: !hasPendingSelection || supportsDiscordModelPickerRuntimeChoices() && selectedRuntime === void 0,
3356
3608
  customId: buildDiscordModelPickerCustomId({
3357
3609
  ...modelActionState,
3358
3610
  action: "submit",
@@ -3406,8 +3658,8 @@ function renderDiscordModelPickerProvidersView(params) {
3406
3658
  const detailLines = [formatCurrentModelLine(params.currentModel), page.bucket && page.bucket.id !== "all" ? `Select a provider (${page.totalItems} in ${page.bucket.label}, ${totalProviders} total).` : `Select a provider (${page.totalItems} available).`];
3407
3659
  const footer = page.totalPages > 1 ? `Showing page ${page.page}/${page.totalPages} · ${page.totalItems} providers total` : `All ${page.totalItems} providers shown`;
3408
3660
  return buildRenderedShell({
3409
- layout: params.layout ?? "v2",
3410
3661
  title: "Model Picker",
3662
+ refreshWarning: params.data.refreshWarning,
3411
3663
  detailLines,
3412
3664
  rows,
3413
3665
  footer
@@ -3433,8 +3685,8 @@ function renderDiscordModelPickerModelsView(params) {
3433
3685
  })
3434
3686
  })])];
3435
3687
  return buildRenderedShell({
3436
- layout: params.layout ?? "v2",
3437
3688
  title: "Model Picker",
3689
+ refreshWarning: params.data.refreshWarning,
3438
3690
  detailLines: [formatCurrentModelLine(params.currentModel), `Provider not found: ${normalizeProviderId(params.provider)}`],
3439
3691
  rows,
3440
3692
  footer: "Choose a different provider."
@@ -3454,12 +3706,7 @@ function renderDiscordModelPickerModelsView(params) {
3454
3706
  quickModels: params.quickModels,
3455
3707
  providerBucket: params.providerBucket
3456
3708
  });
3457
- const runtimeChoices = getRuntimeChoices({
3458
- data: params.data,
3459
- provider: modelPage.provider
3460
- });
3461
3709
  const pendingRuntime = params.pendingRuntime?.trim();
3462
- const pendingRuntimeIndex = pendingRuntime ? runtimeChoices.findIndex((choice) => choice.id === pendingRuntime) : -1;
3463
3710
  const rows = [];
3464
3711
  const bucketRow = buildBucketSelectRow({
3465
3712
  command: params.command,
@@ -3468,24 +3715,32 @@ function renderDiscordModelPickerModelsView(params) {
3468
3715
  buckets: modelPage.buckets,
3469
3716
  currentBucketId: modelPage.bucket?.id,
3470
3717
  provider: modelPage.provider,
3471
- runtimeIndex: pendingRuntimeIndex >= 0 ? pendingRuntimeIndex + 1 : void 0,
3718
+ runtimeToken: pendingRuntime ? createDiscordModelPickerRuntimeToken(pendingRuntime) : void 0,
3472
3719
  providerPage,
3473
3720
  providerBucket: params.providerBucket
3474
3721
  });
3475
3722
  if (bucketRow) rows.push(bucketRow);
3476
3723
  rows.push(...modelRows);
3477
3724
  const defaultModel = `${params.data.resolvedDefault.provider}/${params.data.resolvedDefault.model}`;
3478
- const pendingLine = params.pendingModel ? `Selected: ${params.pendingModel} · runtime ${resolveSelectedRuntime({
3725
+ const choices = getRuntimeChoices({
3479
3726
  data: params.data,
3480
3727
  provider: modelPage.provider,
3481
- currentRuntime: params.currentRuntime,
3728
+ modelRef: params.pendingModel ?? params.currentModel
3729
+ });
3730
+ const selectedRuntime = resolveSelectedRuntime({
3731
+ data: params.data,
3732
+ provider: modelPage.provider,
3733
+ modelRef: params.pendingModel ?? params.currentModel,
3734
+ currentRuntime: parseCurrentModelRef(params.currentModel)?.provider === modelPage.provider ? params.currentRuntime : void 0,
3482
3735
  pendingRuntime: params.pendingRuntime
3483
- })} (press Submit)` : "Select a model, then press Submit.";
3736
+ });
3737
+ const selectedRuntimeLabel = choices?.find((choice) => choice.id === selectedRuntime)?.label;
3738
+ const pendingLine = !params.pendingModel ? "Select a model, then press Submit." : !supportsDiscordModelPickerRuntimeChoices() ? `Selected: ${params.pendingModel} (press Submit)` : choices === void 0 ? "Could not confirm how to run this model. Open /models to try again." : choices.length === 0 ? "This model cannot run with your current connections. Choose another model." : selectedRuntimeLabel ? `Selected: ${params.pendingModel} · ${selectedRuntimeLabel} (press Submit)` : "Choose how to run this model, then press Submit.";
3484
3739
  const detailLines = [formatCurrentModelLine(params.currentModel), `Default: ${defaultModel}`];
3485
3740
  if (modelPage.totalPages > 1) detailLines.push(`${modelPage.provider}: page ${modelPage.page}/${modelPage.totalPages} · ${modelPage.totalItems} models`);
3486
3741
  return buildRenderedShell({
3487
- layout: params.layout ?? "v2",
3488
3742
  title: "Model Picker",
3743
+ refreshWarning: params.data.refreshWarning,
3489
3744
  detailLines,
3490
3745
  preRowText: pendingLine,
3491
3746
  rows,
@@ -3516,7 +3771,7 @@ function renderDiscordModelPickerRecentsView(params) {
3516
3771
  modelToken: createModelRefToken(modelRef),
3517
3772
  provider: params.provider,
3518
3773
  runtime: params.runtime,
3519
- runtimeIndex: params.runtimeIndex,
3774
+ runtimeToken: params.runtimeToken,
3520
3775
  page: params.page,
3521
3776
  providerPage: params.providerPage,
3522
3777
  userId: params.userId
@@ -3530,7 +3785,7 @@ function renderDiscordModelPickerRecentsView(params) {
3530
3785
  view: "models",
3531
3786
  provider: params.provider,
3532
3787
  runtime: params.runtime,
3533
- runtimeIndex: params.runtimeIndex,
3788
+ runtimeToken: params.runtimeToken,
3534
3789
  page: params.page,
3535
3790
  providerPage: params.providerPage,
3536
3791
  modelBucket: params.modelBucket,
@@ -3538,21 +3793,14 @@ function renderDiscordModelPickerRecentsView(params) {
3538
3793
  })
3539
3794
  })]);
3540
3795
  return buildRenderedShell({
3541
- layout: params.layout ?? "v2",
3542
3796
  title: "Recents",
3797
+ refreshWarning: params.data.refreshWarning,
3543
3798
  detailLines: ["Models you've previously selected appear here.", formatCurrentModelLine(params.currentModel)],
3544
3799
  preRowText: "Tap a model to switch.",
3545
3800
  rows,
3546
3801
  trailingRows: [backRow]
3547
3802
  });
3548
3803
  }
3549
- function toDiscordModelPickerMessagePayload(view) {
3550
- if (view.layout === "classic") return {
3551
- content: view.content,
3552
- components: view.components
3553
- };
3554
- return { components: view.components };
3555
- }
3556
3804
  //#endregion
3557
3805
  //#region extensions/discord/src/monitor/native-command-model-picker-apply.ts
3558
3806
  function normalizeExpectedRuntime(value) {
@@ -3575,6 +3823,7 @@ async function applyDiscordModelPickerSelection(params) {
3575
3823
  preferFollowUp: true,
3576
3824
  threadBindings: params.threadBindings,
3577
3825
  suppressReplies: true,
3826
+ buildContext: params.buildContext,
3578
3827
  dispatchReplyFromConfig: params.dispatchReplyFromConfig,
3579
3828
  pluginCommandDispatch: { kind: "non-plugin" }
3580
3829
  }), 12e3);
@@ -3665,11 +3914,11 @@ async function resolveDiscordModelPickerRouteState(params) {
3665
3914
  channel: interaction.channel,
3666
3915
  client: interaction.client,
3667
3916
  hasGuild: Boolean(interaction.guild),
3668
- channelIdFallback: "unknown"
3917
+ channelIdFallback: interaction.rawData.channel_id ?? "unknown"
3669
3918
  });
3670
3919
  const memberRoleIds = Array.isArray(interaction.rawData.member?.roles) ? interaction.rawData.member.roles.map((roleId) => roleId) : [];
3671
3920
  const threadBinding = isThreadChannel ? params.threadBindings.getByThreadId(rawChannelId) : void 0;
3672
- return await resolveDiscordNativeInteractionRouteState({
3921
+ return resolveDiscordNativeInteractionRouteState({
3673
3922
  cfg,
3674
3923
  accountId,
3675
3924
  guildId: interaction.guild?.id ?? void 0,
@@ -3679,8 +3928,7 @@ async function resolveDiscordModelPickerRouteState(params) {
3679
3928
  directUserId: interaction.user?.id ?? rawChannelId,
3680
3929
  conversationId: rawChannelId,
3681
3930
  parentConversationId: threadParentId,
3682
- threadBinding,
3683
- enforceConfiguredBindingReadiness: params.enforceConfiguredBindingReadiness
3931
+ threadBinding
3684
3932
  });
3685
3933
  }
3686
3934
  async function resolveDiscordModelPickerRoute(params) {
@@ -3688,15 +3936,7 @@ async function resolveDiscordModelPickerRoute(params) {
3688
3936
  }
3689
3937
  async function resolveDiscordNativeChoiceContext(params) {
3690
3938
  try {
3691
- const resolved = await resolveDiscordModelPickerRouteState({
3692
- interaction: params.interaction,
3693
- cfg: params.cfg,
3694
- accountId: params.accountId,
3695
- threadBindings: params.threadBindings,
3696
- enforceConfiguredBindingReadiness: true
3697
- });
3698
- if (resolved.bindingReadiness && !resolved.bindingReadiness.ok) return null;
3699
- const route = resolved.effectiveRoute;
3939
+ const route = params.route ?? await resolveDiscordModelPickerRoute(params);
3700
3940
  const fallback = resolveDefaultModelForAgent({
3701
3941
  cfg: params.cfg,
3702
3942
  agentId: route.agentId
@@ -3780,7 +4020,12 @@ async function replyWithDiscordModelPickerProviders(params) {
3780
4020
  accountId: params.accountId,
3781
4021
  threadBindings: params.threadBindings
3782
4022
  });
3783
- const data = await loadDiscordModelPickerData(params.cfg, route.agentId);
4023
+ const sessionEntry = getSessionEntry({
4024
+ storePath: resolveStorePath(params.cfg.session?.store, { agentId: route.agentId }),
4025
+ sessionKey: route.sessionKey,
4026
+ readConsistency: "latest"
4027
+ });
4028
+ const data = await loadDiscordModelPickerData(params.cfg, route.agentId, { sessionEntry });
3784
4029
  const currentModel = resolveDiscordModelPickerCurrentModel({
3785
4030
  cfg: params.cfg,
3786
4031
  route,
@@ -3810,7 +4055,7 @@ async function replyWithDiscordModelPickerProviders(params) {
3810
4055
  const initialModelBucket = initialResolved.bucket;
3811
4056
  const initialProviderLocation = findProviderBucketLocation(data, initialProvider);
3812
4057
  const payload = {
3813
- ...toDiscordModelPickerMessagePayload(renderDiscordModelPickerModelsView({
4058
+ ...renderDiscordModelPickerModelsView({
3814
4059
  command: params.command,
3815
4060
  userId: params.userId,
3816
4061
  data,
@@ -3822,7 +4067,7 @@ async function replyWithDiscordModelPickerProviders(params) {
3822
4067
  currentModel,
3823
4068
  currentRuntime,
3824
4069
  quickModels
3825
- })),
4070
+ }),
3826
4071
  ephemeral: true
3827
4072
  };
3828
4073
  await params.safeInteractionCall("model picker reply", async () => {
@@ -3854,9 +4099,10 @@ function resolveModelPickerSelectionValue(interaction) {
3854
4099
  if (typeof first !== "string") return null;
3855
4100
  return first.trim() || null;
3856
4101
  }
3857
- function resolveModelPickerRuntimeByIndex(params) {
3858
- if (!params.provider || typeof params.runtimeIndex !== "number") return;
3859
- return (params.data.runtimeChoicesByProvider?.get(params.provider))?.[params.runtimeIndex - 1]?.id;
4102
+ function resolveRuntimeToken(choices, token) {
4103
+ if (!token) return;
4104
+ const matches = choices?.filter((choice) => createDiscordModelPickerRuntimeToken(choice.id) === token);
4105
+ return matches?.length === 1 ? matches[0]?.id : void 0;
3860
4106
  }
3861
4107
  function resolveModelPickerProvider(params) {
3862
4108
  return params.parsedProvider ?? splitDiscordModelRef(params.currentModelRef ?? "")?.provider ?? params.data.resolvedDefault.provider;
@@ -3866,20 +4112,7 @@ function resolveSelectedBucket(interaction) {
3866
4112
  return raw && raw !== "all" ? raw : void 0;
3867
4113
  }
3868
4114
  function resolvePendingRuntime(params) {
3869
- return params.parsed.runtime ?? resolveModelPickerRuntimeByIndex({
3870
- data: params.data,
3871
- provider: params.provider,
3872
- runtimeIndex: params.parsed.runtimeIndex
3873
- });
3874
- }
3875
- function resolveParsedRuntimeForSubmission(params) {
3876
- if (params.parsed.runtime) return params.parsed.runtime;
3877
- if (params.parsed.provider !== params.selectedProvider) return;
3878
- return resolveModelPickerRuntimeByIndex({
3879
- data: params.data,
3880
- provider: params.selectedProvider,
3881
- runtimeIndex: params.parsed.runtimeIndex
3882
- });
4115
+ return params.parsed.runtime ?? resolveRuntimeToken(getDiscordModelPickerRuntimeChoices(params.data, params.provider), params.parsed.runtimeToken);
3883
4116
  }
3884
4117
  function resolveSubmittedModelRef(params) {
3885
4118
  if (params.parsed.action === "reset") return `${params.data.resolvedDefault.provider}/${params.data.resolvedDefault.model}`;
@@ -3947,22 +4180,6 @@ function resolveDiscordModelPickerModelSelection(params) {
3947
4180
  if (params.requireModelToken || !params.modelIndex || params.modelIndex < 1) return null;
3948
4181
  return models[params.modelIndex - 1] ?? null;
3949
4182
  }
3950
- function resolveDiscordModelPickerRuntimeForProvider(params) {
3951
- const runtime = normalizeOptionalString(params.runtime);
3952
- if (!runtime) return;
3953
- if (runtime === "auto" || runtime === "default") return params.allowResetRuntime ? runtime : void 0;
3954
- const choices = params.data.runtimeChoicesByProvider?.get(params.provider);
3955
- if (!choices?.length) return runtime === "openclaw" ? runtime : void 0;
3956
- return choices.some((choice) => choice.id === runtime) ? runtime : void 0;
3957
- }
3958
- function resolveDiscordModelPickerSubmissionRuntime(params) {
3959
- return resolveDiscordModelPickerRuntimeForProvider({
3960
- data: params.data,
3961
- provider: params.provider,
3962
- runtime: params.parsedRuntime,
3963
- allowResetRuntime: true
3964
- });
3965
- }
3966
4183
  async function handleDiscordModelPickerInteraction(params) {
3967
4184
  const { interaction, data, ctx } = params;
3968
4185
  const parsed = parseDiscordModelPickerData(data);
@@ -3987,7 +4204,14 @@ async function handleDiscordModelPickerInteraction(params) {
3987
4204
  accountId: ctx.accountId,
3988
4205
  threadBindings: ctx.threadBindings
3989
4206
  });
3990
- const pickerData = await loadDiscordModelPickerData(cfg, route.agentId);
4207
+ const sessionEntry = getSessionEntry({
4208
+ storePath: resolveStorePath(cfg.session?.store, { agentId: route.agentId }),
4209
+ sessionKey: route.sessionKey,
4210
+ readConsistency: "latest"
4211
+ });
4212
+ const pickerData = await loadDiscordModelPickerData(cfg, route.agentId, { sessionEntry });
4213
+ const tokenModel = parsed.modelToken ? resolveDiscordModelPickerModelRefByToken(pickerData, parsed.modelToken) : null;
4214
+ const parsedProvider = parsed.provider ?? splitDiscordModelRef(tokenModel ?? "")?.provider;
3991
4215
  const currentModelRef = resolveDiscordModelPickerCurrentModel({
3992
4216
  cfg,
3993
4217
  route,
@@ -4024,39 +4248,60 @@ async function handleDiscordModelPickerInteraction(params) {
4024
4248
  quickModels,
4025
4249
  ...state
4026
4250
  });
4027
- return await updatePicker(toDiscordModelPickerMessagePayload(rendered));
4251
+ return await updatePicker(rendered);
4028
4252
  };
4253
+ if (parsed.action !== "cancel" && pickerData.isCurrent?.() === false) {
4254
+ await showNotice("That model picker expired. Reopen /model to try again.");
4255
+ return;
4256
+ }
4257
+ if (parsed.runtimeIndex !== void 0 && parsed.action !== "cancel") {
4258
+ await showNotice("That runtime selection expired. Reopen /model and choose a runtime again.");
4259
+ return;
4260
+ }
4261
+ if (parsed.runtimeToken && ![
4262
+ "submit",
4263
+ "reset",
4264
+ "quick",
4265
+ "cancel"
4266
+ ].includes(parsed.action) && parsedProvider && !resolvePendingRuntime({
4267
+ data: pickerData,
4268
+ provider: parsedProvider,
4269
+ parsed
4270
+ })) {
4271
+ await showNotice("That runtime selection expired. Reopen /model and choose a runtime again.");
4272
+ return;
4273
+ }
4029
4274
  if (parsed.action === "recents") {
4030
- await updatePicker(toDiscordModelPickerMessagePayload(renderDiscordModelPickerRecentsView({
4275
+ await updatePicker(renderDiscordModelPickerRecentsView({
4031
4276
  command: parsed.command,
4032
4277
  userId: parsed.userId,
4033
4278
  data: pickerData,
4034
4279
  quickModels,
4035
4280
  currentModel: currentModelRef,
4036
4281
  runtime: parsed.runtime,
4037
- runtimeIndex: parsed.runtimeIndex,
4282
+ runtimeToken: parsed.runtimeToken,
4038
4283
  provider: parsed.provider,
4039
4284
  page: parsed.page,
4040
4285
  providerPage: parsed.providerPage,
4041
4286
  modelBucket: parsed.modelBucket
4042
- })));
4287
+ }));
4043
4288
  return;
4044
4289
  }
4045
4290
  if (parsed.view === "providers" && (parsed.action === "back" || parsed.action === "nav" || parsed.action === "bucket")) {
4046
4291
  const selectingBucket = parsed.action === "bucket";
4047
- await updatePicker(toDiscordModelPickerMessagePayload(renderDiscordModelPickerProvidersView({
4292
+ await updatePicker(renderDiscordModelPickerProvidersView({
4048
4293
  command: parsed.command,
4049
4294
  userId: parsed.userId,
4050
4295
  data: pickerData,
4051
4296
  page: selectingBucket ? 1 : parsed.page,
4052
4297
  providerBucket: selectingBucket ? resolveSelectedBucket(interaction) : parsed.providerBucket,
4053
4298
  currentModel: currentModelRef
4054
- })));
4299
+ }));
4055
4300
  return;
4056
4301
  }
4057
4302
  if (parsed.action === "bucket" && parsed.view === "models") {
4058
4303
  const provider = resolveModelPickerProvider({
4059
- parsedProvider: parsed.provider,
4304
+ parsedProvider,
4060
4305
  currentModelRef,
4061
4306
  data: pickerData
4062
4307
  });
@@ -4073,7 +4318,7 @@ async function handleDiscordModelPickerInteraction(params) {
4073
4318
  }
4074
4319
  if (parsed.action === "nav" && parsed.view === "models") {
4075
4320
  const provider = resolveModelPickerProvider({
4076
- parsedProvider: parsed.provider,
4321
+ parsedProvider,
4077
4322
  currentModelRef,
4078
4323
  data: pickerData
4079
4324
  });
@@ -4085,7 +4330,7 @@ async function handleDiscordModelPickerInteraction(params) {
4085
4330
  requireModelToken
4086
4331
  });
4087
4332
  if ((parsed.modelIndex || parsed.modelToken) && !pendingModel) {
4088
- await showNotice("That selection expired. Please choose a model again.");
4333
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4089
4334
  return;
4090
4335
  }
4091
4336
  const pendingModelIndex = pendingModel ? resolveDiscordModelPickerModelIndex({
@@ -4107,7 +4352,7 @@ async function handleDiscordModelPickerInteraction(params) {
4107
4352
  }
4108
4353
  if (parsed.action === "back" && parsed.view === "models") {
4109
4354
  const provider = resolveModelPickerProvider({
4110
- parsedProvider: parsed.provider,
4355
+ parsedProvider,
4111
4356
  currentModelRef,
4112
4357
  data: pickerData
4113
4358
  });
@@ -4124,7 +4369,7 @@ async function handleDiscordModelPickerInteraction(params) {
4124
4369
  if (parsed.action === "provider") {
4125
4370
  const selectedProvider = resolveModelPickerSelectionValue(interaction) ?? parsed.provider;
4126
4371
  if (!selectedProvider || !pickerData.byProvider.has(selectedProvider)) {
4127
- await showNotice("Sorry, that provider isn't available anymore.");
4372
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4128
4373
  return;
4129
4374
  }
4130
4375
  await updateModelsView(selectedProvider, {
@@ -4135,9 +4380,9 @@ async function handleDiscordModelPickerInteraction(params) {
4135
4380
  }
4136
4381
  if (parsed.action === "model") {
4137
4382
  const selectedModel = resolveModelPickerSelectionValue(interaction);
4138
- const provider = parsed.provider;
4383
+ const provider = parsedProvider;
4139
4384
  if (!provider || !selectedModel) {
4140
- await showNotice("Sorry, I couldn't read that model selection.");
4385
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4141
4386
  return;
4142
4387
  }
4143
4388
  const modelIndex = resolveDiscordModelPickerModelIndex({
@@ -4146,7 +4391,7 @@ async function handleDiscordModelPickerInteraction(params) {
4146
4391
  model: selectedModel
4147
4392
  });
4148
4393
  if (!modelIndex) {
4149
- await showNotice("Sorry, that model isn't available anymore.");
4394
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4150
4395
  return;
4151
4396
  }
4152
4397
  const modelRef = `${provider}/${selectedModel}`;
@@ -4163,10 +4408,10 @@ async function handleDiscordModelPickerInteraction(params) {
4163
4408
  return;
4164
4409
  }
4165
4410
  if (parsed.action === "runtime") {
4166
- const selectedRuntime = resolveModelPickerSelectionValue(interaction) ?? parsed.runtime ?? "auto";
4167
- const provider = parsed.provider;
4411
+ const selectedRuntime = resolveModelPickerSelectionValue(interaction) ?? parsed.runtime;
4412
+ const provider = parsedProvider;
4168
4413
  if (!provider || !pickerData.byProvider.has(provider)) {
4169
- await showNotice("Sorry, that provider isn't available anymore.");
4414
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4170
4415
  return;
4171
4416
  }
4172
4417
  const selectedModel = resolveDiscordModelPickerModelSelection({
@@ -4177,7 +4422,13 @@ async function handleDiscordModelPickerInteraction(params) {
4177
4422
  requireModelToken
4178
4423
  });
4179
4424
  if ((parsed.modelIndex || parsed.modelToken) && !selectedModel) {
4180
- await showNotice("That selection expired. Please choose a model again.");
4425
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4426
+ return;
4427
+ }
4428
+ const currentModel = splitDiscordModelRef(currentModelRef ?? "");
4429
+ const choices = getDiscordModelPickerRuntimeChoices(pickerData, provider, selectedModel ?? (currentModel?.provider === provider ? currentModel.model : void 0));
4430
+ if (!selectedRuntime || !choices?.some((choice) => choice.id === selectedRuntime)) {
4431
+ await showNotice("That runtime is not available for this model. Choose a runtime again.");
4181
4432
  return;
4182
4433
  }
4183
4434
  const pendingModel = selectedModel ? `${provider}/${selectedModel}` : void 0;
@@ -4204,19 +4455,50 @@ async function handleDiscordModelPickerInteraction(params) {
4204
4455
  });
4205
4456
  const parsedModelRef = modelRef ? splitDiscordModelRef(modelRef) : null;
4206
4457
  if (!parsedModelRef || !pickerData.byProvider.get(parsedModelRef.provider)?.has(parsedModelRef.model)) {
4207
- await showNotice("That selection expired. Please choose a model again.");
4458
+ await showNotice(MODEL_PICKER_CHANGED_MESSAGE);
4208
4459
  return;
4209
4460
  }
4210
4461
  const resolvedModelRef = `${parsedModelRef.provider}/${parsedModelRef.model}`;
4211
- const selectedRuntime = resolveDiscordModelPickerSubmissionRuntime({
4212
- data: pickerData,
4213
- provider: parsedModelRef.provider,
4214
- parsedRuntime: resolveParsedRuntimeForSubmission({
4215
- data: pickerData,
4216
- parsed,
4217
- selectedProvider: parsedModelRef.provider
4218
- })
4219
- });
4462
+ const choices = getDiscordModelPickerRuntimeChoices(pickerData, parsedModelRef.provider, parsedModelRef.model);
4463
+ const modelOnlyHost = !supportsDiscordModelPickerRuntimeChoices();
4464
+ const supportsModelOnlySelection = () => {
4465
+ const currentEntry = getSessionEntry({
4466
+ storePath: resolveStorePath(cfg.session?.store, { agentId: route.agentId }),
4467
+ sessionKey: route.sessionKey,
4468
+ readConsistency: "latest"
4469
+ });
4470
+ const override = currentEntry?.agentRuntimeOverride?.trim();
4471
+ if (override && ![
4472
+ "auto",
4473
+ "default",
4474
+ "openclaw"
4475
+ ].includes(override)) return false;
4476
+ const model = pickerData.modelCatalog?.find((entry) => entry.provider === parsedModelRef.provider && entry.id === parsedModelRef.model);
4477
+ return resolveEffectiveAgentRuntime({
4478
+ cfg,
4479
+ provider: parsedModelRef.provider,
4480
+ modelId: parsedModelRef.model,
4481
+ modelApi: model?.api,
4482
+ modelBaseUrl: model?.baseUrl,
4483
+ agentId: route.agentId,
4484
+ sessionKey: route.sessionKey,
4485
+ sessionEntry: currentEntry
4486
+ }) === "openclaw";
4487
+ };
4488
+ const legacyRuntimeNotice = "This OpenClaw version supports model-only selection here. Update OpenClaw to change runtimes in the picker.";
4489
+ if (modelOnlyHost && (parsed.runtime || parsed.runtimeToken || !supportsModelOnlySelection())) {
4490
+ await showNotice(legacyRuntimeNotice);
4491
+ return;
4492
+ }
4493
+ if (!modelOnlyHost && choices === void 0) {
4494
+ await showNotice("Runtime availability is not confirmed. Reopen /model to try again.");
4495
+ return;
4496
+ }
4497
+ const selectedRuntime = normalizeOptionalString(parsed.runtime) ?? resolveRuntimeToken(choices, parsed.runtimeToken);
4498
+ if (choices?.length === 0 || parsed.runtimeToken && selectedRuntime === void 0 || selectedRuntime && selectedRuntime !== "auto" && selectedRuntime !== "default" && !choices?.some((choice) => choice.id === selectedRuntime)) {
4499
+ await showNotice("That runtime is not available for this model. Reopen /model and choose again.");
4500
+ return;
4501
+ }
4220
4502
  const selectionCommand = buildDiscordModelPickerSelectionCommand({
4221
4503
  modelRef: resolvedModelRef,
4222
4504
  runtime: selectedRuntime
@@ -4226,17 +4508,20 @@ async function handleDiscordModelPickerInteraction(params) {
4226
4508
  return;
4227
4509
  }
4228
4510
  if (await showNotice(`Applying model change to ${resolvedModelRef}...`) === null) return;
4511
+ if (pickerData.isCurrent?.() === false) {
4512
+ await showNotice("That model picker expired. Reopen /model to try again.");
4513
+ return;
4514
+ }
4515
+ if (modelOnlyHost && !supportsModelOnlySelection()) {
4516
+ await showNotice(legacyRuntimeNotice);
4517
+ return;
4518
+ }
4229
4519
  const applyResult = await applyDiscordModelPickerSelection({
4520
+ ...ctx,
4230
4521
  interaction,
4231
4522
  selectionCommand,
4232
4523
  dispatchCommandInteraction: params.dispatchCommandInteraction,
4233
4524
  cfg,
4234
- discordConfig: ctx.discordConfig,
4235
- readPolicy: ctx.readPolicy,
4236
- accountId: ctx.accountId,
4237
- sessionPrefix: ctx.sessionPrefix,
4238
- threadBindings: ctx.threadBindings,
4239
- dispatchReplyFromConfig: ctx.dispatchReplyFromConfig,
4240
4525
  route,
4241
4526
  resolvedModelRef,
4242
4527
  selectedRuntime,
@@ -4394,22 +4679,13 @@ function buildDiscordCommandOptions(params) {
4394
4679
  if (!args || args.length === 0) return;
4395
4680
  return args.map((arg) => {
4396
4681
  const required = arg.required ?? false;
4397
- if (arg.type === "number") return {
4398
- name: arg.name,
4399
- description: truncateDiscordCommandDescription({
4400
- value: arg.description,
4401
- label: `command:${commandLabel} arg:${arg.name}`
4402
- }),
4403
- type: ApplicationCommandOptionType.Number,
4404
- required
4405
- };
4406
- if (arg.type === "boolean") return {
4682
+ if (arg.type === "number" || arg.type === "boolean") return {
4407
4683
  name: arg.name,
4408
4684
  description: truncateDiscordCommandDescription({
4409
4685
  value: arg.description,
4410
4686
  label: `command:${commandLabel} arg:${arg.name}`
4411
4687
  }),
4412
- type: ApplicationCommandOptionType.Boolean,
4688
+ type: arg.type === "number" ? ApplicationCommandOptionType.Number : ApplicationCommandOptionType.Boolean,
4413
4689
  required
4414
4690
  };
4415
4691
  const resolvedChoices = resolveCommandArgChoices({
@@ -4440,7 +4716,7 @@ function buildDiscordCommandOptions(params) {
4440
4716
  provider: context?.provider,
4441
4717
  model: context?.model,
4442
4718
  agentRuntime: context?.agentRuntime,
4443
- ...choiceCatalog?.length ? { catalog: choiceCatalog } : {}
4719
+ catalog: choiceCatalog
4444
4720
  });
4445
4721
  const filtered = focusValue ? choices.filter((choice) => normalizeLowercaseStringOrEmpty(choice.label).includes(focusValue)) : choices;
4446
4722
  await interaction.respond(filtered.slice(0, 25).map((choice) => ({
@@ -4469,18 +4745,8 @@ function buildDiscordCommandOptions(params) {
4469
4745
  //#region extensions/discord/src/monitor/native-command.ts
4470
4746
  const log = createSubsystemLogger("discord/native-command");
4471
4747
  const NON_PLUGIN_COMMAND_DISPATCH = Object.freeze({ kind: "non-plugin" });
4472
- function resolveDiscordNativePolicyReader(params) {
4473
- return params.readPolicy ?? createDiscordLivePolicyReader({
4474
- ...params,
4475
- readConfig: () => getRuntimeConfigSnapshot() ?? params.cfg,
4476
- resolvedAllowlist: {
4477
- guildEntries: params.discordConfig?.guilds,
4478
- allowFrom: params.discordConfig?.allowFrom ?? resolveDiscordAccountAllowFrom(params)
4479
- }
4480
- });
4481
- }
4482
4748
  function createDiscordNativeCommand(params) {
4483
- const { command, cfg, discordConfig, accountId, sessionPrefix, ephemeralDefault, threadBindings, dispatchReplyFromConfig } = params;
4749
+ const { command, cfg, discordConfig, accountId, sessionPrefix, ephemeralDefault, threadBindings, buildContext, dispatchReplyFromConfig } = params;
4484
4750
  const fallbackCommandDefinition = createNativeCommandDefinition(command);
4485
4751
  const pluginCommandCandidate = "prepareDispatch" in command ? command : void 0;
4486
4752
  const commandDefinition = pluginCommandCandidate ? fallbackCommandDefinition : findCommandByNativeName$1(command.name, "discord", { includeBundledChannelFallback: false }) ?? fallbackCommandDefinition;
@@ -4499,6 +4765,9 @@ function createDiscordNativeCommand(params) {
4499
4765
  ...policy,
4500
4766
  isPolicyCurrent: policy.isCurrent,
4501
4767
  accountId,
4768
+ sessionPrefix,
4769
+ threadBindings,
4770
+ buildContext,
4502
4771
  skipCommandOwnerAllowFrom: pluginCommandCandidate !== void 0
4503
4772
  });
4504
4773
  },
@@ -4553,6 +4822,7 @@ function createDiscordNativeCommand(params) {
4553
4822
  preferFollowUp: true,
4554
4823
  threadBindings,
4555
4824
  responseEphemeral: ephemeralDefault,
4825
+ buildContext,
4556
4826
  dispatchReplyFromConfig,
4557
4827
  pluginCommandDispatch: preparedPluginCommand ?? NON_PLUGIN_COMMAND_DISPATCH
4558
4828
  });
@@ -4560,7 +4830,7 @@ function createDiscordNativeCommand(params) {
4560
4830
  }();
4561
4831
  }
4562
4832
  async function dispatchDiscordCommandInteraction(params) {
4563
- const { interaction, prompt, command, commandArgs, cfg: inputConfig, discordConfig: inputDiscordConfig, accountId, sessionPrefix, preferFollowUp, threadBindings, responseEphemeral, suppressReplies, dispatchReplyFromConfig } = params;
4833
+ const { interaction, prompt, command, commandArgs, cfg: inputConfig, discordConfig: inputDiscordConfig, accountId, sessionPrefix, preferFollowUp, threadBindings, responseEphemeral, suppressReplies, buildContext, dispatchReplyFromConfig } = params;
4564
4834
  const policy = await params.readPolicy?.();
4565
4835
  const cfg = policy?.cfg ?? getRuntimeConfigSnapshot() ?? inputConfig;
4566
4836
  const discordConfig = policy?.discordConfig ?? inputDiscordConfig;
@@ -4587,12 +4857,13 @@ async function dispatchDiscordCommandInteraction(params) {
4587
4857
  pluralkitInfo: null
4588
4858
  });
4589
4859
  const channel = interaction.channel;
4590
- const { isDirectMessage, isGroupDm, isThreadChannel, channelName, channelSlug, rawChannelId, threadParentId, threadParentName, threadParentSlug } = await resolveDiscordNativeInteractionChannelContext({
4860
+ const channelContext = await resolveDiscordNativeInteractionChannelContext({
4591
4861
  channel,
4592
4862
  client: interaction.client,
4593
4863
  hasGuild: Boolean(interaction.guild),
4594
- channelIdFallback: ""
4864
+ channelIdFallback: interaction.rawData.channel_id ?? ""
4595
4865
  });
4866
+ const { isDirectMessage, isGroupDm, isThreadChannel, channelName, channelSlug, rawChannelId, threadParentId, threadParentName, threadParentSlug } = channelContext;
4596
4867
  if (policy?.isCurrent() === false) {
4597
4868
  await respond("Access policy changed. Try this interaction again.", { ephemeral: true });
4598
4869
  return { accepted: false };
@@ -4603,7 +4874,6 @@ async function dispatchDiscordCommandInteraction(params) {
4603
4874
  cfg,
4604
4875
  accountId
4605
4876
  }) ?? [];
4606
- const commandOwnerAllowFrom = resolveDiscordCommandOwnerAllowFrom(cfg);
4607
4877
  const { ownerAllowList: discordOwnerAllowList, ownerAllowed: discordOwnerOk } = resolveDiscordOwnerAccess({
4608
4878
  allowFrom: configuredDmAllowFrom,
4609
4879
  sender: {
@@ -4613,18 +4883,6 @@ async function dispatchDiscordCommandInteraction(params) {
4613
4883
  },
4614
4884
  allowNameMatching
4615
4885
  });
4616
- const { ownerAllowed: commandOwnerOk } = resolveDiscordOwnerAccess({
4617
- allowFrom: commandOwnerAllowFrom,
4618
- sender: {
4619
- id: sender.id,
4620
- name: sender.name,
4621
- tag: sender.tag
4622
- },
4623
- allowNameMatching
4624
- });
4625
- const commandOwnerAllowAll = commandOwnerAllowFrom?.includes("*") === true;
4626
- const senderIsCommandOwner = commandOwnerOk;
4627
- const commandOwnerAccessAllowed = senderIsCommandOwner || commandOwnerAllowAll;
4628
4886
  const ownerAllowListConfigured = discordOwnerAllowList != null;
4629
4887
  const ownerOk = discordOwnerOk;
4630
4888
  const { commandsAllowFromAccess, guildInfo, channelConfig } = resolveDiscordNativeCommandChannelAccessContext({
@@ -4642,8 +4900,8 @@ async function dispatchDiscordCommandInteraction(params) {
4642
4900
  threadParentName,
4643
4901
  threadParentSlug
4644
4902
  });
4645
- let nativeRouteStatePromise;
4646
- const getNativeRouteState = () => nativeRouteStatePromise ??= nativeCommandRuntime.resolveDiscordNativeInteractionRouteState({
4903
+ let nativeRouteState;
4904
+ const getNativeRouteState = () => nativeRouteState ??= nativeCommandRuntime.resolveDiscordNativeInteractionRouteState({
4647
4905
  cfg,
4648
4906
  accountId,
4649
4907
  guildId: interaction.guild?.id ?? void 0,
@@ -4653,19 +4911,18 @@ async function dispatchDiscordCommandInteraction(params) {
4653
4911
  directUserId: user.id,
4654
4912
  conversationId: rawChannelId || "unknown",
4655
4913
  parentConversationId: threadParentId,
4656
- threadBinding: isThreadChannel ? threadBindings.getByThreadId(rawChannelId) : void 0,
4657
- enforceConfiguredBindingReadiness: !shouldBypassConfiguredAcpEnsure(commandName)
4914
+ threadBinding: isThreadChannel ? threadBindings.getByThreadId(rawChannelId) : void 0
4658
4915
  });
4659
- const canBypassConfiguredAcpGuildGuards = async () => {
4916
+ const canBypassConfiguredAcpGuildGuards = () => {
4660
4917
  if (!interaction.guild || !shouldBypassConfiguredAcpGuildGuards(commandName)) return false;
4661
- const routeState = await getNativeRouteState();
4662
- return routeState.effectiveRoute.matchedBy === "binding.channel" || routeState.boundSessionKey != null || routeState.configuredBinding != null || routeState.configuredRoute != null;
4918
+ const routeState = getNativeRouteState();
4919
+ return routeState.effectiveRoute.matchedBy === "binding.channel" || routeState.boundSessionKey != null || routeState.configuredBinding != null;
4663
4920
  };
4664
- if (channelConfig?.enabled === false && !await canBypassConfiguredAcpGuildGuards()) {
4921
+ if (channelConfig?.enabled === false && !canBypassConfiguredAcpGuildGuards()) {
4665
4922
  await respond("This channel is disabled.");
4666
4923
  return { accepted: false };
4667
4924
  }
4668
- if (interaction.guild && channelConfig?.allowed === false && !await canBypassConfiguredAcpGuildGuards()) {
4925
+ if (interaction.guild && channelConfig?.allowed === false && !canBypassConfiguredAcpGuildGuards()) {
4669
4926
  await respond("This channel is not allowed.");
4670
4927
  return { accepted: false };
4671
4928
  }
@@ -4679,7 +4936,7 @@ async function dispatchDiscordCommandInteraction(params) {
4679
4936
  groupPolicy,
4680
4937
  guildInfo,
4681
4938
  channelConfig
4682
- }).allowed && !await canBypassConfiguredAcpGuildGuards()) {
4939
+ }).allowed && !canBypassConfiguredAcpGuildGuards()) {
4683
4940
  await respond("This channel is not allowed.");
4684
4941
  return { accepted: false };
4685
4942
  }
@@ -4767,7 +5024,7 @@ async function dispatchDiscordCommandInteraction(params) {
4767
5024
  ownerAllowListConfigured,
4768
5025
  ownerAllowed: ownerOk
4769
5026
  });
4770
- if (!commandAuthorized && !await canBypassConfiguredAcpGuildGuards()) {
5027
+ if (!commandAuthorized && !canBypassConfiguredAcpGuildGuards()) {
4771
5028
  await respond("You are not authorized to use this command.", { ephemeral: true });
4772
5029
  return { accepted: false };
4773
5030
  }
@@ -4776,18 +5033,63 @@ async function dispatchDiscordCommandInteraction(params) {
4776
5033
  await respond("Access policy changed. Try this interaction again.", { ephemeral: true });
4777
5034
  return { accepted: false };
4778
5035
  }
4779
- if (commandOwnerAllowFrom && !commandOwnerAccessAllowed && !commandsAllowFromAccess.allowed && commandName !== "status" && params.pluginCommandDispatch.kind !== "plugin") {
5036
+ const routeState = getNativeRouteState();
5037
+ const effectiveRoute = routeState.effectiveRoute;
5038
+ const { ctxPayload, sessionKey, commandTargetSessionKey } = await buildDiscordNativeInteractionContext({
5039
+ buildContext,
5040
+ interaction,
5041
+ channelContext,
5042
+ route: effectiveRoute,
5043
+ boundSessionKey: routeState.boundSessionKey,
5044
+ sessionPrefix,
5045
+ prompt,
5046
+ commandArgs: commandArgs ?? {},
5047
+ channelConfig,
5048
+ guildInfo,
5049
+ allowNameMatching,
5050
+ commandAuthorized,
5051
+ user,
5052
+ sender
5053
+ });
5054
+ const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg, effectiveRoute.agentId);
5055
+ if (policy?.isCurrent() === false) {
5056
+ await respond("Access policy changed. Try this interaction again.", { ephemeral: true });
5057
+ return { accepted: false };
5058
+ }
5059
+ const authority = createDiscordNativeCommandAuthority({
5060
+ cfg,
5061
+ ctx: ctxPayload,
5062
+ commandAuthorized,
5063
+ sender,
5064
+ allowNameMatching,
5065
+ isPolicyCurrent: policy?.isCurrent,
5066
+ accountId,
5067
+ guildId: interaction.guild?.id,
5068
+ commandName,
5069
+ pluginCommand: params.pluginCommandDispatch.kind === "plugin"
5070
+ });
5071
+ if (!authority.isAllowed()) {
5072
+ await respond("You are not authorized to use this command.", { ephemeral: true });
5073
+ return { accepted: false };
5074
+ }
5075
+ const bindingReadiness = routeState.configuredBinding && !shouldBypassConfiguredAcpEnsure(commandName) ? await nativeCommandRuntime.ensureConfiguredBindingRouteReady({
5076
+ cfg,
5077
+ bindingResolution: routeState.configuredBinding,
5078
+ assertActive: authority.assertActive
5079
+ }) : null;
5080
+ if (!authority.isAllowed()) {
4780
5081
  await respond("You are not authorized to use this command.", { ephemeral: true });
4781
5082
  return { accepted: false };
4782
5083
  }
4783
5084
  const isGuild = Boolean(interaction.guild);
4784
5085
  const channelId = rawChannelId || "unknown";
4785
5086
  const menuNeedsModelContext = !(commandArgs?.raw && !commandArgs.values) && command.args?.some((arg) => typeof arg.choices === "function" && commandArgs?.values?.[arg.name] == null);
4786
- const menuModelContext = menuNeedsModelContext ? await resolveDiscordNativeChoiceContext({
5087
+ const menuModelContext = menuNeedsModelContext && bindingReadiness?.ok !== false ? await resolveDiscordNativeChoiceContext({
4787
5088
  interaction,
4788
5089
  cfg,
4789
5090
  accountId,
4790
- threadBindings
5091
+ threadBindings,
5092
+ route: effectiveRoute
4791
5093
  }) : null;
4792
5094
  const menuModelCatalog = command.key === "think" && menuNeedsModelContext ? await loadPreparedModelCatalog({
4793
5095
  config: cfg,
@@ -4797,17 +5099,20 @@ async function dispatchDiscordCommandInteraction(params) {
4797
5099
  } : {},
4798
5100
  readOnly: true
4799
5101
  }) : void 0;
4800
- const menuRouteState = command.key === "verbose" ? await getNativeRouteState() : void 0;
4801
- const menu = menuRouteState?.bindingReadiness?.ok === false ? null : resolveCommandArgMenu({
5102
+ const menu = command.key === "verbose" && bindingReadiness?.ok === false ? null : resolveCommandArgMenu({
4802
5103
  command,
4803
5104
  args: commandArgs,
4804
5105
  cfg,
4805
- session: menuRouteState?.effectiveRoute,
5106
+ session: command.key === "verbose" ? effectiveRoute : void 0,
4806
5107
  provider: menuModelContext?.provider,
4807
5108
  model: menuModelContext?.model,
4808
5109
  agentRuntime: menuModelContext?.agentRuntime,
4809
- ...menuModelCatalog?.length ? { catalog: menuModelCatalog } : {}
5110
+ catalog: menuModelCatalog
4810
5111
  });
5112
+ if (policy?.isCurrent() === false) {
5113
+ await respond("Access policy changed. Try this interaction again.", { ephemeral: true });
5114
+ return { accepted: false };
5115
+ }
4811
5116
  if (menu) {
4812
5117
  const menuPayload = buildDiscordCommandArgMenu({
4813
5118
  command,
@@ -4819,6 +5124,7 @@ async function dispatchDiscordCommandInteraction(params) {
4819
5124
  accountId,
4820
5125
  sessionPrefix,
4821
5126
  threadBindings,
5127
+ buildContext,
4822
5128
  dispatchReplyFromConfig
4823
5129
  },
4824
5130
  safeInteractionCall: safeDiscordInteractionCall,
@@ -4846,19 +5152,20 @@ async function dispatchDiscordCommandInteraction(params) {
4846
5152
  }
4847
5153
  const messageThreadId = !isDirectMessage && isThreadChannel ? channelId : void 0;
4848
5154
  const pluginThreadParentId = !isDirectMessage && isThreadChannel ? threadParentId : void 0;
4849
- const routeState = await getNativeRouteState();
4850
- const { effectiveRoute } = routeState;
4851
5155
  const pluginCommandAgentId = (isThreadChannel ? threadBindings.getByThreadId(rawChannelId)?.agentId : void 0) || routeState.configuredBinding?.statefulTarget.agentId || effectiveRoute.agentId;
4852
5156
  const targetSessionEntry = nativeCommandRuntime.getSessionEntry({
4853
5157
  agentId: pluginCommandAgentId,
4854
5158
  sessionKey: effectiveRoute.sessionKey
4855
5159
  });
5160
+ authority.assertActive();
5161
+ const senderIsOwner = authority.senderIsOwner();
4856
5162
  const pluginReply = await params.pluginCommandDispatch.execute({
4857
5163
  senderId: sender.id,
4858
5164
  channel: "discord",
4859
5165
  channelId,
4860
5166
  isAuthorizedSender: commandAuthorized,
4861
- senderIsOwner: senderIsCommandOwner,
5167
+ senderIsOwner,
5168
+ ...senderIsOwner ? { assertOwnerCurrent: authority.assertOwnerCurrent } : {},
4862
5169
  agentId: pluginCommandAgentId,
4863
5170
  sessionKey: effectiveRoute.sessionKey,
4864
5171
  authProfileId: targetSessionEntry?.authProfileOverride,
@@ -4919,58 +5226,14 @@ async function dispatchDiscordCommandInteraction(params) {
4919
5226
  });
4920
5227
  return { accepted: true };
4921
5228
  }
4922
- const interactionId = interaction.rawData.id;
4923
- const routeState = await getNativeRouteState();
4924
- if (routeState.bindingReadiness && !routeState.bindingReadiness.ok) {
5229
+ if (bindingReadiness && !bindingReadiness.ok) {
4925
5230
  const configuredBinding = routeState.configuredBinding;
4926
5231
  if (configuredBinding) {
4927
- logVerbose(`discord native command: configured ACP binding unavailable for channel ${configuredBinding.record.conversation.conversationId}: ${routeState.bindingReadiness.error}`);
5232
+ logVerbose(`discord native command: configured ACP binding unavailable for channel ${configuredBinding.record.conversation.conversationId}: ${bindingReadiness.error}`);
4928
5233
  await respond("Configured ACP binding is unavailable right now. Please try again.");
4929
5234
  return { accepted: false };
4930
5235
  }
4931
5236
  }
4932
- const boundSessionKey = routeState.boundSessionKey;
4933
- const effectiveRoute = routeState.effectiveRoute;
4934
- const { sessionKey, commandTargetSessionKey } = resolveNativeCommandSessionTargets({
4935
- agentId: effectiveRoute.agentId,
4936
- sessionPrefix,
4937
- userId: user.id,
4938
- targetSessionKey: effectiveRoute.sessionKey,
4939
- boundSessionKey
4940
- });
4941
- const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg, effectiveRoute.agentId);
4942
- const ctxPayload = buildDiscordNativeCommandContext({
4943
- prompt,
4944
- commandArgs: commandArgs ?? {},
4945
- sessionKey,
4946
- commandTargetSessionKey,
4947
- accountId: effectiveRoute.accountId,
4948
- interactionId,
4949
- channelId,
4950
- threadParentId,
4951
- memberRoleIds,
4952
- guildId: interaction.guild?.id,
4953
- guildName: interaction.guild?.name,
4954
- channelTopic: resolveDiscordChannelTopicSafe(channel),
4955
- channelConfig,
4956
- guildInfo,
4957
- allowNameMatching,
4958
- commandAuthorized,
4959
- isDirectMessage,
4960
- isGroupDm,
4961
- isGuild,
4962
- isThreadChannel,
4963
- user: {
4964
- id: user.id,
4965
- username: user.username,
4966
- globalName: user.globalName
4967
- },
4968
- sender: {
4969
- id: sender.id,
4970
- name: sender.name,
4971
- tag: sender.tag
4972
- }
4973
- });
4974
5237
  const directStatusResult = await maybeDeliverDiscordDirectStatus({
4975
5238
  commandName,
4976
5239
  suppressReplies,
@@ -4982,7 +5245,7 @@ async function dispatchDiscordCommandInteraction(params) {
4982
5245
  commandTargetSessionKey,
4983
5246
  channel: "discord",
4984
5247
  senderId: sender.id,
4985
- senderIsOwner: senderIsCommandOwner,
5248
+ senderIsOwner: authority.senderIsOwner(),
4986
5249
  isAuthorizedSender: commandAuthorized,
4987
5250
  isGroup: isGuild || isGroupDm,
4988
5251
  defaultGroupActivation: () => !isGuild ? "always" : channelConfig?.requireMention === false ? "always" : "mention",
@@ -5975,7 +6238,7 @@ function parseDiscordGatewayInfoBody(body) {
5975
6238
  async function fetchDiscordGatewayInfo(params) {
5976
6239
  let response;
5977
6240
  try {
5978
- response = await params.fetchImpl(DISCORD_GATEWAY_BOT_URL, {
6241
+ response = await params.fetchImpl(params.gatewayBotUrl ?? DISCORD_GATEWAY_BOT_URL, {
5979
6242
  ...params.fetchInit,
5980
6243
  headers: {
5981
6244
  ...params.fetchInit?.headers,
@@ -5984,7 +6247,7 @@ async function fetchDiscordGatewayInfo(params) {
5984
6247
  });
5985
6248
  } catch (error) {
5986
6249
  throw createGatewayMetadataError({
5987
- detail: formatErrorMessage(error),
6250
+ detail: formatErrorMessage$1(error),
5988
6251
  transient: true,
5989
6252
  cause: error
5990
6253
  });
@@ -5994,7 +6257,7 @@ async function fetchDiscordGatewayInfo(params) {
5994
6257
  body = await response.text();
5995
6258
  } catch (error) {
5996
6259
  throw createGatewayMetadataError({
5997
- detail: formatErrorMessage(error),
6260
+ detail: formatErrorMessage$1(error),
5998
6261
  transient: true,
5999
6262
  cause: error
6000
6263
  });
@@ -6009,7 +6272,7 @@ async function fetchDiscordGatewayInfo(params) {
6009
6272
  return parseDiscordGatewayInfoBody(body);
6010
6273
  } catch (error) {
6011
6274
  throw createGatewayMetadataError({
6012
- detail: `Discord API /gateway/bot returned invalid metadata: ${formatErrorMessage(error)} (${summary})`,
6275
+ detail: `Discord API /gateway/bot returned invalid metadata: ${formatErrorMessage$1(error)} (${summary})`,
6013
6276
  transient,
6014
6277
  cause: error
6015
6278
  });
@@ -6026,6 +6289,7 @@ async function fetchDiscordGatewayInfoWithTimeout(params) {
6026
6289
  }),
6027
6290
  run: async (signal) => await fetchDiscordGatewayInfo({
6028
6291
  token: params.token,
6292
+ gatewayBotUrl: params.gatewayBotUrl,
6029
6293
  fetchImpl: params.fetchImpl,
6030
6294
  fetchInit: {
6031
6295
  ...params.fetchInit,
@@ -6036,7 +6300,7 @@ async function fetchDiscordGatewayInfoWithTimeout(params) {
6036
6300
  }
6037
6301
  function resolveGatewayInfoWithFallback(params) {
6038
6302
  if (!isTransientGatewayMetadataError(params.error)) throw params.error;
6039
- const message = formatErrorMessage(params.error);
6303
+ const message = formatErrorMessage$1(params.error);
6040
6304
  const now = Date.now();
6041
6305
  if (params.runtime) {
6042
6306
  const previous = gatewayMetadataFallbackLogLastAt.get(params.runtime);
@@ -6179,16 +6443,20 @@ function createGatewayPlugin(params) {
6179
6443
  if (!this.gatewayInfo || this.gatewayInfoUsedFallback) {
6180
6444
  const resolved = await fetchDiscordGatewayInfoWithTimeout({
6181
6445
  token: client.options.token,
6446
+ ...params.endpoint ? { gatewayBotUrl: params.endpoint.gatewayBotUrl } : {},
6182
6447
  fetchImpl: params.fetchImpl,
6183
6448
  fetchInit: params.fetchInit,
6184
6449
  timeoutMs: params.gatewayInfoTimeoutMs
6185
6450
  }).then((info) => ({
6186
6451
  info,
6187
6452
  usedFallback: false
6188
- })).catch((error) => resolveGatewayInfoWithFallback({
6189
- runtime: params.runtime,
6190
- error
6191
- }));
6453
+ })).catch((error) => {
6454
+ if (params.endpoint) throw error;
6455
+ return resolveGatewayInfoWithFallback({
6456
+ runtime: params.runtime,
6457
+ error
6458
+ });
6459
+ });
6192
6460
  this.gatewayInfo = resolved.info;
6193
6461
  this.gatewayInfoUsedFallback = resolved.usedFallback;
6194
6462
  }
@@ -6201,6 +6469,7 @@ function createGatewayPlugin(params) {
6201
6469
  }
6202
6470
  createWebSocket(url) {
6203
6471
  if (!url) throw new Error("Gateway URL is required");
6472
+ assertDiscordEndpointGatewayUrl(url, params.endpoint?.gatewayOrigin);
6204
6473
  const wsFlowId = randomUUID();
6205
6474
  const socket = new ((params.testing?.webSocketCtor) ?? WebSocket)(url, {
6206
6475
  ...DISCORD_GATEWAY_WS_CLIENT_OPTIONS,
@@ -6274,13 +6543,21 @@ function createGatewayPlugin(params) {
6274
6543
  }
6275
6544
  return new OpenClawGatewayPlugin();
6276
6545
  }
6277
- function createDiscordGatewayMetadataFetch(debugCaptureEnabled, proxyUrl) {
6546
+ function createDiscordGatewayMetadataFetch(debugCaptureEnabled, transport) {
6547
+ const endpoint = transport?.endpoint;
6548
+ if (endpoint) return (input, init) => {
6549
+ const signal = init?.signal instanceof AbortSignal ? init.signal : void 0;
6550
+ return endpoint.fetch(input, {
6551
+ ...init?.headers ? { headers: init.headers } : {},
6552
+ ...signal ? { signal } : {}
6553
+ });
6554
+ };
6278
6555
  return (input, init) => fetchDiscordGatewayMetadataGuarded(input, init, {
6279
6556
  ...debugCaptureEnabled ? {} : { capture: {
6280
6557
  flowId: randomUUID(),
6281
6558
  meta: { subsystem: "discord-gateway-metadata" }
6282
6559
  } },
6283
- ...proxyUrl ? { proxyUrl } : {}
6560
+ ...transport?.proxyUrl ? { proxyUrl: transport.proxyUrl } : {}
6284
6561
  });
6285
6562
  }
6286
6563
  function waitForDiscordGatewayPluginRegistration(plugin) {
@@ -6295,16 +6572,23 @@ function createDiscordGatewayPlugin(params) {
6295
6572
  const proxy = resolveEffectiveDebugProxyUrl(params.discordConfig?.proxy);
6296
6573
  const debugProxySettings = resolveDebugProxySettings();
6297
6574
  const gatewayInfoTimeoutMs = resolveDiscordGatewayInfoTimeoutMs({ env: process.env });
6298
- let fetchImpl = createDiscordGatewayMetadataFetch(debugProxySettings.enabled);
6299
- let wsAgent = new Agent$1({ lookup: discordDnsLookup });
6300
- if (proxy) try {
6575
+ const endpointRuntime = getDiscordEndpointRuntime();
6576
+ const endpoint = endpointRuntime ? {
6577
+ gatewayBotUrl: endpointRuntime.descriptor.gatewayBotUrl,
6578
+ gatewayOrigin: endpointRuntime.descriptor.gatewayOrigin,
6579
+ fetch: endpointRuntime.fetch
6580
+ } : void 0;
6581
+ const endpointGatewayUrl = endpoint ? new URL(endpoint.gatewayOrigin) : void 0;
6582
+ let fetchImpl = createDiscordGatewayMetadataFetch(debugProxySettings.enabled, endpoint ? { endpoint } : void 0);
6583
+ let wsAgent = endpointGatewayUrl?.protocol === "ws:" ? void 0 : new Agent$1({ lookup: endpointGatewayUrl ? createDiscordEndpointDnsLookup(endpointGatewayUrl.hostname) : discordDnsLookup });
6584
+ if (proxy && !endpoint) try {
6301
6585
  validateDiscordProxyUrl(proxy);
6302
6586
  wsAgent = params.testing?.createProxyAgent?.(proxy) ?? createNodeProxyAgent({
6303
6587
  mode: "explicit",
6304
6588
  proxyUrl: proxy,
6305
6589
  protocol: "https"
6306
6590
  });
6307
- fetchImpl = createDiscordGatewayMetadataFetch(debugProxySettings.enabled, proxy);
6591
+ fetchImpl = createDiscordGatewayMetadataFetch(debugProxySettings.enabled, { proxyUrl: proxy });
6308
6592
  params.runtime.log?.("discord: gateway proxy enabled");
6309
6593
  } catch (err) {
6310
6594
  params.runtime.error?.(danger(`discord: invalid gateway proxy: ${String(err)}`));
@@ -6317,6 +6601,7 @@ function createDiscordGatewayPlugin(params) {
6317
6601
  autoInteractions: false
6318
6602
  },
6319
6603
  gatewayInfoTimeoutMs,
6604
+ ...endpoint ? { endpoint } : {},
6320
6605
  fetchImpl,
6321
6606
  runtime: params.runtime,
6322
6607
  testing: params.testing,
@@ -6362,12 +6647,12 @@ function readFirstStackFrame(err) {
6362
6647
  return frame ? frame.replace(/^at\s+/, "") : void 0;
6363
6648
  }
6364
6649
  function formatDiscordGatewayErrorMessage(err) {
6365
- if (!(err instanceof Error)) return formatErrorMessage$1(err);
6650
+ if (!(err instanceof Error)) return formatErrorMessage(err);
6366
6651
  if (err.message) {
6367
- const detail = formatErrorMessage$1(err);
6652
+ const detail = formatErrorMessage(err);
6368
6653
  return err.name ? `${err.name}: ${detail}` : detail;
6369
6654
  }
6370
- const detail = formatErrorMessage$1(err);
6655
+ const detail = formatErrorMessage(err);
6371
6656
  const firstFrame = readFirstStackFrame(err);
6372
6657
  if (firstFrame && detail === (err.name || "Error")) return `${detail} @ ${firstFrame}`;
6373
6658
  return detail;
@@ -6901,7 +7186,7 @@ async function runDiscordGatewayLifecycle(params) {
6901
7186
  });
6902
7187
  try {
6903
7188
  if (drainPendingGatewayErrors() === "stop") return;
6904
- if (gatewayReadyAtLifecycleStart && params.voiceManager) params.voiceManager.autoJoin().catch((err) => params.runtime.error?.(danger(`discord voice: autoJoin failed: ${formatErrorMessage$1(err)}`)));
7189
+ if (gatewayReadyAtLifecycleStart && params.voiceManager) params.voiceManager.autoJoin().catch((err) => params.runtime.error?.(danger(`discord voice: autoJoin failed: ${formatErrorMessage(err)}`)));
6905
7190
  await waitForGatewayReady({
6906
7191
  gateway,
6907
7192
  abortSignal: params.abortSignal,
@@ -6946,7 +7231,7 @@ async function runDiscordGatewayLifecycle(params) {
6946
7231
  let discordVoiceRuntimePromise;
6947
7232
  let discordProviderSessionRuntimePromise;
6948
7233
  async function loadDiscordVoiceRuntime() {
6949
- const promise = discordVoiceRuntimePromise ?? import("./voice-runtime-DMYDMkJx.js").then((n) => n.t);
7234
+ const promise = discordVoiceRuntimePromise ?? import("./voice-runtime-elTtjEIG.mjs").then((n) => n.t);
6950
7235
  discordVoiceRuntimePromise = promise;
6951
7236
  try {
6952
7237
  return await promise;
@@ -6956,7 +7241,7 @@ async function loadDiscordVoiceRuntime() {
6956
7241
  }
6957
7242
  }
6958
7243
  async function loadDiscordProviderSessionRuntime() {
6959
- const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-U1M8_EYY.js");
7244
+ const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-DrGAYnZv.mjs");
6960
7245
  discordProviderSessionRuntimePromise = promise;
6961
7246
  try {
6962
7247
  return await promise;
@@ -6990,13 +7275,13 @@ function isLegacyMissingSessionError(message) {
6990
7275
  function classifyAcpStatusProbeError(params) {
6991
7276
  if (params.isAcpRuntimeError(params.error) && ["SESSION_OWNER_MIGRATION_REQUIRED", "SESSION_OWNER_UNSUPPORTED"].includes(params.error.detailCode ?? "")) return {
6992
7277
  status: "uncertain",
6993
- reason: formatErrorMessage$1(params.error)
7278
+ reason: formatErrorMessage(params.error)
6994
7279
  };
6995
7280
  if (params.isAcpRuntimeError(params.error) && params.error.code === "ACP_SESSION_INIT_FAILED") return {
6996
7281
  status: "stale",
6997
7282
  reason: "session-init-failed"
6998
7283
  };
6999
- if (isLegacyMissingSessionError(formatErrorMessage$1(params.error))) return {
7284
+ if (isLegacyMissingSessionError(formatErrorMessage(params.error))) return {
7000
7285
  status: "stale",
7001
7286
  reason: "session-missing"
7002
7287
  };
@@ -7060,7 +7345,12 @@ async function probeDiscordAcpBindingHealth(params) {
7060
7345
  //#endregion
7061
7346
  //#region extensions/discord/src/monitor/provider.cleanup.ts
7062
7347
  async function cleanupDiscordProviderStartup(params) {
7063
- await params.deactivateMessageHandler?.();
7348
+ const listenersStopped = params.stopMonitorListeners?.();
7349
+ try {
7350
+ await params.deactivateMessageHandler?.();
7351
+ } finally {
7352
+ await listenersStopped;
7353
+ }
7064
7354
  params.autoPresenceController?.stop();
7065
7355
  params.setStatus?.({ connected: false });
7066
7356
  if (params.onEarlyGatewayDebug) params.earlyGatewayEmitter?.removeListener("debug", params.onEarlyGatewayDebug);
@@ -7442,7 +7732,7 @@ function readDiscordDeployObjectField(value, field) {
7442
7732
  function isAbortLikeError(err) {
7443
7733
  if (!err || typeof err !== "object") return false;
7444
7734
  const name = "name" in err && typeof err.name === "string" ? err.name : void 0;
7445
- const message = formatErrorMessage$1(err);
7735
+ const message = formatErrorMessage(err);
7446
7736
  return name === "AbortError" || message === "This operation was aborted" || message === "The operation was aborted" || /\boperation was aborted\b/i.test(message);
7447
7737
  }
7448
7738
  function formatDiscordDeployRestOperation(err) {
@@ -7454,7 +7744,7 @@ function formatDiscordDeployRestOperation(err) {
7454
7744
  return "request";
7455
7745
  }
7456
7746
  function formatDiscordDeployErrorMessage(err) {
7457
- if (!isAbortLikeError(err)) return formatErrorMessage$1(err);
7747
+ if (!isAbortLikeError(err)) return formatErrorMessage(err);
7458
7748
  const deployErr = err && typeof err === "object" ? err : {};
7459
7749
  const requestMs = parseFiniteNumber$1(deployErr.deployRequestMs);
7460
7750
  const timeoutMs = parseFiniteNumber$1(deployErr.deployTimeoutMs);
@@ -7563,7 +7853,7 @@ function isDiscordDeployDailyCreateLimit(err) {
7563
7853
  const deployErr = err;
7564
7854
  const discordCode = parseStrictNonNegativeInteger$1(deployErr.discordCode);
7565
7855
  const rawCode = parseStrictNonNegativeInteger$1(readDiscordDeployObjectField(deployErr.rawBody, "code"));
7566
- return (discordCode === 30034 || rawCode === 30034) && /daily application command creates/i.test(formatErrorMessage$1(err));
7856
+ return (discordCode === 30034 || rawCode === 30034) && /daily application command creates/i.test(formatErrorMessage(err));
7567
7857
  }
7568
7858
  //#endregion
7569
7859
  //#region extensions/discord/src/monitor/provider.startup-log.ts
@@ -7698,7 +7988,7 @@ function runDiscordCommandDeployInBackground(params) {
7698
7988
  isVerbose: params.isVerbose
7699
7989
  });
7700
7990
  }).catch((err) => {
7701
- params.runtime.log?.(warn(`[${params.accountId}] slash command deploy failed in background (message send/receive unaffected): ${formatErrorMessage$1(err)}`));
7991
+ params.runtime.log?.(warn(`[${params.accountId}] slash command deploy failed in background (message send/receive unaffected): ${formatErrorMessage(err)}`));
7702
7992
  });
7703
7993
  }
7704
7994
  //#endregion
@@ -8596,8 +8886,8 @@ async function deliverDiscordReply(params) {
8596
8886
  }
8597
8887
  //#endregion
8598
8888
  //#region extensions/discord/src/monitor/agent-components.dispatch.ts
8599
- const loadConversationRuntime$1 = createLazyRuntimeModule(() => import("./agent-components.runtime-CEPrf2SY.js"));
8600
- const loadTypingRuntime = createLazyRuntimeModule(() => import("./typing-DuBg1U8Q.js").then((n) => n.n));
8889
+ const loadConversationRuntime$1 = createLazyRuntimeModule(() => import("./agent-components.runtime-CEPrf2SY.mjs"));
8890
+ const loadTypingRuntime = createLazyRuntimeModule(() => import("./typing-BKZL5fGj.mjs").then((n) => n.n));
8601
8891
  function buildDiscordComponentConversationLabel(params) {
8602
8892
  if (params.interactionCtx.isDirectMessage) return buildDirectLabel(params.interactionCtx.user);
8603
8893
  if (params.interactionCtx.isGroupDm) return `Group DM #${params.channelCtx.channelName ?? params.interactionCtx.channelId} channel id:${params.interactionCtx.channelId}`;
@@ -8742,13 +9032,11 @@ async function dispatchDiscordComponentEvent(params) {
8742
9032
  Surface: "discord",
8743
9033
  WasMentioned: true,
8744
9034
  CommandAuthorized: commandAuthorized,
8745
- CommandTurn: {
8746
- kind: "text-slash",
8747
- source: "text",
9035
+ CommandTurn: createCommandTurnContext(params.commandSource ?? "text", {
8748
9036
  authorized: commandAuthorized,
8749
9037
  body: eventText
8750
- },
8751
- CommandSource: "text",
9038
+ }),
9039
+ CommandSource: params.commandSource ?? "text",
8752
9040
  MessageSid: interaction.rawData.id,
8753
9041
  Timestamp: timestamp,
8754
9042
  OriginatingChannel: "discord",
@@ -8881,7 +9169,7 @@ async function dispatchDiscordPluginInteractiveHandler(params) {
8881
9169
  }
8882
9170
  //#endregion
8883
9171
  //#region extensions/discord/src/monitor/agent-components.plugin-interactive.ts
8884
- const loadConversationRuntime = createLazyRuntimeModule(() => import("./agent-components.runtime-CEPrf2SY.js"));
9172
+ const loadConversationRuntime = createLazyRuntimeModule(() => import("./agent-components.runtime-CEPrf2SY.mjs"));
8885
9173
  async function dispatchPluginDiscordInteractiveEvent(params) {
8886
9174
  const normalizedConversationId = params.interactionCtx.rawGuildId || params.channelCtx.channelType === ChannelType.GroupDM ? `channel:${params.interactionCtx.channelId}` : `user:${params.interactionCtx.userId}`;
8887
9175
  let responded = false;
@@ -9004,7 +9292,7 @@ async function dispatchPluginDiscordInteractiveEvent(params) {
9004
9292
  }
9005
9293
  //#endregion
9006
9294
  //#region extensions/discord/src/monitor/agent-components.handlers.ts
9007
- const loadComponentsRuntime = createLazyRuntimeModule(() => import("./components-DBFTIN6P.js").then((n) => n.t));
9295
+ const loadComponentsRuntime = createLazyRuntimeModule(() => import("./components-yBEb75bB.mjs").then((n) => n.t));
9008
9296
  async function handleDiscordComponentEvent(params) {
9009
9297
  const parsed = parseDiscordComponentData(params.data, resolveInteractionCustomId(params.interaction));
9010
9298
  if (!parsed) {
@@ -9090,6 +9378,7 @@ async function handleDiscordComponentEvent(params) {
9090
9378
  channelCtx,
9091
9379
  guildInfo,
9092
9380
  eventText,
9381
+ commandSource: consumed.callbackDataKind === "command" && (buttonCallbackFallback || selectedCommandFallback) ? "native" : void 0,
9093
9382
  replyToId: consumed.messageId ?? params.interaction.message?.id,
9094
9383
  routeOverrides: {
9095
9384
  sessionKey: consumed.sessionKey,
@@ -9582,11 +9871,14 @@ var ExecApprovalButton = class extends Button {
9582
9871
  const terminalLabel = resolveTerminalLabel(result.resolution.approval);
9583
9872
  let terminalized = false;
9584
9873
  try {
9585
- await interaction.editReply(buildTerminalPayload({
9586
- approval: result.resolution.approval,
9587
- applied: result.resolution.applied
9588
- }));
9589
- terminalized = true;
9874
+ if (interaction.message) terminalized = await discordApprovalMessageUpdates.enqueue(interaction.message.id, async () => {
9875
+ if (!hasDiscordApprovalControl(await interaction.fetchReply(), parsed)) return false;
9876
+ await interaction.editReply(buildTerminalPayload({
9877
+ approval: result.resolution.approval,
9878
+ applied: result.resolution.applied
9879
+ }));
9880
+ return true;
9881
+ });
9590
9882
  } catch {}
9591
9883
  if (!terminalized || !result.resolution.applied) try {
9592
9884
  await interaction.followUp({
@@ -9717,6 +10009,7 @@ function createDiscordProviderInteractionSurface(params) {
9717
10009
  sessionPrefix: params.sessionPrefix,
9718
10010
  ephemeralDefault: params.ephemeralDefault,
9719
10011
  threadBindings: params.threadBindings,
10012
+ buildContext: params.channelRuntime?.inbound.buildContext,
9720
10013
  dispatchReplyFromConfig: params.channelRuntime?.reply?.dispatchReplyFromConfig
9721
10014
  });
9722
10015
  });
@@ -9765,6 +10058,7 @@ function createDiscordProviderInteractionSurface(params) {
9765
10058
  accountId: params.accountId,
9766
10059
  sessionPrefix: params.sessionPrefix,
9767
10060
  threadBindings: params.threadBindings,
10061
+ buildContext: params.channelRuntime?.inbound.buildContext,
9768
10062
  dispatchReplyFromConfig: params.channelRuntime?.reply?.dispatchReplyFromConfig
9769
10063
  }),
9770
10064
  createDiscordModelPickerFallbackButton({
@@ -9774,6 +10068,7 @@ function createDiscordProviderInteractionSurface(params) {
9774
10068
  accountId: params.accountId,
9775
10069
  sessionPrefix: params.sessionPrefix,
9776
10070
  threadBindings: params.threadBindings,
10071
+ buildContext: params.channelRuntime?.inbound.buildContext,
9777
10072
  dispatchReplyFromConfig: params.channelRuntime?.reply?.dispatchReplyFromConfig
9778
10073
  }),
9779
10074
  createDiscordModelPickerFallbackSelect({
@@ -9783,6 +10078,7 @@ function createDiscordProviderInteractionSurface(params) {
9783
10078
  accountId: params.accountId,
9784
10079
  sessionPrefix: params.sessionPrefix,
9785
10080
  threadBindings: params.threadBindings,
10081
+ buildContext: params.channelRuntime?.inbound.buildContext,
9786
10082
  dispatchReplyFromConfig: params.channelRuntime?.reply?.dispatchReplyFromConfig
9787
10083
  })
9788
10084
  ];
@@ -9858,7 +10154,7 @@ var VoicePlugin = class extends Plugin {
9858
10154
  }
9859
10155
  },
9860
10156
  destroy: () => {
9861
- this.adapters.delete(guildId);
10157
+ if (this.adapters.get(guildId) === methods) this.adapters.delete(guildId);
9862
10158
  }
9863
10159
  };
9864
10160
  };
@@ -9937,9 +10233,13 @@ var DiscordGuildJoinIntroductionListener = class extends GuildCreateListener {
9937
10233
  constructor(params) {
9938
10234
  super();
9939
10235
  this.params = params;
10236
+ this.stopped = false;
10237
+ this.pendingReports = /* @__PURE__ */ new Set();
9940
10238
  }
9941
10239
  async handle(data, client) {
10240
+ if (this.stopped) return;
9942
10241
  const policy = await this.params.readPolicy?.();
10242
+ if (this.stopped) return;
9943
10243
  const params = {
9944
10244
  ...this.params,
9945
10245
  ...policy
@@ -9987,6 +10287,7 @@ var DiscordGuildJoinIntroductionListener = class extends GuildCreateListener {
9987
10287
  break;
9988
10288
  }
9989
10289
  }
10290
+ if (this.stopped) return;
9990
10291
  if (policy?.isCurrent() === false) {
9991
10292
  params.logger?.info("Discord guild join introduction skipped: access policy changed", {
9992
10293
  guildId: data.id,
@@ -10002,7 +10303,7 @@ var DiscordGuildJoinIntroductionListener = class extends GuildCreateListener {
10002
10303
  return;
10003
10304
  }
10004
10305
  const selectedChannel = targetChannel;
10005
- await reportChannelRoomJoin({
10306
+ const report = reportChannelRoomJoin({
10006
10307
  cfg: params.cfg,
10007
10308
  channel: "discord",
10008
10309
  accountId: params.accountId,
@@ -10038,6 +10339,16 @@ var DiscordGuildJoinIntroductionListener = class extends GuildCreateListener {
10038
10339
  }
10039
10340
  }
10040
10341
  });
10342
+ this.pendingReports.add(report);
10343
+ try {
10344
+ await report;
10345
+ } finally {
10346
+ this.pendingReports.delete(report);
10347
+ }
10348
+ }
10349
+ async stop() {
10350
+ this.stopped = true;
10351
+ await Promise.allSettled(this.pendingReports);
10041
10352
  }
10042
10353
  };
10043
10354
  //#endregion
@@ -10165,7 +10476,7 @@ async function fetchDiscordBotIdentity(params) {
10165
10476
  function registerDiscordMonitorListeners(params) {
10166
10477
  registerDiscordListener(params.client.listeners, new DiscordInteractionListener(params.logger, params.trackInboundEvent));
10167
10478
  registerDiscordListener(params.client.listeners, new DiscordMessageListener(params.messageHandler, params.logger, params.trackInboundEvent));
10168
- registerDiscordListener(params.client.listeners, new DiscordGuildJoinIntroductionListener({
10479
+ const guildJoinListener = new DiscordGuildJoinIntroductionListener({
10169
10480
  readPolicy: params.readPolicy,
10170
10481
  cfg: params.cfg,
10171
10482
  accountId: params.accountId,
@@ -10173,7 +10484,8 @@ function registerDiscordMonitorListeners(params) {
10173
10484
  groupPolicy: params.groupPolicy,
10174
10485
  guildEntries: params.guildEntries,
10175
10486
  logger: params.logger
10176
- }));
10487
+ });
10488
+ registerDiscordListener(params.client.listeners, guildJoinListener);
10177
10489
  const reactionListenerOptions = {
10178
10490
  readPolicy: params.readPolicy,
10179
10491
  cfg: params.cfg,
@@ -10193,10 +10505,13 @@ function registerDiscordMonitorListeners(params) {
10193
10505
  };
10194
10506
  registerDiscordListener(params.client.listeners, new DiscordReactionListener(reactionListenerOptions));
10195
10507
  registerDiscordListener(params.client.listeners, new DiscordReactionRemoveListener(reactionListenerOptions));
10196
- registerDiscordListener(params.client.listeners, new DiscordThreadUpdateListener(params.cfg, params.logger));
10508
+ const threadUpdateListener = new DiscordThreadUpdateListener(params.cfg, params.logger);
10509
+ registerDiscordListener(params.client.listeners, threadUpdateListener);
10510
+ registerDiscordListener(params.client.listeners, new DiscordThreadReadyListener(threadUpdateListener));
10197
10511
  registerDiscordListener(params.client.listeners, new DiscordThreadDeleteListener(params.cfg, params.accountId, params.logger));
10512
+ let presenceListener;
10198
10513
  if (params.discordConfig.intents?.presence) {
10199
- const presenceListener = new DiscordPresenceListener({
10514
+ presenceListener = new DiscordPresenceListener({
10200
10515
  readPolicy: params.readPolicy,
10201
10516
  cfg: params.cfg,
10202
10517
  logger: params.logger,
@@ -10210,6 +10525,14 @@ function registerDiscordMonitorListeners(params) {
10210
10525
  registerDiscordListener(params.client.listeners, new DiscordPresenceReadyListener(presenceListener));
10211
10526
  params.runtime.log?.("discord: GuildPresences intent enabled — presence listener registered");
10212
10527
  }
10528
+ return async () => {
10529
+ const introductionsStopped = guildJoinListener.stop();
10530
+ try {
10531
+ await presenceListener?.stop();
10532
+ } finally {
10533
+ await introductionsStopped;
10534
+ }
10535
+ };
10213
10536
  }
10214
10537
  //#endregion
10215
10538
  //#region extensions/discord/src/monitor/startup-status.ts
@@ -10230,7 +10553,7 @@ function logDiscordStartupPhase(params) {
10230
10553
  const DISCORD_DISALLOWED_INTENTS_CODE = GatewayCloseCodes$1.DisallowedIntents;
10231
10554
  function isDiscordDisallowedIntentsError(err) {
10232
10555
  if (!err) return false;
10233
- return formatErrorMessage$1(err).includes(String(DISCORD_DISALLOWED_INTENTS_CODE));
10556
+ return formatErrorMessage(err).includes(String(DISCORD_DISALLOWED_INTENTS_CODE));
10234
10557
  }
10235
10558
  async function monitorDiscordProvider(opts = {}) {
10236
10559
  const startupStartedAt = Date.now();
@@ -10272,7 +10595,7 @@ async function monitorDiscordProvider(opts = {}) {
10272
10595
  let allowFrom = configuredDmAllowFrom ?? [];
10273
10596
  const mediaMaxBytes = (opts.mediaMaxMb ?? discordCfg.mediaMaxMb ?? DEFAULT_DISCORD_MEDIA_MAX_MB) * 1024 * 1024;
10274
10597
  const textLimit = resolveTextChunkLimit(cfg, "discord", account.accountId, { fallbackLimit: 2e3 });
10275
- const historyLimit = Math.max(0, opts.historyLimit ?? discordCfg.historyLimit ?? cfg.messages?.groupChat?.historyLimit ?? 20);
10598
+ const historyLimit = resolvePromptHistoryLimit(opts.historyLimit ?? discordCfg.historyLimit ?? cfg.messages?.groupChat?.historyLimit, 20);
10276
10599
  const replyToMode = opts.replyToMode ?? discordCfg.replyToMode ?? "off";
10277
10600
  const dmEnabled = dmConfig?.enabled ?? true;
10278
10601
  const dmPolicy = resolveDiscordAccountDmPolicy({
@@ -10309,6 +10632,7 @@ async function monitorDiscordProvider(opts = {}) {
10309
10632
  const sessionPrefix = "discord:slash";
10310
10633
  const ephemeralDefault = slashCommand.ephemeral;
10311
10634
  const voiceEnabled = resolveDiscordVoiceEnabled(discordCfg.voice);
10635
+ if (voiceEnabled && getDiscordEndpointRuntime()) throw new Error("Discord voice transport is unavailable while DISCORD_API_URL is configured");
10312
10636
  const allowlistResolved = await resolveDiscordAllowlistConfig({
10313
10637
  token,
10314
10638
  guildEntries,
@@ -10361,7 +10685,7 @@ async function monitorDiscordProvider(opts = {}) {
10361
10685
  if (applicationIdProbe.kind !== "resolved") {
10362
10686
  const at = Date.now();
10363
10687
  const terminal = applicationIdProbe.kind === "rejected";
10364
- const probeError = formatErrorMessage$1(applicationIdProbe.error);
10688
+ const probeError = formatErrorMessage(applicationIdProbe.error);
10365
10689
  const message = `Failed to resolve Discord application id: ${probeError}`;
10366
10690
  opts.setStatus?.({
10367
10691
  connected: false,
@@ -10395,43 +10719,46 @@ async function monitorDiscordProvider(opts = {}) {
10395
10719
  listNativeCommandSpecsForConfig: discordProviderRuntime.listNativeCommandSpecsForConfig
10396
10720
  });
10397
10721
  const voiceManagerRef = { current: null };
10398
- const threadBindings = threadBindingsEnabled ? discordProviderSessionRuntime.createThreadBindingManager({
10722
+ const threadBindings = threadBindingsEnabled ? await discordProviderSessionRuntime.createThreadBindingManager({
10399
10723
  accountId: account.accountId,
10400
10724
  token,
10401
10725
  cfg,
10402
10726
  idleTimeoutMs: threadBindingIdleTimeoutMs,
10403
10727
  maxAgeMs: threadBindingMaxAgeMs
10404
10728
  }) : discordProviderSessionRuntime.createNoopThreadBindingManager(account.accountId);
10405
- if (threadBindingsEnabled) {
10406
- const uncertainProbeKeys = /* @__PURE__ */ new Set();
10407
- const reconciliation = await discordProviderSessionRuntime.reconcileAcpThreadBindingsOnStartup({
10408
- cfg,
10409
- accountId: account.accountId,
10410
- sendFarewell: false,
10411
- healthProbe: async ({ sessionKey, session }) => {
10412
- const probe = await probeDiscordAcpBindingHealth({
10413
- cfg,
10414
- sessionKey,
10415
- agentId: session.agentId,
10416
- storedState: session.acp?.state,
10417
- lastActivityAt: session.acp?.lastActivityAt,
10418
- providerSessionRuntime: discordProviderSessionRuntime
10419
- });
10420
- if (probe.status === "uncertain") uncertainProbeKeys.add(`${sessionKey}${probe.reason ? ` (${probe.reason})` : ""}`);
10421
- return probe;
10422
- }
10423
- });
10424
- if (reconciliation.removed > 0) logVerbose(`discord: removed ${reconciliation.removed}/${reconciliation.checked} stale ACP thread bindings on startup for account ${account.accountId}: ${reconciliation.staleSessionKeys.join(", ")}`);
10425
- if (uncertainProbeKeys.size > 0) logVerbose(`discord: ACP thread-binding health probe uncertain for account ${account.accountId}: ${[...uncertainProbeKeys].join(", ")}`);
10426
- }
10427
10729
  let lifecycleStarted = false;
10428
10730
  let gatewaySupervisor;
10429
10731
  let deactivateMessageHandler;
10732
+ let stopMonitorListeners;
10430
10733
  let autoPresenceController = null;
10431
10734
  let lifecycleGateway;
10432
10735
  let earlyGatewayEmitter = gatewaySupervisor?.emitter;
10433
10736
  let onEarlyGatewayDebug;
10434
10737
  try {
10738
+ if (opts.abortSignal?.aborted) return;
10739
+ if (threadBindingsEnabled) {
10740
+ const uncertainProbeKeys = /* @__PURE__ */ new Set();
10741
+ const reconciliation = await discordProviderSessionRuntime.reconcileAcpThreadBindingsOnStartup({
10742
+ cfg,
10743
+ accountId: account.accountId,
10744
+ sendFarewell: false,
10745
+ healthProbe: async ({ sessionKey, session }) => {
10746
+ const probe = await probeDiscordAcpBindingHealth({
10747
+ cfg,
10748
+ sessionKey,
10749
+ agentId: session.agentId,
10750
+ storedState: session.acp?.state,
10751
+ lastActivityAt: session.acp?.lastActivityAt,
10752
+ providerSessionRuntime: discordProviderSessionRuntime
10753
+ });
10754
+ if (probe.status === "uncertain") uncertainProbeKeys.add(`${sessionKey}${probe.reason ? ` (${probe.reason})` : ""}`);
10755
+ return probe;
10756
+ }
10757
+ });
10758
+ if (reconciliation.removed > 0) logVerbose(`discord: removed ${reconciliation.removed}/${reconciliation.checked} stale ACP thread bindings on startup for account ${account.accountId}: ${reconciliation.staleSessionKeys.join(", ")}`);
10759
+ if (uncertainProbeKeys.size > 0) logVerbose(`discord: ACP thread-binding health probe uncertain for account ${account.accountId}: ${[...uncertainProbeKeys].join(", ")}`);
10760
+ }
10761
+ if (opts.abortSignal?.aborted) return;
10435
10762
  const pluginChannelRuntime = opts.channelRuntime;
10436
10763
  const { commands, components, modals } = createDiscordProviderInteractionSurface({
10437
10764
  readPolicy,
@@ -10572,7 +10899,7 @@ async function monitorDiscordProvider(opts = {}) {
10572
10899
  lastInboundAt: at
10573
10900
  });
10574
10901
  } : void 0;
10575
- registerDiscordMonitorListeners({
10902
+ stopMonitorListeners = registerDiscordMonitorListeners({
10576
10903
  readPolicy,
10577
10904
  cfg,
10578
10905
  client,
@@ -10622,6 +10949,7 @@ async function monitorDiscordProvider(opts = {}) {
10622
10949
  } finally {
10623
10950
  await cleanupDiscordProviderStartup({
10624
10951
  deactivateMessageHandler,
10952
+ stopMonitorListeners,
10625
10953
  autoPresenceController,
10626
10954
  setStatus: opts.setStatus,
10627
10955
  onEarlyGatewayDebug,