@openclaw/imessage 2026.9.5 → 2026.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (436) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{accounts-Dv0uksBG.mjs → accounts-nzcU0cq2.mjs} +4 -7
  3. package/dist/.setup/{actions.runtime-B-qGAkYG.mjs → actions.runtime-DdBN29zj.mjs} +3 -5
  4. package/dist/.setup/{api-_NoJAo2x.mjs → api-B9Qx21G-.mjs} +6 -5
  5. package/dist/.setup/{api-DcUWvBmD.mjs → api-D2S6FhGw.mjs} +7 -7
  6. package/dist/.setup/{approval-handler.runtime-CkG235P7.mjs → approval-handler.runtime-DKSq0DWq.mjs} +9 -9
  7. package/dist/.setup/{approval-reactions-CX1-6KeG.mjs → approval-reactions-Bp33xc83.mjs} +5 -5
  8. package/dist/.setup/{channel-CCbYCQiN.mjs → channel-9fyvuN_p.mjs} +110 -152
  9. package/dist/.setup/channel.runtime-n-MPKL8k.mjs +92 -0
  10. package/dist/.setup/{config-schema-CCbTcJEV.mjs → config-schema-4Q3_EqYt.mjs} +9 -1
  11. package/dist/.setup/{group-policy-BoOAkmoQ.mjs → group-policy-90pw4tyG.mjs} +65 -335
  12. package/dist/.setup/{media-contract-BpPh5Oh1.mjs → media-contract-CagwSMvo.mjs} +1 -1
  13. package/dist/.setup/{message-tool-api-DZSH-2gY.mjs → message-tool-api-D032l82H.mjs} +3 -18
  14. package/dist/.setup/{monitor-CSeWJ3Qh.mjs → monitor-fv9nRuTH.mjs} +235 -344
  15. package/dist/.setup/{question-reactions-lm8OxWbb.mjs → question-reactions-Cy-dmU_j.mjs} +1 -1
  16. package/dist/.setup/{remote-file-4RbwiXYh.mjs → remote-file-DRPCaVmg.mjs} +70 -21
  17. package/dist/.setup/rolldown-runtime-BBjsoOtd.mjs +27 -0
  18. package/dist/.setup/{sanitize-outbound-o1ePXajW.mjs → sanitize-outbound-3MLljgtY.mjs} +86 -24
  19. package/dist/.setup/{send-DXiUWygv.mjs → send-Cu9nl757.mjs} +29 -94
  20. package/dist/.setup/setup-core-8MDdYHj5.mjs +226 -0
  21. package/dist/.setup/{channel.runtime-Kw4iCQax.mjs → setup-surface-tGXFDdWh.mjs} +6 -103
  22. package/dist/.setup/state-migrations-B-Q7bO0Y.mjs +47 -0
  23. package/dist/.setup/{targets-Cc9vthzI.mjs → targets-BicBiYsM.mjs} +10 -16
  24. package/dist/api.js +7 -7
  25. package/dist/channel-config-api.js +1 -1
  26. package/dist/channel-plugin-api.js +1 -1
  27. package/dist/contract-api.js +1 -1
  28. package/dist/doctor-contract-api.js +168 -7
  29. package/dist/media-contract-api.js +1 -1
  30. package/dist/message-tool-api.js +1 -1
  31. package/dist/runtime-api.js +6 -6
  32. package/dist/setup-entry.js +1 -1
  33. package/dist/src/{send-receipt-db.worker.js → chat-db.worker.js} +12 -2
  34. package/node_modules/typebox/build/compile/code.mjs +1 -2
  35. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  36. package/node_modules/typebox/build/format/iri.mjs +16 -9
  37. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  38. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  39. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  40. package/node_modules/typebox/build/guard/index.mjs +6 -0
  41. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  42. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  43. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  44. package/node_modules/typebox/build/schema/build.mjs +2 -3
  45. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  46. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  47. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  48. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  49. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  50. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  51. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  52. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  53. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  54. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  55. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  56. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  57. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  58. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  59. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  60. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  61. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  62. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  63. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  64. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  65. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  66. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  67. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  68. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  69. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  70. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  71. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  72. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  73. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  74. package/node_modules/typebox/package.json +1 -1
  75. package/node_modules/typebox/readme.md +3 -1
  76. package/node_modules/zod/README.md +2 -2
  77. package/node_modules/zod/compile.cjs +19 -0
  78. package/node_modules/zod/index.cjs +19 -0
  79. package/node_modules/zod/locales/index.cjs +19 -0
  80. package/node_modules/zod/mini/index.cjs +19 -0
  81. package/node_modules/zod/package.json +8 -7
  82. package/node_modules/zod/src/v3/helpers/errorUtil.ts +1 -1
  83. package/node_modules/zod/src/v4/classic/external.ts +2 -0
  84. package/node_modules/zod/src/v4/classic/from-json-schema.ts +248 -25
  85. package/node_modules/zod/src/v4/classic/schemas.ts +243 -168
  86. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +60 -9
  87. package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +6 -0
  88. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +2 -2
  89. package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +265 -0
  90. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +112 -6
  91. package/node_modules/zod/src/v4/classic/tests/enum.test.ts +9 -0
  92. package/node_modules/zod/src/v4/classic/tests/error.test.ts +130 -1
  93. package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +157 -0
  94. package/node_modules/zod/src/v4/classic/tests/iban.test.ts +81 -0
  95. package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +40 -2
  96. package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +27 -7
  97. package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +88 -56
  98. package/node_modules/zod/src/v4/classic/tests/number.test.ts +39 -0
  99. package/node_modules/zod/src/v4/classic/tests/object.test.ts +56 -0
  100. package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +3 -2
  101. package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +70 -0
  102. package/node_modules/zod/src/v4/classic/tests/properties.test.ts +141 -0
  103. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +46 -1
  104. package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +19 -0
  105. package/node_modules/zod/src/v4/classic/tests/string.test.ts +95 -1
  106. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +33 -1
  107. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +234 -38
  108. package/node_modules/zod/src/v4/classic/tests/validate.test.ts +569 -0
  109. package/node_modules/zod/src/v4/core/api.ts +44 -28
  110. package/node_modules/zod/src/v4/core/checks.ts +62 -102
  111. package/node_modules/zod/src/v4/core/compile.ts +218 -93
  112. package/node_modules/zod/src/v4/core/core.ts +1 -3
  113. package/node_modules/zod/src/v4/core/doc.ts +6 -2
  114. package/node_modules/zod/src/v4/core/errors.ts +3 -6
  115. package/node_modules/zod/src/v4/core/json-schema-generator.ts +2 -2
  116. package/node_modules/zod/src/v4/core/json-schema-processors.ts +185 -81
  117. package/node_modules/zod/src/v4/core/memoizer.ts +75 -28
  118. package/node_modules/zod/src/v4/core/parse.ts +37 -16
  119. package/node_modules/zod/src/v4/core/regexes.ts +14 -4
  120. package/node_modules/zod/src/v4/core/schemas.ts +296 -132
  121. package/node_modules/zod/src/v4/core/tests/cached.test.ts +54 -0
  122. package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +35 -0
  123. package/node_modules/zod/src/v4/core/tests/compile-generative.test.ts +445 -0
  124. package/node_modules/zod/src/v4/core/tests/compile.test.ts +399 -2
  125. package/node_modules/zod/src/v4/core/tests/email-regex.test.ts +140 -0
  126. package/node_modules/zod/src/v4/core/tests/locales/tg.test.ts +85 -0
  127. package/node_modules/zod/src/v4/core/tests/polyfill-collision.test.ts +46 -0
  128. package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +118 -16
  129. package/node_modules/zod/src/v4/core/to-json-schema.ts +9 -7
  130. package/node_modules/zod/src/v4/core/util.ts +218 -147
  131. package/node_modules/zod/src/v4/core/versions.ts +2 -2
  132. package/node_modules/zod/src/v4/locales/ar.ts +2 -0
  133. package/node_modules/zod/src/v4/locales/az.ts +2 -0
  134. package/node_modules/zod/src/v4/locales/be.ts +2 -0
  135. package/node_modules/zod/src/v4/locales/bg.ts +2 -0
  136. package/node_modules/zod/src/v4/locales/bn.ts +2 -0
  137. package/node_modules/zod/src/v4/locales/ca.ts +2 -0
  138. package/node_modules/zod/src/v4/locales/ckb.ts +2 -0
  139. package/node_modules/zod/src/v4/locales/cs.ts +2 -0
  140. package/node_modules/zod/src/v4/locales/da.ts +2 -0
  141. package/node_modules/zod/src/v4/locales/de.ts +2 -0
  142. package/node_modules/zod/src/v4/locales/el.ts +2 -0
  143. package/node_modules/zod/src/v4/locales/en.ts +2 -0
  144. package/node_modules/zod/src/v4/locales/eo.ts +2 -0
  145. package/node_modules/zod/src/v4/locales/es.ts +2 -0
  146. package/node_modules/zod/src/v4/locales/fa.ts +2 -0
  147. package/node_modules/zod/src/v4/locales/fi.ts +2 -0
  148. package/node_modules/zod/src/v4/locales/fr-CA.ts +2 -0
  149. package/node_modules/zod/src/v4/locales/fr.ts +2 -0
  150. package/node_modules/zod/src/v4/locales/gu.ts +2 -0
  151. package/node_modules/zod/src/v4/locales/he.ts +2 -0
  152. package/node_modules/zod/src/v4/locales/hi.ts +2 -0
  153. package/node_modules/zod/src/v4/locales/hr.ts +2 -0
  154. package/node_modules/zod/src/v4/locales/hu.ts +2 -0
  155. package/node_modules/zod/src/v4/locales/hy.ts +2 -0
  156. package/node_modules/zod/src/v4/locales/id.ts +2 -0
  157. package/node_modules/zod/src/v4/locales/index.ts +1 -0
  158. package/node_modules/zod/src/v4/locales/is.ts +2 -0
  159. package/node_modules/zod/src/v4/locales/it.ts +2 -0
  160. package/node_modules/zod/src/v4/locales/ja.ts +2 -0
  161. package/node_modules/zod/src/v4/locales/ka.ts +2 -0
  162. package/node_modules/zod/src/v4/locales/km.ts +2 -0
  163. package/node_modules/zod/src/v4/locales/kn.ts +2 -0
  164. package/node_modules/zod/src/v4/locales/ko.ts +2 -0
  165. package/node_modules/zod/src/v4/locales/lt.ts +2 -0
  166. package/node_modules/zod/src/v4/locales/mk.ts +2 -0
  167. package/node_modules/zod/src/v4/locales/ms.ts +2 -0
  168. package/node_modules/zod/src/v4/locales/ne.ts +2 -0
  169. package/node_modules/zod/src/v4/locales/nl.ts +2 -0
  170. package/node_modules/zod/src/v4/locales/nn.ts +2 -0
  171. package/node_modules/zod/src/v4/locales/no.ts +2 -0
  172. package/node_modules/zod/src/v4/locales/ota.ts +2 -0
  173. package/node_modules/zod/src/v4/locales/pl.ts +2 -0
  174. package/node_modules/zod/src/v4/locales/ps.ts +2 -0
  175. package/node_modules/zod/src/v4/locales/pt-BR.ts +2 -0
  176. package/node_modules/zod/src/v4/locales/pt.ts +2 -0
  177. package/node_modules/zod/src/v4/locales/ro.ts +2 -0
  178. package/node_modules/zod/src/v4/locales/ru.ts +2 -0
  179. package/node_modules/zod/src/v4/locales/sk.ts +2 -0
  180. package/node_modules/zod/src/v4/locales/sl.ts +2 -0
  181. package/node_modules/zod/src/v4/locales/sv.ts +2 -0
  182. package/node_modules/zod/src/v4/locales/ta.ts +2 -0
  183. package/node_modules/zod/src/v4/locales/tg.ts +135 -0
  184. package/node_modules/zod/src/v4/locales/th.ts +2 -0
  185. package/node_modules/zod/src/v4/locales/tk.ts +2 -0
  186. package/node_modules/zod/src/v4/locales/tr.ts +2 -0
  187. package/node_modules/zod/src/v4/locales/uk.ts +2 -0
  188. package/node_modules/zod/src/v4/locales/ur.ts +2 -0
  189. package/node_modules/zod/src/v4/locales/uz.ts +2 -0
  190. package/node_modules/zod/src/v4/locales/vi.ts +2 -0
  191. package/node_modules/zod/src/v4/locales/yo.ts +2 -0
  192. package/node_modules/zod/src/v4/locales/zh-CN.ts +2 -0
  193. package/node_modules/zod/src/v4/locales/zh-TW.ts +2 -0
  194. package/node_modules/zod/src/v4/mini/external.ts +2 -0
  195. package/node_modules/zod/src/v4/mini/schemas.ts +32 -7
  196. package/node_modules/zod/src/v4/mini/tests/checks.test.ts +1 -1
  197. package/node_modules/zod/src/v4/mini/tests/computed.test.ts +11 -17
  198. package/node_modules/zod/src/v4/mini/tests/index.test.ts +86 -0
  199. package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +16 -0
  200. package/node_modules/zod/src/v4/mini/tests/string.test.ts +23 -0
  201. package/node_modules/zod/v3/ZodError.cjs +19 -0
  202. package/node_modules/zod/v3/errors.cjs +19 -0
  203. package/node_modules/zod/v3/external.cjs +19 -0
  204. package/node_modules/zod/v3/helpers/enumUtil.cjs +19 -0
  205. package/node_modules/zod/v3/helpers/errorUtil.cjs +20 -1
  206. package/node_modules/zod/v3/helpers/errorUtil.js +1 -1
  207. package/node_modules/zod/v3/helpers/parseUtil.cjs +19 -0
  208. package/node_modules/zod/v3/helpers/partialUtil.cjs +19 -0
  209. package/node_modules/zod/v3/helpers/typeAliases.cjs +19 -0
  210. package/node_modules/zod/v3/helpers/util.cjs +19 -0
  211. package/node_modules/zod/v3/index.cjs +19 -0
  212. package/node_modules/zod/v3/standard-schema.cjs +19 -0
  213. package/node_modules/zod/v3/types.cjs +19 -0
  214. package/node_modules/zod/v4/classic/checks.cjs +19 -0
  215. package/node_modules/zod/v4/classic/coerce.cjs +19 -0
  216. package/node_modules/zod/v4/classic/compat.cjs +19 -0
  217. package/node_modules/zod/v4/classic/deep-partial.cjs +19 -0
  218. package/node_modules/zod/v4/classic/errors.cjs +19 -0
  219. package/node_modules/zod/v4/classic/external.cjs +22 -1
  220. package/node_modules/zod/v4/classic/external.d.cts +1 -1
  221. package/node_modules/zod/v4/classic/external.d.ts +1 -1
  222. package/node_modules/zod/v4/classic/external.js +1 -1
  223. package/node_modules/zod/v4/classic/from-json-schema.cjs +264 -24
  224. package/node_modules/zod/v4/classic/from-json-schema.js +245 -24
  225. package/node_modules/zod/v4/classic/in-out.cjs +19 -0
  226. package/node_modules/zod/v4/classic/index.cjs +19 -0
  227. package/node_modules/zod/v4/classic/iso.cjs +19 -0
  228. package/node_modules/zod/v4/classic/parse.cjs +19 -0
  229. package/node_modules/zod/v4/classic/schemas.cjs +100 -35
  230. package/node_modules/zod/v4/classic/schemas.d.cts +15 -1
  231. package/node_modules/zod/v4/classic/schemas.d.ts +15 -1
  232. package/node_modules/zod/v4/classic/schemas.js +77 -33
  233. package/node_modules/zod/v4/core/api.cjs +45 -22
  234. package/node_modules/zod/v4/core/api.d.cts +12 -6
  235. package/node_modules/zod/v4/core/api.d.ts +12 -6
  236. package/node_modules/zod/v4/core/api.js +25 -22
  237. package/node_modules/zod/v4/core/checks.cjs +51 -97
  238. package/node_modules/zod/v4/core/checks.d.cts +17 -1
  239. package/node_modules/zod/v4/core/checks.d.ts +17 -1
  240. package/node_modules/zod/v4/core/checks.js +31 -96
  241. package/node_modules/zod/v4/core/compile.cjs +173 -78
  242. package/node_modules/zod/v4/core/compile.d.cts +18 -4
  243. package/node_modules/zod/v4/core/compile.d.ts +18 -4
  244. package/node_modules/zod/v4/core/compile.js +154 -79
  245. package/node_modules/zod/v4/core/core.cjs +20 -1
  246. package/node_modules/zod/v4/core/core.js +1 -1
  247. package/node_modules/zod/v4/core/doc.cjs +26 -2
  248. package/node_modules/zod/v4/core/doc.js +7 -2
  249. package/node_modules/zod/v4/core/errors.cjs +21 -5
  250. package/node_modules/zod/v4/core/errors.js +2 -5
  251. package/node_modules/zod/v4/core/index.cjs +19 -0
  252. package/node_modules/zod/v4/core/json-schema-generator.cjs +20 -1
  253. package/node_modules/zod/v4/core/json-schema-generator.js +2 -2
  254. package/node_modules/zod/v4/core/json-schema-processors.cjs +188 -72
  255. package/node_modules/zod/v4/core/json-schema-processors.d.cts +16 -0
  256. package/node_modules/zod/v4/core/json-schema-processors.d.ts +16 -0
  257. package/node_modules/zod/v4/core/json-schema-processors.js +170 -74
  258. package/node_modules/zod/v4/core/json-schema.cjs +19 -0
  259. package/node_modules/zod/v4/core/memoizer.cjs +111 -23
  260. package/node_modules/zod/v4/core/memoizer.js +69 -23
  261. package/node_modules/zod/v4/core/parse.cjs +56 -16
  262. package/node_modules/zod/v4/core/parse.js +37 -16
  263. package/node_modules/zod/v4/core/regexes.cjs +31 -6
  264. package/node_modules/zod/v4/core/regexes.d.cts +3 -0
  265. package/node_modules/zod/v4/core/regexes.d.ts +3 -0
  266. package/node_modules/zod/v4/core/regexes.js +10 -4
  267. package/node_modules/zod/v4/core/registries.cjs +19 -0
  268. package/node_modules/zod/v4/core/schemas.cjs +302 -114
  269. package/node_modules/zod/v4/core/schemas.d.cts +28 -8
  270. package/node_modules/zod/v4/core/schemas.d.ts +28 -8
  271. package/node_modules/zod/v4/core/schemas.js +279 -113
  272. package/node_modules/zod/v4/core/standard-schema.cjs +19 -0
  273. package/node_modules/zod/v4/core/to-json-schema.cjs +28 -7
  274. package/node_modules/zod/v4/core/to-json-schema.d.cts +4 -3
  275. package/node_modules/zod/v4/core/to-json-schema.d.ts +4 -3
  276. package/node_modules/zod/v4/core/to-json-schema.js +7 -6
  277. package/node_modules/zod/v4/core/util.cjs +177 -143
  278. package/node_modules/zod/v4/core/util.d.cts +25 -4
  279. package/node_modules/zod/v4/core/util.d.ts +25 -4
  280. package/node_modules/zod/v4/core/util.js +156 -143
  281. package/node_modules/zod/v4/core/versions.cjs +21 -2
  282. package/node_modules/zod/v4/core/versions.d.cts +1 -1
  283. package/node_modules/zod/v4/core/versions.d.ts +1 -1
  284. package/node_modules/zod/v4/core/versions.js +2 -2
  285. package/node_modules/zod/v4/core/visit.cjs +19 -0
  286. package/node_modules/zod/v4/index.cjs +19 -0
  287. package/node_modules/zod/v4/locales/ar.cjs +2 -0
  288. package/node_modules/zod/v4/locales/ar.js +2 -0
  289. package/node_modules/zod/v4/locales/az.cjs +2 -0
  290. package/node_modules/zod/v4/locales/az.js +2 -0
  291. package/node_modules/zod/v4/locales/be.cjs +2 -0
  292. package/node_modules/zod/v4/locales/be.js +2 -0
  293. package/node_modules/zod/v4/locales/bg.cjs +2 -0
  294. package/node_modules/zod/v4/locales/bg.js +2 -0
  295. package/node_modules/zod/v4/locales/bn.cjs +2 -0
  296. package/node_modules/zod/v4/locales/bn.js +2 -0
  297. package/node_modules/zod/v4/locales/ca.cjs +2 -0
  298. package/node_modules/zod/v4/locales/ca.js +2 -0
  299. package/node_modules/zod/v4/locales/ckb.cjs +2 -0
  300. package/node_modules/zod/v4/locales/ckb.js +2 -0
  301. package/node_modules/zod/v4/locales/cs.cjs +2 -0
  302. package/node_modules/zod/v4/locales/cs.js +2 -0
  303. package/node_modules/zod/v4/locales/da.cjs +2 -0
  304. package/node_modules/zod/v4/locales/da.js +2 -0
  305. package/node_modules/zod/v4/locales/de.cjs +2 -0
  306. package/node_modules/zod/v4/locales/de.js +2 -0
  307. package/node_modules/zod/v4/locales/el.cjs +2 -0
  308. package/node_modules/zod/v4/locales/el.js +2 -0
  309. package/node_modules/zod/v4/locales/en.cjs +2 -0
  310. package/node_modules/zod/v4/locales/en.js +2 -0
  311. package/node_modules/zod/v4/locales/eo.cjs +2 -0
  312. package/node_modules/zod/v4/locales/eo.js +2 -0
  313. package/node_modules/zod/v4/locales/es.cjs +2 -0
  314. package/node_modules/zod/v4/locales/es.js +2 -0
  315. package/node_modules/zod/v4/locales/fa.cjs +2 -0
  316. package/node_modules/zod/v4/locales/fa.js +2 -0
  317. package/node_modules/zod/v4/locales/fi.cjs +2 -0
  318. package/node_modules/zod/v4/locales/fi.js +2 -0
  319. package/node_modules/zod/v4/locales/fr-CA.cjs +2 -0
  320. package/node_modules/zod/v4/locales/fr-CA.js +2 -0
  321. package/node_modules/zod/v4/locales/fr.cjs +2 -0
  322. package/node_modules/zod/v4/locales/fr.js +2 -0
  323. package/node_modules/zod/v4/locales/gu.cjs +2 -0
  324. package/node_modules/zod/v4/locales/gu.js +2 -0
  325. package/node_modules/zod/v4/locales/he.cjs +2 -0
  326. package/node_modules/zod/v4/locales/he.js +2 -0
  327. package/node_modules/zod/v4/locales/hi.cjs +2 -0
  328. package/node_modules/zod/v4/locales/hi.js +2 -0
  329. package/node_modules/zod/v4/locales/hr.cjs +2 -0
  330. package/node_modules/zod/v4/locales/hr.js +2 -0
  331. package/node_modules/zod/v4/locales/hu.cjs +2 -0
  332. package/node_modules/zod/v4/locales/hu.js +2 -0
  333. package/node_modules/zod/v4/locales/hy.cjs +2 -0
  334. package/node_modules/zod/v4/locales/hy.js +2 -0
  335. package/node_modules/zod/v4/locales/id.cjs +2 -0
  336. package/node_modules/zod/v4/locales/id.js +2 -0
  337. package/node_modules/zod/v4/locales/index.cjs +22 -1
  338. package/node_modules/zod/v4/locales/index.d.cts +1 -0
  339. package/node_modules/zod/v4/locales/index.d.ts +1 -0
  340. package/node_modules/zod/v4/locales/index.js +1 -0
  341. package/node_modules/zod/v4/locales/is.cjs +2 -0
  342. package/node_modules/zod/v4/locales/is.js +2 -0
  343. package/node_modules/zod/v4/locales/it.cjs +2 -0
  344. package/node_modules/zod/v4/locales/it.js +2 -0
  345. package/node_modules/zod/v4/locales/ja.cjs +2 -0
  346. package/node_modules/zod/v4/locales/ja.js +2 -0
  347. package/node_modules/zod/v4/locales/ka.cjs +2 -0
  348. package/node_modules/zod/v4/locales/ka.js +2 -0
  349. package/node_modules/zod/v4/locales/km.cjs +2 -0
  350. package/node_modules/zod/v4/locales/km.js +2 -0
  351. package/node_modules/zod/v4/locales/kn.cjs +2 -0
  352. package/node_modules/zod/v4/locales/kn.js +2 -0
  353. package/node_modules/zod/v4/locales/ko.cjs +2 -0
  354. package/node_modules/zod/v4/locales/ko.js +2 -0
  355. package/node_modules/zod/v4/locales/lt.cjs +2 -0
  356. package/node_modules/zod/v4/locales/lt.js +2 -0
  357. package/node_modules/zod/v4/locales/mk.cjs +2 -0
  358. package/node_modules/zod/v4/locales/mk.js +2 -0
  359. package/node_modules/zod/v4/locales/ms.cjs +2 -0
  360. package/node_modules/zod/v4/locales/ms.js +2 -0
  361. package/node_modules/zod/v4/locales/ne.cjs +2 -0
  362. package/node_modules/zod/v4/locales/ne.js +2 -0
  363. package/node_modules/zod/v4/locales/nl.cjs +2 -0
  364. package/node_modules/zod/v4/locales/nl.js +2 -0
  365. package/node_modules/zod/v4/locales/nn.cjs +2 -0
  366. package/node_modules/zod/v4/locales/nn.js +2 -0
  367. package/node_modules/zod/v4/locales/no.cjs +2 -0
  368. package/node_modules/zod/v4/locales/no.js +2 -0
  369. package/node_modules/zod/v4/locales/ota.cjs +2 -0
  370. package/node_modules/zod/v4/locales/ota.js +2 -0
  371. package/node_modules/zod/v4/locales/pl.cjs +2 -0
  372. package/node_modules/zod/v4/locales/pl.js +2 -0
  373. package/node_modules/zod/v4/locales/ps.cjs +2 -0
  374. package/node_modules/zod/v4/locales/ps.js +2 -0
  375. package/node_modules/zod/v4/locales/pt-BR.cjs +2 -0
  376. package/node_modules/zod/v4/locales/pt-BR.js +2 -0
  377. package/node_modules/zod/v4/locales/pt.cjs +2 -0
  378. package/node_modules/zod/v4/locales/pt.js +2 -0
  379. package/node_modules/zod/v4/locales/ro.cjs +2 -0
  380. package/node_modules/zod/v4/locales/ro.js +2 -0
  381. package/node_modules/zod/v4/locales/ru.cjs +2 -0
  382. package/node_modules/zod/v4/locales/ru.js +2 -0
  383. package/node_modules/zod/v4/locales/sk.cjs +2 -0
  384. package/node_modules/zod/v4/locales/sk.js +2 -0
  385. package/node_modules/zod/v4/locales/sl.cjs +2 -0
  386. package/node_modules/zod/v4/locales/sl.js +2 -0
  387. package/node_modules/zod/v4/locales/sv.cjs +2 -0
  388. package/node_modules/zod/v4/locales/sv.js +2 -0
  389. package/node_modules/zod/v4/locales/ta.cjs +2 -0
  390. package/node_modules/zod/v4/locales/ta.js +2 -0
  391. package/node_modules/zod/v4/locales/tg.cjs +144 -0
  392. package/node_modules/zod/v4/locales/tg.d.cts +5 -0
  393. package/node_modules/zod/v4/locales/tg.d.ts +4 -0
  394. package/node_modules/zod/v4/locales/tg.js +117 -0
  395. package/node_modules/zod/v4/locales/th.cjs +2 -0
  396. package/node_modules/zod/v4/locales/th.js +2 -0
  397. package/node_modules/zod/v4/locales/tk.cjs +2 -0
  398. package/node_modules/zod/v4/locales/tk.js +2 -0
  399. package/node_modules/zod/v4/locales/tr.cjs +2 -0
  400. package/node_modules/zod/v4/locales/tr.js +2 -0
  401. package/node_modules/zod/v4/locales/uk.cjs +2 -0
  402. package/node_modules/zod/v4/locales/uk.js +2 -0
  403. package/node_modules/zod/v4/locales/ur.cjs +2 -0
  404. package/node_modules/zod/v4/locales/ur.js +2 -0
  405. package/node_modules/zod/v4/locales/uz.cjs +2 -0
  406. package/node_modules/zod/v4/locales/uz.js +2 -0
  407. package/node_modules/zod/v4/locales/vi.cjs +2 -0
  408. package/node_modules/zod/v4/locales/vi.js +2 -0
  409. package/node_modules/zod/v4/locales/yo.cjs +2 -0
  410. package/node_modules/zod/v4/locales/yo.js +2 -0
  411. package/node_modules/zod/v4/locales/zh-CN.cjs +2 -0
  412. package/node_modules/zod/v4/locales/zh-CN.js +2 -0
  413. package/node_modules/zod/v4/locales/zh-TW.cjs +2 -0
  414. package/node_modules/zod/v4/locales/zh-TW.js +2 -0
  415. package/node_modules/zod/v4/mini/checks.cjs +19 -0
  416. package/node_modules/zod/v4/mini/coerce.cjs +19 -0
  417. package/node_modules/zod/v4/mini/deep-partial.cjs +19 -0
  418. package/node_modules/zod/v4/mini/external.cjs +22 -1
  419. package/node_modules/zod/v4/mini/external.d.cts +1 -1
  420. package/node_modules/zod/v4/mini/external.d.ts +1 -1
  421. package/node_modules/zod/v4/mini/external.js +1 -1
  422. package/node_modules/zod/v4/mini/in-out.cjs +19 -0
  423. package/node_modules/zod/v4/mini/index.cjs +19 -0
  424. package/node_modules/zod/v4/mini/iso.cjs +19 -0
  425. package/node_modules/zod/v4/mini/parse.cjs +19 -0
  426. package/node_modules/zod/v4/mini/schemas.cjs +44 -8
  427. package/node_modules/zod/v4/mini/schemas.d.cts +6 -1
  428. package/node_modules/zod/v4/mini/schemas.d.ts +6 -1
  429. package/node_modules/zod/v4/mini/schemas.js +21 -6
  430. package/node_modules/zod/v4-mini/index.cjs +19 -0
  431. package/openclaw.plugin.json +14 -0
  432. package/package.json +7 -7
  433. package/dist/.setup/rolldown-runtime-D7D4PA-g.mjs +0 -13
  434. package/dist/.setup/state-contract-DvahEY4X.mjs +0 -56
  435. package/dist/.setup/state-migrations-CIwg07l5.mjs +0 -277
  436. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
@@ -1,15 +1,15 @@
1
- import { c as parseIMessageTarget, o as normalizeIMessageHandle, r as isAllowedIMessageReplyContextSender, s as parseIMessageAllowTarget, t as formatIMessageChatTarget } from "./targets-Cc9vthzI.mjs";
2
- import { d as resolveIMessageChatDbLookupPath, f as resolveIMessageHomeDir, l as resolveIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-Dv0uksBG.mjs";
3
- import { r as imessageRpcSupportsMethod } from "./message-tool-api-DZSH-2gY.mjs";
4
- import { b as resolveIMessageDirectChatService, d as isKnownFromMeIMessageMessageId, f as rememberIMessageReplyCache, o as createIMessageRpcClient, r as sanitizeOutboundText } from "./sanitize-outbound-o1ePXajW.mjs";
5
- import { d as probeIMessagePrivateApi, r as resolveIMessageInboundConversationId, u as probeIMessage } from "./group-policy-BoOAkmoQ.mjs";
1
+ import { c as parseIMessageTarget, o as normalizeIMessageHandle, r as isAllowedIMessageReplyContextSender, s as parseIMessageAllowTarget, t as formatIMessageChatTarget } from "./targets-BicBiYsM.mjs";
2
+ import { d as resolveIMessageChatDbLookupPath, f as resolveIMessageHomeDir, l as resolveIMessageRemoteHost, o as resolveIMessageAccount } from "./accounts-nzcU0cq2.mjs";
3
+ import { r as imessageRpcSupportsMethod } from "./message-tool-api-D032l82H.mjs";
4
+ import { D as resolveIMessageDirectChatService, b as resolveIMessageEchoMediaKey, d as isKnownFromMeIMessageTarget, f as rememberIMessageReplyCache, h as IMESSAGE_CATCHUP_CURSOR_NAMESPACE, o as createIMessageRpcClient, r as sanitizeOutboundText, v as capFailureRetriesMap, y as resolveIMessageCatchupCursorKey } from "./sanitize-outbound-3MLljgtY.mjs";
5
+ import { d as probeIMessage, f as probeIMessagePrivateApi, i as resolveIMessageInboundConversationId, n as resolveIMessageGroupSystemPrompt } from "./group-policy-90pw4tyG.mjs";
6
6
  import { t as getIMessageRuntime } from "./runtime-Cza4CY5T.mjs";
7
- import { d as resolveIMessageEchoMediaKey, l as capFailureRetriesMap, t as IMESSAGE_CATCHUP_CURSOR_NAMESPACE, u as resolveIMessageCatchupCursorKey } from "./state-contract-DvahEY4X.mjs";
8
- import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-BpPh5Oh1.mjs";
9
- import { i as registerIMessageApprovalReactionTarget, n as handleIMessageApprovalReaction, o as listPendingIMessageApprovalReactionPollTargets, r as maybeResolveIMessageApprovalReaction, s as buildIMessageApprovalConversationKeyForInbound } from "./approval-reactions-CX1-6KeG.mjs";
10
- import { c as iMessageApprovalControlBindings, n as hasPersistedIMessageEcho, r as stripLeadingEchoTextCorruptionMarkers, s as maybeResolveIMessageApprovalPollVote, t as sendMessageIMessage } from "./send-DXiUWygv.mjs";
7
+ import { n as resolveIMessageAttachmentRoots, r as resolveIMessageRemoteAttachmentRoots } from "./media-contract-CagwSMvo.mjs";
8
+ import { i as registerIMessageApprovalReactionTarget, n as handleIMessageApprovalReaction, o as listPendingIMessageApprovalReactionPollTargets, r as maybeResolveIMessageApprovalReaction, s as buildIMessageApprovalConversationKeyForInbound } from "./approval-reactions-Bp33xc83.mjs";
9
+ import { c as iMessageApprovalControlBindings, n as hasPersistedIMessageEcho, r as normalizeIMessageEchoText, s as maybeResolveIMessageApprovalPollVote, t as sendMessageIMessage } from "./send-Cu9nl757.mjs";
11
10
  import { n as normalizeIMessageGuid, t as resolveIMessageReactionContext } from "./reaction-context-Br-vAJFp.mjs";
12
- import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-lm8OxWbb.mjs";
11
+ import { i as resolveIMessageStartupRowidWatermark } from "./remote-file-DRPCaVmg.mjs";
12
+ import { n as maybeResolveIMessageQuestionReaction, t as hasIMessageQuestionReactionTarget } from "./question-reactions-Cy-dmU_j.mjs";
13
13
  import { asSafeIntegerInRange, hasNonEmptyString, isRecord, normalizeOptionalString, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
14
14
  import { bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
15
15
  import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
@@ -17,45 +17,45 @@ import { resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/p
17
17
  import path from "node:path";
18
18
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
19
19
  import fs from "node:fs/promises";
20
- import { createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
21
20
  import { isInboundPathAllowed, kindFromMime } from "openclaw/plugin-sdk/media-runtime";
22
- import { asDateTimestampMs, asPositiveFiniteNumber, parseDateStringTimestampMs, resolveIntegerOption, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
21
+ import { createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
22
+ import { asDateTimestampMs, asPositiveFiniteNumber, parseDateStringTimestampMs, resolveIntegerOption, resolvePromptHistoryLimit, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
23
23
  import { createHash } from "node:crypto";
24
24
  import { createRuntimeConfigReader, getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
25
25
  import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
26
26
  import { collectErrorGraphCandidates, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
27
- import { buildChannelGroupsScopeTree, resolveChannelGroupPolicy, resolveChannelGroups, resolveChannelGroupsConfigPath, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
28
- import { convertMarkdownTables as convertMarkdownTables$1, findCodeRegions, isInsideCode, sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
27
+ import { resolveChannelGroupPolicy, resolveChannelGroups, resolveChannelGroupsConfigPath, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
28
+ import { convertMarkdownTables, findCodeRegions, isInsideCode, sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
29
29
  import { buildChannelInboundEventContext, buildMentionRegexes, createAcceptedChannelDeliveryResult, createChannelInboundDebouncer, createChannelPartialDeliveryError, filterChannelInboundQuoteContext, formatInboundEnvelope, formatInboundFromLabel, formatInboundMediaUnavailableText, formatMediaPlaceholderText, isChannelPartialDeliveryError, logInboundDrop, matchesMentionPatterns, resolveEnvelopeFormatOptions, resolveInboundDebounceMs, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent, shouldDebounceTextInbound, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
30
30
  import { resolveAgentConfig, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
31
31
  import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-runtime";
32
32
  import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
33
- import { createChannelIngressResolver, defineStableChannelIngressIdentity, fanInChannelIngressLifecycles } from "openclaw/plugin-sdk/channel-ingress-runtime";
33
+ import { defineStableChannelIngressIdentity, fanInChannelIngressLifecycles } from "openclaw/plugin-sdk/channel-ingress-runtime";
34
34
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
35
35
  import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
36
- import { ensureConfiguredBindingRouteReady, readChannelAllowFromStore, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
36
+ import { ensureConfiguredBindingRouteReady, readChannelAllowFromStore, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
37
37
  import { channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
38
38
  import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
39
- import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
40
39
  import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
41
40
  import { FsSafeError, openLocalFileSafely, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
42
41
  import { getSessionEntry, readSessionUpdatedAt, resolveSendPolicy, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
43
- import { openNodeSqliteDatabase } from "openclaw/plugin-sdk/sqlite-runtime";
44
42
  import { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
45
43
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
46
- import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
44
+ import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
47
45
  import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
48
46
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
47
+ import { chunkMarkdownTextWithMode, resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking";
49
48
  import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
50
- import { chunkMarkdownTextWithMode as chunkTextWithMode, resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking";
51
49
  import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
52
50
  import { hasControlCommand } from "openclaw/plugin-sdk/command-auth-native";
53
51
  import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
52
+ import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
53
+ import { getSessionBindingService, inspectRuntimeConversationBindingRoute, resolveConfiguredBindingRoute } from "openclaw/plugin-sdk/conversation-binding-runtime";
54
54
  import { isRecord as isRecord$1 } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
55
55
  import { readFileHandleBounded } from "openclaw/plugin-sdk/file-access-runtime";
56
56
  import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
57
57
  import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
58
- import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
58
+ import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
59
59
  //#region extensions/imessage/src/approval-reaction-poller.ts
60
60
  const RECENT_CHAT_LIMIT = 50;
61
61
  const PER_CHAT_HISTORY_LIMIT$1 = 30;
@@ -73,9 +73,6 @@ function listTargetChatIds(targets) {
73
73
  function hasUnscopedTarget(targets) {
74
74
  return targets.some((target) => normalizeChatId(target.conversation.chatId) === null);
75
75
  }
76
- function uniqueChatIds(chatIds) {
77
- return [...new Set(chatIds)];
78
- }
79
76
  function enumerateMessageGuidCandidates(value) {
80
77
  const trimmed = value.trim();
81
78
  if (!trimmed) return [];
@@ -154,7 +151,7 @@ async function pollPendingIMessageApprovalReactions(params) {
154
151
  if (targets.length === 0) return;
155
152
  const pendingByMessageId = buildPendingTargetsByMessageId(targets);
156
153
  const explicitChatIds = listTargetChatIds(targets);
157
- const chatIds = params.allowRecentChatDiscovery === true && targets.length > 0 && hasUnscopedTarget(targets) ? uniqueChatIds([...explicitChatIds, ...await listRecentChatIds(params.client)]) : explicitChatIds;
154
+ const chatIds = params.allowRecentChatDiscovery === true && hasUnscopedTarget(targets) ? [.../* @__PURE__ */ new Set([...explicitChatIds, ...await listRecentChatIds(params.client)])] : explicitChatIds;
158
155
  if (chatIds.length === 0) return;
159
156
  for (const chatId of chatIds) {
160
157
  let messages;
@@ -210,9 +207,7 @@ function buildChatTargetParams(to, opts) {
210
207
  else params.to = target.to;
211
208
  return {
212
209
  params,
213
- service: opts.service ?? (target.kind === "handle" ? target.service : void 0) ?? account.config.service,
214
- region: opts.region?.trim() || account.config.region?.trim() || "US",
215
- account
210
+ service: opts.service ?? (target.kind === "handle" ? target.service : void 0) ?? account.config.service
216
211
  };
217
212
  }
218
213
  async function runChatAction(method, params, opts) {
@@ -278,15 +273,11 @@ function openCatchupCursorStore() {
278
273
  maxEntries: 256
279
274
  });
280
275
  }
281
- function enqueueCursorWrite(accountId, fn) {
282
- const key = resolveIMessageCatchupCursorKey(accountId);
283
- return cursorWriteQueue.enqueue(key, fn);
284
- }
285
276
  function sanitizeFailureRetriesInput(raw) {
286
277
  if (!raw || typeof raw !== "object") return {};
287
278
  const out = {};
288
279
  for (const [guid, count] of Object.entries(raw)) {
289
- if (!guid || typeof guid !== "string") continue;
280
+ if (!guid) continue;
290
281
  if (typeof count !== "number" || !Number.isFinite(count) || count <= 0) continue;
291
282
  out[guid] = Math.floor(count);
292
283
  }
@@ -348,14 +339,17 @@ function decideCatchupCursorSave(existingValue, cursor, allowCursorRewindForRetr
348
339
  async function saveIMessageCatchupCursor(accountId, next, options = {}) {
349
340
  const cursor = buildIMessageCatchupCursor(next, Date.now());
350
341
  const allowCursorRewindForRetries = options.allowCursorRewindForRetries === true;
342
+ await updateIMessageCatchupCursor(accountId, (existing) => decideCatchupCursorSave(existing, cursor, allowCursorRewindForRetries));
343
+ }
344
+ async function updateIMessageCatchupCursor(accountId, decide) {
351
345
  const store = openCatchupCursorStore();
352
346
  if (!store.observe || !store.compareAndApply) throw new Error("iMessage catchup cursor persistence requires plugin-state comparison support.");
353
347
  const key = resolveIMessageCatchupCursorKey(accountId);
354
348
  let observation = await store.observe(key);
355
349
  for (;;) {
356
- const intent = decideCatchupCursorSave(observation.value, cursor, allowCursorRewindForRetries);
350
+ const intent = decide(observation.value);
357
351
  const result = await store.compareAndApply(key, observation.comparison, intent);
358
- if (result.status !== "conflict") return;
352
+ if (result.status !== "conflict") return result.status === "applied";
359
353
  observation = result.current;
360
354
  }
361
355
  }
@@ -396,32 +390,12 @@ function decideLiveCatchupCursorAdvance(existingValue, next, maxFailureRetries)
396
390
  }
397
391
  async function advanceIMessageCatchupCursor(accountId, next, config) {
398
392
  if (!Number.isFinite(next.lastSeenMs) || !Number.isFinite(next.lastSeenRowid)) return false;
399
- return await enqueueCursorWrite(accountId, async () => {
393
+ return await cursorWriteQueue.enqueue(resolveIMessageCatchupCursorKey(accountId), async () => {
400
394
  const cursor = buildIMessageCatchupCursor(next, Date.now());
401
395
  const maxFailureRetries = config.maxFailureRetries;
402
- const store = openCatchupCursorStore();
403
- if (!store.observe || !store.compareAndApply) throw new Error("iMessage catchup cursor persistence requires plugin-state comparison support.");
404
- const key = resolveIMessageCatchupCursorKey(accountId);
405
- let observation = await store.observe(key);
406
- for (;;) {
407
- const intent = decideLiveCatchupCursorAdvance(observation.value, cursor, maxFailureRetries);
408
- const result = await store.compareAndApply(key, observation.comparison, intent);
409
- if (result.status !== "conflict") return result.status === "applied";
410
- observation = result.current;
411
- }
396
+ return updateIMessageCatchupCursor(accountId, (existing) => decideLiveCatchupCursorAdvance(existing, cursor, maxFailureRetries));
412
397
  });
413
398
  }
414
- /**
415
- * One catchup pass. Loads the cursor, fetches `messages.history`, replays
416
- * each row through `dispatch`, advances the cursor on success / give-up,
417
- * persists the cursor, returns a summary.
418
- *
419
- * The fetch and dispatch functions are injected so this loop is unit-testable
420
- * without standing up an `imsg` daemon. The wiring in `monitor-provider.ts`
421
- * passes the live `client.request("messages.history", ...)` adapter as
422
- * `fetch` and the `evaluateIMessageInbound` + `runChannelInboundEvent`
423
- * pipeline as `dispatch`.
424
- */
425
399
  async function performIMessageCatchup(params) {
426
400
  const now = params.now ?? Date.now();
427
401
  const cfg = params.config;
@@ -756,13 +730,8 @@ async function runIMessageCatchup(params) {
756
730
  warnLog(`imessage catchup: missing payload for guid=${row.guid}, skipping`);
757
731
  return { ok: false };
758
732
  }
759
- try {
760
- await dispatchPayload(entry.message, entry.rawEnvelope);
761
- return { ok: true };
762
- } catch (err) {
763
- warnLog(`imessage catchup: dispatch threw for guid=${row.guid}: ${String(err)}`);
764
- return { ok: false };
765
- }
733
+ await dispatchPayload(entry.message, entry.rawEnvelope);
734
+ return { ok: true };
766
735
  };
767
736
  return await performIMessageCatchup({
768
737
  accountId,
@@ -784,13 +753,6 @@ async function runIMessageCatchup(params) {
784
753
  }
785
754
  //#endregion
786
755
  //#region extensions/imessage/src/monitor/coalesce.ts
787
- /**
788
- * Bounds on the merged output when multiple inbound iMessage payloads are
789
- * folded into one agent turn. Caps each merge so a sender who
790
- * rapid-fires DMs inside the debounce window cannot amplify the downstream
791
- * prompt past a safe ceiling. Every source GUID still surfaces via
792
- * `coalescedMessageGuids` so a future replay path can recognize duplicates.
793
- */
794
756
  const MAX_COALESCED_TEXT_CHARS = 4e3;
795
757
  const MAX_COALESCED_ATTACHMENTS = 20;
796
758
  /**
@@ -810,12 +772,8 @@ function combineIMessagePayloads(payloads) {
810
772
  const seenTexts = /* @__PURE__ */ new Set();
811
773
  const textParts = [];
812
774
  const allAttachments = [];
813
- const seenGuids = /* @__PURE__ */ new Set();
814
- const coalescedMessageGuids = [];
815
775
  let textLength = 0;
816
776
  let latestCreatedAt;
817
- let maxRowid = -Infinity;
818
- let maxDateMs = -Infinity;
819
777
  let reply;
820
778
  let payloadIndex = 0;
821
779
  for (const payload of payloads) {
@@ -823,14 +781,6 @@ function combineIMessagePayloads(payloads) {
823
781
  payloadIndex += 1;
824
782
  const createdAt = payload.created_at;
825
783
  if (typeof createdAt === "string" && createdAt.length > 0 && (latestCreatedAt === void 0 || createdAt > latestCreatedAt)) latestCreatedAt = createdAt;
826
- if (typeof payload.id === "number" && Number.isFinite(payload.id)) maxRowid = Math.max(maxRowid, payload.id);
827
- const dateMs = typeof createdAt === "string" ? Date.parse(createdAt) : NaN;
828
- if (Number.isFinite(dateMs)) maxDateMs = Math.max(maxDateMs, dateMs);
829
- const guid = payload.guid?.trim();
830
- if (guid && !seenGuids.has(guid)) {
831
- seenGuids.add(guid);
832
- coalescedMessageGuids.push(guid);
833
- }
834
784
  if (!reply && (payload.thread_originator_guid != null || payload.reply_to_guid != null)) reply = payload;
835
785
  if (!keepContent) continue;
836
786
  const text = textLength <= MAX_COALESCED_TEXT_CHARS ? (payload.text ?? "").trim() : "";
@@ -860,12 +810,7 @@ function combineIMessagePayloads(payloads) {
860
810
  thread_originator_guid: reply.thread_originator_guid ?? null,
861
811
  reply_to_guid: reply.reply_to_guid ?? null,
862
812
  reply_to_text: reply.reply_to_text ?? null,
863
- reply_to_sender: reply.reply_to_sender ?? null,
864
- coalescedMessageGuids: coalescedMessageGuids.length > 0 ? coalescedMessageGuids : void 0,
865
- coalescedCatchupCursor: Number.isFinite(maxRowid) && Number.isFinite(maxDateMs) ? {
866
- lastSeenMs: maxDateMs,
867
- lastSeenRowid: maxRowid
868
- } : void 0
813
+ reply_to_sender: reply.reply_to_sender ?? null
869
814
  };
870
815
  }
871
816
  //#endregion
@@ -913,20 +858,6 @@ function projectionConflictKey(projection) {
913
858
  is_from_me: projection.is_from_me
914
859
  });
915
860
  }
916
- function applyAuthoritativeRecoveryProjection(message, projection) {
917
- return {
918
- ...message,
919
- ...projection.chat_id !== void 0 ? { chat_id: projection.chat_id } : {},
920
- ...projection.chat_guid !== void 0 ? { chat_guid: projection.chat_guid } : {},
921
- ...projection.chat_identifier !== void 0 ? { chat_identifier: projection.chat_identifier } : {},
922
- ...projection.chat_name !== void 0 ? { chat_name: projection.chat_name } : {},
923
- ...projection.participants !== void 0 ? { participants: projection.participants } : {},
924
- is_group: projection.is_group,
925
- sender: projection.sender,
926
- destination_caller_id: projection.destination_caller_id ?? null,
927
- is_from_me: projection.is_from_me
928
- };
929
- }
930
861
  async function repairIMessageConversationAnchor(params) {
931
862
  const { client, message, runtime } = params;
932
863
  if (!isIMessageAnchorless(message)) return message;
@@ -983,12 +914,12 @@ async function repairIMessageConversationAnchor(params) {
983
914
  runtime?.error?.(`imessage: dropping anchorless message GUID=${guid}; recovered authoritative row is from-me`);
984
915
  return null;
985
916
  }
986
- const repaired = applyAuthoritativeRecoveryProjection(message, projection);
987
- if (isIMessageAnchorless(repaired)) {
988
- runtime?.error?.(`imessage: dropping anchorless message GUID=${guid} after recovery found no usable conversation anchor`);
989
- return null;
990
- }
991
- runtime?.log?.(`imessage: recovered anchorless message GUID=${guid} chat_id=${repaired.chat_id ?? "unknown"} is_group=${repaired.is_group === true}`);
917
+ const repaired = {
918
+ ...message,
919
+ ...projection,
920
+ destination_caller_id: projection.destination_caller_id ?? null
921
+ };
922
+ runtime?.log?.(`imessage: recovered anchorless message GUID=${guid} chat_id=${repaired.chat_id ?? "unknown"} is_group=${repaired.is_group}`);
992
923
  return repaired;
993
924
  }
994
925
  //#endregion
@@ -997,14 +928,14 @@ async function deliverIMessageReply(params) {
997
928
  const { payload, target, runtime, maxBytes, textLimit, accountId, sentMessageCache } = params;
998
929
  const scope = `${accountId ?? ""}:${target}`;
999
930
  const { cfg } = params;
1000
- const tableMode = resolveMarkdownTableMode$1({
931
+ const tableMode = resolveMarkdownTableMode({
1001
932
  cfg,
1002
933
  channel: "imessage",
1003
934
  accountId
1004
935
  });
1005
936
  const chunkMode = resolveChunkMode(cfg, "imessage", accountId);
1006
937
  const rawText = sanitizeOutboundText(payload.text ?? "");
1007
- const reply = resolveSendableOutboundReplyParts(payload, { text: convertMarkdownTables$1(rawText, tableMode) });
938
+ const reply = resolveSendableOutboundReplyParts(payload, { text: convertMarkdownTables(rawText, tableMode) });
1008
939
  const accepted = [];
1009
940
  const sendAccepted = async (text, mediaUrl) => {
1010
941
  const sent = await sendMessageIMessage(target, text, {
@@ -1030,7 +961,7 @@ async function deliverIMessageReply(params) {
1030
961
  delivered = await deliverTextOrMediaReply({
1031
962
  payload,
1032
963
  text: reply.text,
1033
- chunkText: (value) => chunkTextWithMode(value, textLimit, chunkMode),
964
+ chunkText: (value) => chunkMarkdownTextWithMode(value, textLimit, chunkMode),
1034
965
  sendText: sendAccepted,
1035
966
  sendMedia: ({ mediaUrl, caption }) => sendAccepted(caption ?? "", mediaUrl)
1036
967
  });
@@ -1154,11 +1085,6 @@ function createIMessageThrottledDropDiagnosticCache() {
1154
1085
  //#region extensions/imessage/src/monitor/echo-cache.ts
1155
1086
  const SENT_MESSAGE_TEXT_TTL_MS = 4e3;
1156
1087
  const SENT_MESSAGE_ID_TTL_MS = 6e4;
1157
- function normalizeEchoTextKey(text) {
1158
- if (!text) return null;
1159
- const normalized = stripLeadingEchoTextCorruptionMarkers(text.replace(/\r\n?/g, "\n").trim()).trim();
1160
- return normalized ? normalized : null;
1161
- }
1162
1088
  function normalizeEchoMessageIdKey(messageId) {
1163
1089
  if (!messageId) return null;
1164
1090
  const normalized = messageId.trim();
@@ -1174,7 +1100,7 @@ var DefaultSentMessageCache = class {
1174
1100
  this.messageIdCache = /* @__PURE__ */ new Map();
1175
1101
  }
1176
1102
  remember(scope, lookup) {
1177
- const textKey = normalizeEchoTextKey(lookup.text);
1103
+ const textKey = normalizeIMessageEchoText(lookup.text);
1178
1104
  if (textKey) this.textCache.set(`${scope}:${textKey}`, Date.now());
1179
1105
  const mediaKey = resolveIMessageEchoMediaKey(lookup.media);
1180
1106
  if (mediaKey) this.mediaCache.set(`${scope}:${mediaKey}`, Date.now());
@@ -1197,7 +1123,7 @@ var DefaultSentMessageCache = class {
1197
1123
  skipIdShortCircuit: resolvedOptions.skipIdShortCircuit,
1198
1124
  includePendingText: resolvedOptions.includePendingText
1199
1125
  })) return true;
1200
- const textKey = normalizeEchoTextKey(lookup.text);
1126
+ const textKey = normalizeIMessageEchoText(lookup.text);
1201
1127
  const mediaKey = resolveIMessageEchoMediaKey(lookup.media);
1202
1128
  const messageIdKey = normalizeEchoMessageIdKey(lookup.messageId);
1203
1129
  let canUseMediaFallback = !messageIdKey;
@@ -1225,11 +1151,16 @@ var DefaultSentMessageCache = class {
1225
1151
  }
1226
1152
  cleanup() {
1227
1153
  const now = Date.now();
1228
- for (const [key, timestamp] of this.textCache.entries()) if (now - timestamp > SENT_MESSAGE_TEXT_TTL_MS) this.textCache.delete(key);
1229
- for (const [key, timestamp] of this.textBackedByIdCache.entries()) if (now - timestamp > SENT_MESSAGE_TEXT_TTL_MS) this.textBackedByIdCache.delete(key);
1230
- for (const [key, timestamp] of this.mediaCache.entries()) if (now - timestamp > SENT_MESSAGE_TEXT_TTL_MS) this.mediaCache.delete(key);
1231
- for (const [key, timestamp] of this.mediaBackedByIdCache.entries()) if (now - timestamp > SENT_MESSAGE_TEXT_TTL_MS) this.mediaBackedByIdCache.delete(key);
1232
- for (const [key, timestamp] of this.messageIdCache.entries()) if (now - timestamp > SENT_MESSAGE_ID_TTL_MS) this.messageIdCache.delete(key);
1154
+ for (const cache of [
1155
+ this.textCache,
1156
+ this.textBackedByIdCache,
1157
+ this.mediaCache,
1158
+ this.mediaBackedByIdCache,
1159
+ this.messageIdCache
1160
+ ]) {
1161
+ const ttlMs = cache === this.messageIdCache ? SENT_MESSAGE_ID_TTL_MS : SENT_MESSAGE_TEXT_TTL_MS;
1162
+ for (const [key, timestamp] of cache) if (now - timestamp > ttlMs) cache.delete(key);
1163
+ }
1233
1164
  }
1234
1165
  };
1235
1166
  function createSentMessageCache() {
@@ -1291,23 +1222,25 @@ function isStaleIMessageBacklog(message, nowMs, thresholdMs = IMESSAGE_STALE_INB
1291
1222
  }
1292
1223
  //#endregion
1293
1224
  //#region extensions/imessage/src/conversation-route.ts
1294
- function resolveIMessageConversationRoute(params) {
1295
- const route = resolveAgentRoute({
1296
- cfg: params.cfg,
1225
+ async function resolveIMessageConversationRoute(params) {
1226
+ const routeInput = {
1297
1227
  channel: "imessage",
1298
1228
  accountId: params.accountId,
1299
1229
  peer: {
1300
1230
  kind: params.isGroup ? "group" : "direct",
1301
1231
  id: params.peerId
1302
1232
  }
1303
- });
1233
+ };
1304
1234
  const conversationId = resolveIMessageInboundConversationId({
1305
1235
  isGroup: params.isGroup,
1306
1236
  sender: params.sender,
1307
1237
  chatId: params.chatId
1308
1238
  });
1309
1239
  if (!conversationId) return {
1310
- route,
1240
+ route: resolveAgentRoute({
1241
+ ...routeInput,
1242
+ cfg: params.cfg
1243
+ }),
1311
1244
  bindingResolution: null
1312
1245
  };
1313
1246
  const conversation = {
@@ -1315,20 +1248,81 @@ function resolveIMessageConversationRoute(params) {
1315
1248
  accountId: params.accountId,
1316
1249
  conversationId
1317
1250
  };
1318
- const configuredRoute = resolveConfiguredBindingRoute({
1319
- cfg: params.cfg,
1320
- route,
1321
- conversation
1322
- });
1323
- const runtimeRoute = resolveRuntimeConversationBindingRoute({
1324
- route: configuredRoute.route,
1325
- conversation
1251
+ const service = getSessionBindingService();
1252
+ const inspection = await service.inspectByConversationAsync(conversation);
1253
+ if (inspection.status === "unavailable") throw new Error("iMessage conversation binding owner is temporarily unavailable; retry the message.");
1254
+ let bindingResolution = null;
1255
+ const runtimeRoute = inspectRuntimeConversationBindingRoute({
1256
+ inspection,
1257
+ resolveRoute: ({ boundAgentId }) => {
1258
+ if (boundAgentId) return resolveAgentRoute({
1259
+ ...routeInput,
1260
+ cfg: { session: params.cfg.session },
1261
+ defaultAgentId: boundAgentId
1262
+ });
1263
+ const configuredRoute = resolveConfiguredBindingRoute({
1264
+ cfg: params.cfg,
1265
+ route: resolveAgentRoute({
1266
+ ...routeInput,
1267
+ cfg: params.cfg
1268
+ }),
1269
+ conversation
1270
+ });
1271
+ bindingResolution = configuredRoute.bindingResolution;
1272
+ return configuredRoute.route;
1273
+ }
1326
1274
  });
1275
+ if (runtimeRoute.bindingRecord) await service.touchAsync(runtimeRoute.bindingRecord.bindingId, void 0, runtimeRoute.bindingRecord.conversation);
1327
1276
  if (runtimeRoute.bindingRecord && !runtimeRoute.boundSessionKey) logVerbose(`imessage: plugin-bound conversation ${conversationId}`);
1328
1277
  else if (runtimeRoute.boundSessionKey) logVerbose(`imessage: routed via bound conversation ${conversationId} -> ${runtimeRoute.boundSessionKey}`);
1329
1278
  return {
1330
1279
  route: runtimeRoute.route,
1331
- bindingResolution: runtimeRoute.bindingRecord ? null : configuredRoute.bindingResolution
1280
+ bindingResolution: runtimeRoute.bindingRecord ? null : bindingResolution
1281
+ };
1282
+ }
1283
+ //#endregion
1284
+ //#region src/channels/mention-gating.ts
1285
+ function resolveBotThreadMentionPolicy(params) {
1286
+ if (!params.isBotOwnedThread || params.requireMentionInBotThreads === void 0) return {
1287
+ requireMention: params.requireMention,
1288
+ implicitMentionKinds: params.implicitMentionKinds
1289
+ };
1290
+ return {
1291
+ requireMention: params.requireMentionInBotThreads,
1292
+ implicitMentionKinds: params.requireMentionInBotThreads ? params.implicitMentionKinds?.filter((kind) => kind === "native") : params.implicitMentionKinds
1293
+ };
1294
+ }
1295
+ //#endregion
1296
+ //#region extensions/imessage/src/monitor/mention-policy.ts
1297
+ async function resolveIMessageInboundMentionPolicy(params) {
1298
+ const groups = resolveChannelGroups(params.cfg, "imessage", params.accountId);
1299
+ const { "*": defaults, ...scopes } = groups ?? {};
1300
+ const requireMention = resolveScopeRequireMention({
1301
+ tree: {
1302
+ defaults,
1303
+ scopes
1304
+ },
1305
+ path: params.groupId ? [params.groupId] : [],
1306
+ requireMentionOverride: params.requireMentionOverride,
1307
+ overrideOrder: "before-config"
1308
+ });
1309
+ const requireMentionInBotThreads = (params.groupId ? groups?.[params.groupId]?.requireMentionInBotThreads : void 0) ?? defaults?.requireMentionInBotThreads;
1310
+ const threadOriginatorGuid = params.message.thread_originator_guid?.trim();
1311
+ const isBotOwnedThread = Boolean(params.isGroup && requireMentionInBotThreads !== void 0 && threadOriginatorGuid && await isKnownFromMeIMessageTarget({
1312
+ messageIds: uniqueStrings([normalizeIMessageGuid(threadOriginatorGuid), threadOriginatorGuid]),
1313
+ accountId: params.accountId,
1314
+ chatId: params.message.chat_id ?? void 0,
1315
+ chatGuid: params.message.chat_guid ?? void 0,
1316
+ chatIdentifier: params.message.chat_identifier ?? void 0,
1317
+ isKnownFromMeMessageId: params.isKnownFromMeMessageId
1318
+ }));
1319
+ return {
1320
+ ...resolveBotThreadMentionPolicy({
1321
+ isBotOwnedThread,
1322
+ requireMentionInBotThreads,
1323
+ requireMention
1324
+ }),
1325
+ enforceMentionRequirement: isBotOwnedThread && requireMentionInBotThreads === true
1332
1326
  };
1333
1327
  }
1334
1328
  //#endregion
@@ -1363,8 +1357,7 @@ const REFLECTION_PATTERNS = [
1363
1357
  label: "gateway-missing-api-key"
1364
1358
  }
1365
1359
  ];
1366
- function hasMatchOutsideCode(text, re) {
1367
- const codeRegions = findCodeRegions(text);
1360
+ function hasMatchOutsideCode(text, re, codeRegions) {
1368
1361
  const globalRe = new RegExp(re.source, re.flags.includes("g") ? re.flags : `${re.flags}g`);
1369
1362
  for (const match of text.matchAll(globalRe)) {
1370
1363
  const start = match.index ?? -1;
@@ -1381,8 +1374,9 @@ function detectReflectedContent(text) {
1381
1374
  isReflection: false,
1382
1375
  matchedLabels: []
1383
1376
  };
1377
+ const codeRegions = findCodeRegions(text);
1384
1378
  const matchedLabels = [];
1385
- for (const { re, label } of REFLECTION_PATTERNS) if (hasMatchOutsideCode(text, re)) matchedLabels.push(label);
1379
+ for (const { re, label } of REFLECTION_PATTERNS) if (hasMatchOutsideCode(text, re, codeRegions)) matchedLabels.push(label);
1386
1380
  return {
1387
1381
  isReflection: matchedLabels.length > 0,
1388
1382
  matchedLabels
@@ -1480,12 +1474,16 @@ function describeReplyContext(message) {
1480
1474
  }
1481
1475
  function resolveInboundEchoMessageIds(message) {
1482
1476
  const values = [message.id != null ? String(message.id) : void 0, normalizeReplyField(message.guid)];
1483
- const ids = [];
1484
- for (const value of values) {
1485
- if (!value || ids.includes(value)) continue;
1486
- ids.push(value);
1487
- }
1488
- return ids;
1477
+ return uniqueStrings(values.filter((value) => Boolean(value)));
1478
+ }
1479
+ function classifyIMessageSelfChat(message, isGroup, senderNormalized) {
1480
+ const chatIdentifier = normalizeIMessageHandle(message.chat_identifier ?? "") || void 0;
1481
+ const destination = normalizeIMessageHandle(message.destination_caller_id ?? "") || void 0;
1482
+ const matchesThread = !isGroup && chatIdentifier != null && senderNormalized === chatIdentifier;
1483
+ return {
1484
+ isSelfChat: matchesThread && destination != null && destination === senderNormalized,
1485
+ isAmbiguousSelfThread: matchesThread && destination == null
1486
+ };
1489
1487
  }
1490
1488
  function rememberIMessageSkippedFromMeForSelfChatDedupe(params) {
1491
1489
  if (params.message.is_from_me !== true) return;
@@ -1493,9 +1491,6 @@ function rememberIMessageSkippedFromMeForSelfChatDedupe(params) {
1493
1491
  if (!sender) return;
1494
1492
  const chatId = params.message.chat_id ?? void 0;
1495
1493
  const isGroup = Boolean(params.message.is_group);
1496
- const chatIdentifierNormalized = normalizeIMessageHandle(params.message.chat_identifier ?? "") || void 0;
1497
- const destinationCallerIdNormalized = normalizeIMessageHandle(params.message.destination_caller_id ?? "") || void 0;
1498
- const senderNormalized = normalizeIMessageHandle(sender);
1499
1494
  const createdAt = params.message.created_at ? Date.parse(params.message.created_at) : void 0;
1500
1495
  const lookup = {
1501
1496
  accountId: params.accountId,
@@ -1505,8 +1500,7 @@ function rememberIMessageSkippedFromMeForSelfChatDedupe(params) {
1505
1500
  text: params.bodyText.trim(),
1506
1501
  createdAt
1507
1502
  };
1508
- const isSelfChat = !isGroup && chatIdentifierNormalized != null && senderNormalized === chatIdentifierNormalized && destinationCallerIdNormalized != null && destinationCallerIdNormalized === senderNormalized;
1509
- const isAmbiguousSelfThread = !isGroup && chatIdentifierNormalized != null && senderNormalized === chatIdentifierNormalized && destinationCallerIdNormalized == null;
1503
+ const { isSelfChat, isAmbiguousSelfThread } = classifyIMessageSelfChat(params.message, isGroup, normalizeIMessageHandle(sender));
1510
1504
  if (isSelfChat) params.selfChatCache?.remember({
1511
1505
  ...lookup,
1512
1506
  allowCreatedAtSkew: true
@@ -1531,36 +1525,6 @@ async function hasIMessageEchoMatch(params) {
1531
1525
  }
1532
1526
  return false;
1533
1527
  }
1534
- async function isKnownFromMeIMessageReactionTarget(params) {
1535
- const { accountId, chatId, chatGuid, chatIdentifier } = params;
1536
- const ctx = {
1537
- accountId,
1538
- chatId,
1539
- chatGuid,
1540
- chatIdentifier
1541
- };
1542
- const isKnownFromMe = params.isKnownFromMeMessageId ?? isKnownFromMeIMessageMessageId;
1543
- for (const messageId of params.messageIds) if (await isKnownFromMe(messageId, ctx)) return true;
1544
- return false;
1545
- }
1546
- /**
1547
- * Per-group `systemPrompt` resolution. Mirrors `resolveWhatsAppGroupSystemPrompt`
1548
- * in `extensions/whatsapp/src/system-prompt.ts`:
1549
- *
1550
- * 1. If the matched per-`chat_id` entry exists AND defines `systemPrompt` (key
1551
- * is present, value is non-null), use it. Trim whitespace; if the trim
1552
- * leaves an empty string, return `undefined` and DO NOT fall through to the
1553
- * wildcard. This is how operators say "this specific group has no prompt"
1554
- * without inheriting from `groups["*"]`.
1555
- * 2. Otherwise, return the wildcard `groups["*"].systemPrompt` (trimmed; empty
1556
- * after trim → `undefined`).
1557
- */
1558
- function resolveIMessageGroupSystemPrompt(params) {
1559
- const specific = params.groupConfig;
1560
- if (specific != null && specific.systemPrompt != null) return specific.systemPrompt.trim() || void 0;
1561
- const wildcard = params.defaultConfig?.systemPrompt;
1562
- return wildcard != null ? wildcard.trim() || void 0 : void 0;
1563
- }
1564
1528
  async function resolveIMessageInboundDecision(params) {
1565
1529
  const sender = (params.message.sender ?? "").trim();
1566
1530
  if (!sender) return {
@@ -1571,7 +1535,6 @@ async function resolveIMessageInboundDecision(params) {
1571
1535
  const chatId = params.message.chat_id ?? void 0;
1572
1536
  const chatGuid = params.message.chat_guid ?? void 0;
1573
1537
  const chatIdentifier = params.message.chat_identifier ?? void 0;
1574
- const destinationCallerId = params.message.destination_caller_id ?? void 0;
1575
1538
  const createdAt = params.message.created_at ? Date.parse(params.message.created_at) : void 0;
1576
1539
  const messageText = params.messageText.trim();
1577
1540
  const bodyText = params.bodyText.trim();
@@ -1605,10 +1568,7 @@ async function resolveIMessageInboundDecision(params) {
1605
1568
  text: bodyText,
1606
1569
  createdAt
1607
1570
  };
1608
- const chatIdentifierNormalized = normalizeIMessageHandle(chatIdentifier ?? "") || void 0;
1609
- const destinationCallerIdNormalized = normalizeIMessageHandle(destinationCallerId ?? "") || void 0;
1610
- const isSelfChat = !isGroup && chatIdentifierNormalized != null && senderNormalized === chatIdentifierNormalized && destinationCallerIdNormalized != null && destinationCallerIdNormalized === senderNormalized;
1611
- const isAmbiguousSelfThread = !isGroup && chatIdentifierNormalized != null && senderNormalized === chatIdentifierNormalized && destinationCallerIdNormalized == null;
1571
+ const { isSelfChat, isAmbiguousSelfThread } = classifyIMessageSelfChat(params.message, isGroup, senderNormalized);
1612
1572
  let skipSelfChatHasCheck = false;
1613
1573
  const inboundMessageIds = resolveInboundEchoMessageIds(params.message);
1614
1574
  const inboundMessageId = inboundMessageIds[0];
@@ -1653,7 +1613,7 @@ async function resolveIMessageInboundDecision(params) {
1653
1613
  const groupId = isGroup ? groupIdCandidate : void 0;
1654
1614
  const hasControlCommandInMessage = hasControlCommand(messageText, params.cfg);
1655
1615
  const groupAllowFromForAccess = isGroup ? groupAllowFromWithLegacyChatTargets : params.groupAllowFrom;
1656
- const { route, bindingResolution } = resolveIMessageConversationRoute({
1616
+ const { route, bindingResolution } = await resolveIMessageConversationRoute({
1657
1617
  cfg: params.cfg,
1658
1618
  accountId: params.accountId,
1659
1619
  isGroup,
@@ -1661,13 +1621,14 @@ async function resolveIMessageInboundDecision(params) {
1661
1621
  sender,
1662
1622
  chatId
1663
1623
  });
1664
- const accessDecision = await createChannelIngressResolver({
1624
+ const ingressResolver = getIMessageRuntime().channel.inbound.ingress.createResolver({
1665
1625
  channelId: "imessage",
1666
1626
  accountId: params.accountId,
1667
1627
  identity: imessageIngressIdentity,
1668
1628
  cfg: params.cfg,
1669
1629
  readStoreAllowFrom: async () => params.storeAllowFrom
1670
- }).message({
1630
+ });
1631
+ const resolveChannelIngress = (contextBinding) => ingressResolver.message({
1671
1632
  subject: {
1672
1633
  stableId: sender,
1673
1634
  aliases: {
@@ -1678,13 +1639,9 @@ async function resolveIMessageInboundDecision(params) {
1678
1639
  },
1679
1640
  conversation: {
1680
1641
  kind: isGroup ? "group" : "direct",
1681
- id: isGroup ? String(chatId ?? chatGuid ?? chatIdentifier ?? "unknown") : normalizeIMessageHandle(sender)
1642
+ id: chatId != null ? String(chatId) : sender
1682
1643
  },
1683
- ...reactionContext ? {} : { contextBinding: {
1684
- agentId: route.agentId,
1685
- sessionKey: route.sessionKey,
1686
- inboundEventKind: "user_request"
1687
- } },
1644
+ contextBinding,
1688
1645
  dmPolicy: normalizeDmPolicy(params.dmPolicy),
1689
1646
  groupPolicy: normalizeGroupPolicy(params.groupPolicy),
1690
1647
  policy: { groupAllowFromFallbackToAllowFrom: false },
@@ -1696,7 +1653,7 @@ async function resolveIMessageInboundDecision(params) {
1696
1653
  directGroupAllowFrom: "effective"
1697
1654
  }
1698
1655
  });
1699
- const { commandAccess, senderAccess } = accessDecision;
1656
+ const { commandAccess, senderAccess } = await resolveChannelIngress();
1700
1657
  const effectiveGroupAllowFrom = senderAccess.effectiveGroupAllowFrom;
1701
1658
  if (senderAccess.decision !== "allow") {
1702
1659
  if (isGroup) {
@@ -1767,7 +1724,7 @@ async function resolveIMessageInboundDecision(params) {
1767
1724
  sender
1768
1725
  }),
1769
1726
  messageIds: targetGuids
1770
- }) || await isKnownFromMeIMessageReactionTarget({
1727
+ }) || await isKnownFromMeIMessageTarget({
1771
1728
  messageIds: targetGuids,
1772
1729
  accountId: params.accountId,
1773
1730
  chatId,
@@ -1886,13 +1843,16 @@ async function resolveIMessageInboundDecision(params) {
1886
1843
  if (replyContext && !filteredReplyContext && isGroup) params.logVerbose?.(`imessage: drop reply context (mode=${contextVisibilityMode}, sender_allowed=${replySenderAllowed ? "yes" : "no"})`);
1887
1844
  const historyKey = isGroup ? String(chatId ?? chatGuid ?? chatIdentifier ?? "unknown") : void 0;
1888
1845
  const mentioned = isGroup ? matchesMentionPatterns(messageText, mentionRegexes) : true;
1889
- const requireMention = resolveScopeRequireMention({
1890
- tree: buildChannelGroupsScopeTree(params.cfg, "imessage", params.accountId),
1891
- path: groupId ? [groupId] : [],
1846
+ const { requireMention, implicitMentionKinds, enforceMentionRequirement } = await resolveIMessageInboundMentionPolicy({
1847
+ cfg: params.cfg,
1848
+ accountId: params.accountId,
1849
+ groupId,
1850
+ isGroup,
1851
+ message: params.message,
1892
1852
  requireMentionOverride: params.opts?.requireMention,
1893
- overrideOrder: "before-config"
1853
+ isKnownFromMeMessageId: params.isKnownFromMeMessageId
1894
1854
  });
1895
- const canDetectMention = mentionRegexes.length > 0;
1855
+ const canDetectMention = mentionRegexes.length > 0 || enforceMentionRequirement;
1896
1856
  const commandAuthorized = commandAccess.authorized;
1897
1857
  if (commandAccess.shouldBlockControlCommand) {
1898
1858
  if (params.logVerbose) logInboundDrop({
@@ -1911,7 +1871,7 @@ async function resolveIMessageInboundDecision(params) {
1911
1871
  canDetectMention,
1912
1872
  wasMentioned: mentioned,
1913
1873
  hasAnyMention: false,
1914
- implicitMentionKinds: []
1874
+ implicitMentionKinds
1915
1875
  },
1916
1876
  policy: {
1917
1877
  isGroup,
@@ -1941,7 +1901,7 @@ async function resolveIMessageInboundDecision(params) {
1941
1901
  }
1942
1902
  return {
1943
1903
  kind: "dispatch",
1944
- channelIngress: accessDecision,
1904
+ resolveChannelIngress,
1945
1905
  isGroup,
1946
1906
  chatId,
1947
1907
  chatGuid,
@@ -2032,9 +1992,15 @@ async function buildIMessageInboundContext(params) {
2032
1992
  ...entry,
2033
1993
  url: entry.url ?? entry.path
2034
1994
  })));
1995
+ const channelIngress = await decision.resolveChannelIngress({
1996
+ agentId: decision.route.agentId,
1997
+ sessionKey: decision.route.sessionKey,
1998
+ messageId: messageSid,
1999
+ inboundEventKind: "user_request"
2000
+ });
2035
2001
  return {
2036
- ctxPayload: (params.buildContext ?? buildChannelInboundEventContext)({
2037
- channelIngress: decision.channelIngress,
2002
+ ctxPayload: await (params.buildContext ?? buildChannelInboundEventContext)({
2003
+ channelIngress,
2038
2004
  channel: "imessage",
2039
2005
  supplemental: {
2040
2006
  quote: decision.replyContext ? {
@@ -2064,9 +2030,7 @@ async function buildIMessageInboundContext(params) {
2064
2030
  label: conversationName
2065
2031
  },
2066
2032
  route: {
2067
- agentId: decision.route.agentId,
2068
- dmScope: decision.route.dmScope,
2069
- accountId: decision.route.accountId,
2033
+ ...decision.route,
2070
2034
  routeSessionKey: decision.route.sessionKey
2071
2035
  },
2072
2036
  reply: { to: replyTarget },
@@ -2350,44 +2314,40 @@ async function assertAllowedCanonicalAttachmentPath(params) {
2350
2314
  })) throw new Error("attachment path resolves outside allowed roots");
2351
2315
  }
2352
2316
  async function readAttachmentBuffer(params) {
2353
- const opened = await (params.deps.openLocalFileSafely ?? openLocalFileSafely)({ filePath: params.attachmentPath });
2354
- try {
2355
- if (opened.stat.size > params.maxBytes) throw new Error(`attachment exceeds ${Math.round(params.maxBytes / 1048576)}MB limit`);
2356
- await assertAllowedCanonicalAttachmentPath({
2357
- canonicalPath: opened.realPath,
2358
- allowedRoots: params.allowedRoots
2359
- });
2360
- const buffer = await readFileHandleBounded(opened.handle, params.maxBytes).catch((error) => {
2361
- if (error instanceof FsSafeError && error.code === "too-large") throw new Error(`attachment exceeds ${Math.round(params.maxBytes / 1048576)}MB limit`);
2362
- throw error;
2363
- });
2364
- if (isHeicAttachment(params.attachmentPath, params.mimeType)) try {
2365
- const convert = params.deps.convertHeicToJpeg;
2366
- return {
2367
- buffer: (await withTempWorkspace({
2368
- rootDir: resolvePreferredOpenClawTmpDir(),
2369
- prefix: "openclaw-imessage-heic-"
2370
- }, async (workspace) => {
2371
- const pinnedPath = await workspace.write("attachment.heic", buffer);
2372
- return convert ? { buffer: await convert(pinnedPath, params.maxBytes) } : await loadWebMedia(pinnedPath, {
2373
- maxBytes: params.maxBytes,
2374
- localRoots: [workspace.dir]
2375
- });
2376
- })).buffer,
2377
- contentType: "image/jpeg",
2378
- originalFilename: jpegFilenameForAttachment(params.attachmentPath)
2379
- };
2380
- } catch (err) {
2381
- params.deps.logVerbose?.(`imessage: HEIC attachment conversion failed; staging original instead: ${String(err)}`);
2382
- }
2317
+ await using opened = await (params.deps.openLocalFileSafely ?? openLocalFileSafely)({ filePath: params.attachmentPath });
2318
+ if (opened.stat.size > params.maxBytes) throw new Error(`attachment exceeds ${Math.round(params.maxBytes / 1048576)}MB limit`);
2319
+ await assertAllowedCanonicalAttachmentPath({
2320
+ canonicalPath: opened.realPath,
2321
+ allowedRoots: params.allowedRoots
2322
+ });
2323
+ const buffer = await readFileHandleBounded(opened.handle, params.maxBytes).catch((error) => {
2324
+ if (error instanceof FsSafeError && error.code === "too-large") throw new Error(`attachment exceeds ${Math.round(params.maxBytes / 1048576)}MB limit`);
2325
+ throw error;
2326
+ });
2327
+ if (isHeicAttachment(params.attachmentPath, params.mimeType)) try {
2328
+ const convert = params.deps.convertHeicToJpeg;
2383
2329
  return {
2384
- buffer,
2385
- contentType: params.mimeType ?? void 0,
2386
- originalFilename: path.basename(params.attachmentPath)
2330
+ buffer: (await withTempWorkspace({
2331
+ rootDir: resolvePreferredOpenClawTmpDir(),
2332
+ prefix: "openclaw-imessage-heic-"
2333
+ }, async (workspace) => {
2334
+ const pinnedPath = await workspace.write("attachment.heic", buffer);
2335
+ return convert ? { buffer: await convert(pinnedPath, params.maxBytes) } : await loadWebMedia(pinnedPath, {
2336
+ maxBytes: params.maxBytes,
2337
+ localRoots: [workspace.dir]
2338
+ });
2339
+ })).buffer,
2340
+ contentType: "image/jpeg",
2341
+ originalFilename: jpegFilenameForAttachment(params.attachmentPath)
2387
2342
  };
2388
- } finally {
2389
- await opened.handle.close().catch(() => void 0);
2343
+ } catch (err) {
2344
+ params.deps.logVerbose?.(`imessage: HEIC attachment conversion failed; staging original instead: ${String(err)}`);
2390
2345
  }
2346
+ return {
2347
+ buffer,
2348
+ contentType: params.mimeType ?? void 0,
2349
+ originalFilename: path.basename(params.attachmentPath)
2350
+ };
2391
2351
  }
2392
2352
  async function stageIMessageAttachments(attachments, params) {
2393
2353
  const deps = params.deps ?? {};
@@ -2508,10 +2468,7 @@ function renderIMessagePollBody(poll, sender, renderOptions) {
2508
2468
  //#region extensions/imessage/src/monitor/reaction-system-event.ts
2509
2469
  function enqueueIMessageReactionSystemEvent(params) {
2510
2470
  const { decision, runtime } = params;
2511
- const queued = enqueueSystemEvent(decision.text, {
2512
- sessionKey: decision.route.sessionKey,
2513
- contextKey: decision.contextKey
2514
- });
2471
+ const queued = enqueueRoutedSystemEvent(decision.text, decision.route, { contextKey: decision.contextKey });
2515
2472
  runtime.log?.(`imessage: reaction system event ${queued ? "queued" : "deduped"} session=${decision.route.sessionKey} target=${decision.reaction.targetGuid ?? "unknown"} action=${decision.reaction.action} emoji=${decision.reaction.emoji}`);
2516
2473
  params.logVerbose?.(`imessage: reaction event enqueued: ${decision.text}`);
2517
2474
  return queued;
@@ -2659,11 +2616,6 @@ async function advanceIMessageRecoveryCursor(accountId, dbIdentity, rowid) {
2659
2616
  } catch {}
2660
2617
  }
2661
2618
  //#endregion
2662
- //#region extensions/imessage/src/monitor/runtime.ts
2663
- function resolveRuntime(opts) {
2664
- return opts.runtime ?? createNonExitingRuntime();
2665
- }
2666
- //#endregion
2667
2619
  //#region extensions/imessage/src/monitor/self-chat-cache.ts
2668
2620
  const SELF_CHAT_TTL_MS = 1e4;
2669
2621
  const SELF_CHAT_CREATED_AT_TOLERANCE_MS = 1e3;
@@ -2832,23 +2784,6 @@ function formatIMessageInboundMediaBody(params) {
2832
2784
  notice: `[imessage ${params.unavailableCount > 1 ? `${params.unavailableCount} attachments` : "attachment"} unavailable]`
2833
2785
  });
2834
2786
  }
2835
- function resolveIMessageWatchSourceDbPath(params) {
2836
- return resolveIMessageChatDbLookupPath(params);
2837
- }
2838
- async function resolveIMessageStartupRowidWatermark(dbPath) {
2839
- let database;
2840
- try {
2841
- database = openNodeSqliteDatabase(dbPath, { readOnly: true });
2842
- const row = database.prepare("SELECT MAX(ROWID) AS maxRowid FROM message").get();
2843
- if (typeof row?.maxRowid === "number" && Number.isFinite(row.maxRowid)) return row.maxRowid;
2844
- return row?.maxRowid === null ? 0 : null;
2845
- } catch (err) {
2846
- logVerbose(`imessage: startup rowid watermark unavailable for db=${dbPath}: ${String(err)}`);
2847
- return null;
2848
- } finally {
2849
- database?.close();
2850
- }
2851
- }
2852
2787
  const warnIfImsgUpgradeNeeded = (() => {
2853
2788
  let fired = false;
2854
2789
  return { fireOnce: (rpcMethods, runtime) => {
@@ -2896,7 +2831,7 @@ async function waitForWatchSubscribeRetryDelay(params) {
2896
2831
  });
2897
2832
  }
2898
2833
  async function monitorIMessageProvider(opts = {}) {
2899
- const runtime = resolveRuntime(opts);
2834
+ const runtime = opts.runtime ?? createNonExitingRuntime();
2900
2835
  const cfg = opts.config ?? getRuntimeConfig();
2901
2836
  const readConfig = createRuntimeConfigReader(cfg);
2902
2837
  const accountInfo = resolveIMessageAccount({
@@ -2915,7 +2850,7 @@ async function monitorIMessageProvider(opts = {}) {
2915
2850
  capability: CHANNEL_APPROVAL_GATEWAY_RUNTIME_CONTEXT_CAPABILITY
2916
2851
  });
2917
2852
  const imessageCfg = accountInfo.config;
2918
- const historyLimit = Math.max(0, imessageCfg.historyLimit ?? cfg.messages?.groupChat?.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT);
2853
+ const historyLimit = resolvePromptHistoryLimit(imessageCfg.historyLimit ?? cfg.messages?.groupChat?.historyLimit);
2919
2854
  const groupHistories = /* @__PURE__ */ new Map();
2920
2855
  const sentMessageCache = createSentMessageCache();
2921
2856
  const selfChatCache = createSelfChatCache();
@@ -2966,9 +2901,24 @@ async function monitorIMessageProvider(opts = {}) {
2966
2901
  cliPath,
2967
2902
  remoteHost: imessageCfg.remoteHost
2968
2903
  });
2904
+ const sendTyping = (target, isTyping, client) => sendIMessageTyping(target, isTyping, {
2905
+ cfg,
2906
+ accountId: accountInfo.accountId,
2907
+ cliPath,
2908
+ dbPath,
2909
+ remoteHost,
2910
+ ...client ? { client } : {}
2911
+ });
2912
+ const logTypingError = (action, target, error) => logTypingFailure({
2913
+ log: logVerbose,
2914
+ channel: "imessage",
2915
+ action,
2916
+ target,
2917
+ error
2918
+ });
2969
2919
  let staleBacklogSuppressed = 0;
2970
2920
  const loggedThrottledDropDiagnostics = createIMessageThrottledDropDiagnosticCache();
2971
- const watchSourceDbPath = resolveIMessageWatchSourceDbPath({
2921
+ const watchSourceDbPath = resolveIMessageChatDbLookupPath({
2972
2922
  cliPath,
2973
2923
  dbPath,
2974
2924
  remoteHost
@@ -3087,9 +3037,8 @@ async function monitorIMessageProvider(opts = {}) {
3087
3037
  });
3088
3038
  }
3089
3039
  function resolveLiveCatchupCursor(message) {
3090
- const coalescedCursor = message.coalescedCatchupCursor;
3091
- const rowid = typeof coalescedCursor?.lastSeenRowid === "number" && Number.isFinite(coalescedCursor.lastSeenRowid) ? coalescedCursor.lastSeenRowid : typeof message.id === "number" && Number.isFinite(message.id) ? message.id : null;
3092
- const dateMs = typeof coalescedCursor?.lastSeenMs === "number" && Number.isFinite(coalescedCursor.lastSeenMs) ? coalescedCursor.lastSeenMs : typeof message.created_at === "string" ? Date.parse(message.created_at) : NaN;
3040
+ const rowid = typeof message.id === "number" && Number.isFinite(message.id) ? message.id : null;
3041
+ const dateMs = typeof message.created_at === "string" ? Date.parse(message.created_at) : NaN;
3093
3042
  if (rowid === null || !Number.isFinite(dateMs)) return null;
3094
3043
  return {
3095
3044
  lastSeenMs: dateMs,
@@ -3287,20 +3236,8 @@ async function monitorIMessageProvider(opts = {}) {
3287
3236
  const earlyDirectTypingTarget = shouldStartDirectTyping ? `${earlyDirectTypingService}:${decision.sender}` : void 0;
3288
3237
  let stopEarlyDirectTyping;
3289
3238
  if (earlyDirectTypingTarget) {
3290
- const earlyDirectTypingStarted = sendIMessageTyping(earlyDirectTypingTarget, true, {
3291
- cfg,
3292
- accountId: accountInfo.accountId,
3293
- cliPath,
3294
- dbPath,
3295
- remoteHost
3296
- }).then(() => true, (err) => {
3297
- logTypingFailure({
3298
- log: (msg) => logVerbose(msg),
3299
- channel: "imessage",
3300
- action: "start",
3301
- target: earlyDirectTypingTarget,
3302
- error: err
3303
- });
3239
+ const earlyDirectTypingStarted = sendTyping(earlyDirectTypingTarget, true).then(() => true, (err) => {
3240
+ logTypingError("start", earlyDirectTypingTarget, err);
3304
3241
  return false;
3305
3242
  });
3306
3243
  let earlyTypingStopQueued = false;
@@ -3309,21 +3246,9 @@ async function monitorIMessageProvider(opts = {}) {
3309
3246
  earlyTypingStopQueued = true;
3310
3247
  earlyDirectTypingStarted.then(async (started) => {
3311
3248
  if (!started) return;
3312
- await sendIMessageTyping(earlyDirectTypingTarget, false, {
3313
- cfg,
3314
- accountId: accountInfo.accountId,
3315
- cliPath,
3316
- dbPath,
3317
- remoteHost
3318
- });
3249
+ await sendTyping(earlyDirectTypingTarget, false);
3319
3250
  }).catch((err) => {
3320
- logTypingFailure({
3321
- log: (msg) => logVerbose(msg),
3322
- channel: "imessage",
3323
- action: "stop",
3324
- target: earlyDirectTypingTarget,
3325
- error: err
3326
- });
3251
+ logTypingError("stop", earlyDirectTypingTarget, err);
3327
3252
  });
3328
3253
  };
3329
3254
  }
@@ -3404,45 +3329,15 @@ async function monitorIMessageProvider(opts = {}) {
3404
3329
  accountId: decision.route.accountId,
3405
3330
  typing: supportsTyping && typingTarget ? {
3406
3331
  start: async () => {
3407
- await sendIMessageTyping(typingTarget, true, {
3408
- cfg,
3409
- accountId: accountInfo.accountId,
3410
- client: getActiveClient(),
3411
- cliPath,
3412
- dbPath,
3413
- remoteHost
3414
- });
3332
+ await sendTyping(typingTarget, true, getActiveClient());
3415
3333
  },
3416
3334
  stop: async () => {
3417
- await sendIMessageTyping(typingTarget, false, {
3418
- cfg,
3419
- accountId: accountInfo.accountId,
3420
- client: getActiveClient(),
3421
- cliPath,
3422
- dbPath,
3423
- remoteHost
3424
- });
3335
+ await sendTyping(typingTarget, false, getActiveClient());
3425
3336
  },
3426
3337
  keepaliveIntervalMs: IMESSAGE_TYPING_KEEPALIVE_INTERVAL_MS,
3427
3338
  maxDurationMs: IMESSAGE_TYPING_KEEPALIVE_MAX_DURATION_MS,
3428
- onStartError: (err) => {
3429
- logTypingFailure({
3430
- log: (msg) => logVerbose(msg),
3431
- channel: "imessage",
3432
- action: "start",
3433
- target: typingTarget,
3434
- error: err
3435
- });
3436
- },
3437
- onStopError: (err) => {
3438
- logTypingFailure({
3439
- log: (msg) => logVerbose(msg),
3440
- channel: "imessage",
3441
- action: "stop",
3442
- target: typingTarget,
3443
- error: err
3444
- });
3445
- }
3339
+ onStartError: (err) => logTypingError("start", typingTarget, err),
3340
+ onStopError: (err) => logTypingError("stop", typingTarget, err)
3446
3341
  } : void 0
3447
3342
  });
3448
3343
  const dispatcherOptions = {
@@ -3687,17 +3582,13 @@ async function monitorIMessageProvider(opts = {}) {
3687
3582
  else if (msg.method === "error") runtime.error?.(`imessage: watch error ${JSON.stringify(sanitizeIMessageWatchErrorPayload(msg.params))}`);
3688
3583
  }
3689
3584
  });
3690
- const requireWatchClient = (watchClient) => {
3691
- if (!watchClient) throw new Error("imessage monitor client not initialized");
3692
- return watchClient;
3693
- };
3694
3585
  for (let attempt = 1; attempt <= WATCH_SUBSCRIBE_MAX_ATTEMPTS; attempt++) {
3695
3586
  if (abort?.aborted) return;
3696
3587
  let attemptClient;
3697
3588
  let attemptDetachAbortHandler = () => {};
3698
3589
  let keepAttemptClient = false;
3699
3590
  try {
3700
- attemptClient = requireWatchClient(await createWatchClient());
3591
+ attemptClient = await createWatchClient();
3701
3592
  let attemptSubscriptionId = null;
3702
3593
  attemptDetachAbortHandler = attachIMessageMonitorAbortHandler({
3703
3594
  abortSignal: abort,