squidclaw 3.0.2 → 3.0.3

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 (388) hide show
  1. package/dist/{accounts-LA308FHj.js → accounts-CK_sHUyT.js} +2 -2
  2. package/dist/{accounts-CL_NXliB.js → accounts-CkF7YwoF.js} +17 -17
  3. package/dist/{accounts-F7tGwezI.js → accounts-DbloMfwT.js} +2 -2
  4. package/dist/{active-listener-DJv1FZqf.js → active-listener-AepfNSUY.js} +2 -2
  5. package/dist/{agents-DdixSPs3.js → agents-JnnOlm2G.js} +5 -5
  6. package/dist/{agents.config-Cn_vTN1v.js → agents.config-BeGeS2jv.js} +1 -1
  7. package/dist/{agents.config-C6KTwnde.js → agents.config-DHJBQ7uA.js} +1 -1
  8. package/dist/{plugin-sdk/api-key-rotation-DE4gr5YM.js → api-key-rotation-BHFJiYbw.js} +2 -2
  9. package/dist/{audio-preflight-AEM744TY.js → audio-preflight-BTYxAJjy.js} +32 -32
  10. package/dist/{audio-preflight-DpCWFB4z.js → audio-preflight-Dkl6Z32z.js} +4 -4
  11. package/dist/{audio-transcription-runner-CItniQDZ.js → audio-transcription-runner-DBkDgluo.js} +12 -12
  12. package/dist/{audio-transcription-runner-B2BdTEps.js → audio-transcription-runner-Gi_h5HEE.js} +1 -1
  13. package/dist/{audit-membership-runtime-w23FnNAN.js → audit-membership-runtime-DyLj-uhz.js} +4 -4
  14. package/dist/{auth-choice-7WVhiM9J.js → auth-choice-DQbCl-4F.js} +2 -2
  15. package/dist/{auth-choice-17U1cGPH.js → auth-choice-xwYK6txn.js} +2 -2
  16. package/dist/{banner-CJTrU-HC.js → banner-BxibaqUz.js} +1 -1
  17. package/dist/build-info.json +3 -3
  18. package/dist/bundled/boot-md/handler.js +51 -51
  19. package/dist/bundled/bootstrap-extra-files/handler.js +6 -6
  20. package/dist/bundled/command-logger/handler.js +2 -2
  21. package/dist/bundled/session-memory/handler.js +51 -51
  22. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  23. package/dist/{channel-activity-DPrXawu4.js → channel-activity-C5kTj83_.js} +3 -3
  24. package/dist/{channel-options-x47KAgAV.js → channel-options-BKsCYdHu.js} +1 -1
  25. package/dist/{channel-options-BM7IEY5X.js → channel-options-FdCN4cFo.js} +1 -1
  26. package/dist/{channel-web-B48pVgke.js → channel-web-BFUPrpIe.js} +1 -1
  27. package/dist/{channel-web-HM1q5FP_.js → channel-web-BkYtM8H5.js} +1 -1
  28. package/dist/{channels-cli-iPiD6449.js → channels-cli-BxhfVD-R.js} +7 -7
  29. package/dist/{channels-cli-y66ZCzYf.js → channels-cli-CZzGaGvG.js} +7 -7
  30. package/dist/{chrome-BQDCalPp.js → chrome-CAd6FQEn.js} +8 -8
  31. package/dist/{chrome-BFfAGQtd.js → chrome-pBkBuWci.js} +26 -26
  32. package/dist/cli/daemon-cli.js +1 -1
  33. package/dist/{cli-C-neGkM4.js → cli-GSev2Q95.js} +2 -2
  34. package/dist/{cli-BzpBs_KI.js → cli-bXiYaLre.js} +2 -2
  35. package/dist/{command-registry-BL80-JCV.js → command-registry-CvgCFxfY.js} +9 -9
  36. package/dist/{commands-registry-C2t2bcZ6.js → commands-registry-D6ZOTo1C.js} +4 -4
  37. package/dist/{completion-cli-CJ_L_gYr.js → completion-cli-BGM1V6EN.js} +2 -2
  38. package/dist/{completion-cli-Bi2s1mq8.js → completion-cli-OrgUDc2S.js} +1 -1
  39. package/dist/{config-cli-FhKX7MOY.js → config-cli-DbBvjvpS.js} +1 -1
  40. package/dist/{config-cli-BVpzzhoY.js → config-cli-uIP4r17f.js} +1 -1
  41. package/dist/{configure-ChiLGQo6.js → configure-BGvoAfbs.js} +6 -6
  42. package/dist/{configure-t9fm4x9H.js → configure-BOsTXjBw.js} +6 -6
  43. package/dist/{daemon-cli-DK8fQgAw.js → daemon-cli-CNi-QjEX.js} +1 -1
  44. package/dist/{daemon-cli-CO09shIt.js → daemon-cli-DN2TnjHQ.js} +1 -1
  45. package/dist/{deliver-aL8yOYS1.js → deliver-BJuiq0GS.js} +1 -1
  46. package/dist/{deliver-neVJ7AU9.js → deliver-DBXe-ZmL.js} +21 -21
  47. package/dist/{deliver-runtime-ChVR6sR3.js → deliver-runtime-DHKcNQzq.js} +3 -3
  48. package/dist/deliver-runtime-GlnBJNCj.js +36 -0
  49. package/dist/deps-send-discord.runtime-BRE0s2nz.js +26 -0
  50. package/dist/deps-send-imessage.runtime-DbIRBnmD.js +25 -0
  51. package/dist/deps-send-signal.runtime-B4h6X3o4.js +24 -0
  52. package/dist/deps-send-slack.runtime-BWXOnOxS.js +22 -0
  53. package/dist/deps-send-telegram.runtime-YvauJtgv.js +27 -0
  54. package/dist/{deps-send-whatsapp.runtime-WND2o1Mr.js → deps-send-whatsapp.runtime-BcxCalPD.js} +4 -4
  55. package/dist/deps-send-whatsapp.runtime-CslTuV47.js +60 -0
  56. package/dist/{deps-send-whatsapp.runtime-CZj97m5A.js → deps-send-whatsapp.runtime-DdxKewuy.js} +7 -7
  57. package/dist/{deps-send-whatsapp.runtime-DSbrPzxG.js → deps-send-whatsapp.runtime-Dl4ro-Df.js} +4 -4
  58. package/dist/{diagnostic-DoguEiWW.js → diagnostic-ySwZga6c.js} +2 -2
  59. package/dist/{doctor-completion-CKaQEebJ.js → doctor-completion-42wcUATu.js} +1 -1
  60. package/dist/{doctor-completion-Ctqsu6Y2.js → doctor-completion-D6RGDBD5.js} +1 -1
  61. package/dist/entry.js +2 -2
  62. package/dist/{plugin-sdk/errors-9oVz7reJ.js → errors-kkRuS2Cs.js} +1 -1
  63. package/dist/extensionAPI.js +6 -6
  64. package/dist/{fetch-DdiB5_OX.js → fetch-BLS7EMnx.js} +5 -5
  65. package/dist/{fetch-guard-CEV5qBHc.js → fetch-guard-D0fXNJls.js} +2 -2
  66. package/dist/{frontmatter-CjKtFduT.js → frontmatter-Cq1TcIQ2.js} +3 -3
  67. package/dist/{fs-safe-CwHbZdFH.js → fs-safe-BoB4X3GD.js} +4 -4
  68. package/dist/{gateway-cli-CSIyrhFg.js → gateway-cli-BbPfLLT6.js} +10 -10
  69. package/dist/{gateway-cli-xX1CTw9n.js → gateway-cli-CG3mshpO.js} +10 -10
  70. package/dist/{github-copilot-token-Cw3tAXM9.js → github-copilot-token-B5cPlwaz.js} +7 -7
  71. package/dist/{health-D9Pie2kF.js → health-CJgEuWuG.js} +1 -1
  72. package/dist/{health-D7mPTab_.js → health-dZqyhpdR.js} +1 -1
  73. package/dist/{hooks-cli-C6aI9HU7.js → hooks-cli-BD4Ww1dF.js} +3 -3
  74. package/dist/{hooks-cli-_1zdKcZA.js → hooks-cli-C0wWJOBW.js} +3 -3
  75. package/dist/{image-ecaECpjT.js → image-j_UomzVG.js} +6 -6
  76. package/dist/{image-ops-bdrMTILs.js → image-ops-CdgypS_g.js} +2 -2
  77. package/dist/image-runtime-BNh3IfMj.js +29 -0
  78. package/dist/{image-runtime-poRypm-b.js → image-runtime-SUtf9jqh.js} +3 -3
  79. package/dist/{image-DKZCmkET.js → image-sRW3RpTY.js} +1 -1
  80. package/dist/index.js +7 -7
  81. package/dist/{ir-D_GD01cg.js → ir-BvisJWXv.js} +8 -8
  82. package/dist/{legacy-names-B0wgIP0Q.js → legacy-names-aGJJuzM_.js} +1 -1
  83. package/dist/llm-slug-generator.js +51 -51
  84. package/dist/{logger-oGKcCLZ5.js → logger-CnTSBL7T.js} +7 -7
  85. package/dist/{login-gJWPqN66.js → login-BMeLPUiO.js} +5 -5
  86. package/dist/{login-qr-CgmlF7zK.js → login-qr-B2B67qqQ.js} +10 -10
  87. package/dist/{manager-CD69uguS.js → manager-DdxMYEDd.js} +13 -13
  88. package/dist/manager-runtime-BMygJEz3.js +18 -0
  89. package/dist/{model-selection-DMjtmGZP.js → model-selection-ag9BmVct.js} +43 -43
  90. package/dist/{models-BviRe-_7.js → models-BXT0s4KJ.js} +3 -3
  91. package/dist/{models-cli-BM5yo_mo.js → models-cli-BtLc9uPC.js} +3 -3
  92. package/dist/{models-cli-pvYVl1i-.js → models-cli-BwPFxWK2.js} +4 -4
  93. package/dist/{npm-resolution-DMM9Hopy.js → npm-resolution-DWpNPsBF.js} +1 -1
  94. package/dist/{npm-resolution-BTFMooVS.js → npm-resolution-Djbuzx6o.js} +1 -1
  95. package/dist/{onboard-DVuhj8ub.js → onboard-1KfKwvMR.js} +3 -3
  96. package/dist/{onboard-DTsgFKIa.js → onboard-ChxvwUze.js} +3 -3
  97. package/dist/{onboard-channels-W9UHiBQg.js → onboard-channels-CHrtFmhi.js} +2 -2
  98. package/dist/{onboard-channels-B1D9LqV_.js → onboard-channels-CXjnFvP1.js} +2 -2
  99. package/dist/{onboard-helpers-DVaF21TE.js → onboard-helpers-Bvpkyuwm.js} +6 -6
  100. package/dist/{onboard-helpers-PRhg7ZY5.js → onboard-helpers-ByttGRIZ.js} +6 -6
  101. package/dist/{onboard-remote-h-aHSDJ1.js → onboard-remote-Cfx2v9OI.js} +1 -1
  102. package/dist/{onboard-remote-DkIrV4Hx.js → onboard-remote-DxBaaS6o.js} +1 -1
  103. package/dist/{onboard-skills-fFSuiv21.js → onboard-skills-B7pHg1lN.js} +1 -1
  104. package/dist/{onboard-skills-fgrVmjJP.js → onboard-skills-PCnCZ6Od.js} +1 -1
  105. package/dist/{onboarding-D1nCnc_t.js → onboarding-D6kMb3yv.js} +7 -7
  106. package/dist/{onboarding-CYWs766P.js → onboarding-DuUMPrqA.js} +7 -7
  107. package/dist/{onboarding.finalize-Bcan6_vA.js → onboarding.finalize-KTOhO1-l.js} +7 -7
  108. package/dist/{onboarding.finalize-bAiXf9D6.js → onboarding.finalize-bphDUwZy.js} +6 -6
  109. package/dist/{onboarding.gateway-config-61E9xXYF.js → onboarding.gateway-config-DDdX0W74.js} +1 -1
  110. package/dist/{onboarding.gateway-config-Dyaqc_M7.js → onboarding.gateway-config-DNUJ0seU.js} +1 -1
  111. package/dist/{outbound-Cboz5UyH.js → outbound-DHDBvGLA.js} +6 -6
  112. package/dist/{outbound-attachment-PwEbEhAL.js → outbound-attachment-CqXiWbKN.js} +2 -2
  113. package/dist/{path-alias-guards-Cpsiv2KL.js → path-alias-guards-DORgbZ1w.js} +1 -1
  114. package/dist/{paths-CSdAWKDO.js → paths-DA5srn0U.js} +5 -5
  115. package/dist/{paths-CXClY8zC.js → paths-DSd911Oe.js} +4 -4
  116. package/dist/{pi-embedded-MktS4l8v.js → pi-embedded-BGz_qdCc.js} +24 -24
  117. package/dist/{pi-embedded-CkTlmTq8.js → pi-embedded-BP2UlUm_.js} +171 -171
  118. package/dist/{pi-embedded-helpers-DYWYzEOC.js → pi-embedded-helpers-BruaFB5l.js} +3 -3
  119. package/dist/{pi-embedded-helpers-Bfm_CvEb.js → pi-embedded-helpers-CmLnmKlb.js} +52 -52
  120. package/dist/{pi-model-discovery-DEps5Exd.js → pi-model-discovery-DAzuqPoG.js} +7 -7
  121. package/dist/pi-model-discovery-runtime-Dpu7Jm2L.js +11 -0
  122. package/dist/{pi-tools.before-tool-call.runtime-4wPdP7Br.js → pi-tools.before-tool-call.runtime-2Sp1jmlg.js} +9 -9
  123. package/dist/{plugin-registry-CvMvSI8O.js → plugin-registry-CLEhrKYA.js} +1 -1
  124. package/dist/{plugin-registry-DL2ClHLQ.js → plugin-registry-DtuxmgWx.js} +1 -1
  125. package/dist/plugin-sdk/{accounts-kr-Gz1hk.js → accounts-DghIDNk2.js} +2 -2
  126. package/dist/plugin-sdk/{accounts-CxUSDHsT.js → accounts-YTdQYQFr.js} +3 -3
  127. package/dist/plugin-sdk/{accounts-PSzw-z3S.js → accounts-h__dTrLK.js} +2 -2
  128. package/dist/plugin-sdk/{active-listener-BQNrTcR3.js → active-listener-_PRYjtJv.js} +2 -2
  129. package/dist/plugin-sdk/{api-key-rotation-Bhck7wki.js → api-key-rotation-mVDSAkKQ.js} +2 -2
  130. package/dist/plugin-sdk/{audio-preflight-_xgGaeho.js → audio-preflight-BZlQM-qX.js} +26 -26
  131. package/dist/plugin-sdk/{audio-transcription-runner-Dwc0Eh-B.js → audio-transcription-runner-CrYTX8py.js} +11 -11
  132. package/dist/plugin-sdk/{audit-membership-runtime-DHQDvH4u.js → audit-membership-runtime-Xl20kCBe.js} +2 -2
  133. package/dist/plugin-sdk/{channel-activity-XajEg_DL.js → channel-activity-gwxRn4wF.js} +3 -3
  134. package/dist/plugin-sdk/{channel-web-KtqCp4mz.js → channel-web-1WF-Nabe.js} +18 -18
  135. package/dist/plugin-sdk/{chrome-diV5m81I.js → chrome-BXbYwXRH.js} +6 -6
  136. package/dist/plugin-sdk/{commands-registry-DwZAJuut.js → commands-registry-0w-aZenK.js} +4 -4
  137. package/dist/plugin-sdk/{common-CqnO92P8.js → common-DBOCt6Yv.js} +2 -2
  138. package/dist/plugin-sdk/{config-DYbtdrsT.js → config-pRtEoVyZ.js} +7 -7
  139. package/dist/plugin-sdk/{deliver-DG_7Uagn.js → deliver-FjlJrtZk.js} +10 -10
  140. package/dist/plugin-sdk/deliver-runtime-DEzvpBW1.js +32 -0
  141. package/dist/plugin-sdk/deps-send-discord.runtime-Bhusa_Hi.js +23 -0
  142. package/dist/plugin-sdk/deps-send-imessage.runtime-bmakPm5f.js +22 -0
  143. package/dist/plugin-sdk/deps-send-signal.runtime-n00sfFto.js +21 -0
  144. package/dist/plugin-sdk/deps-send-slack.runtime-BvM3Z-Mr.js +19 -0
  145. package/dist/plugin-sdk/deps-send-telegram.runtime-CPuMkcmo.js +24 -0
  146. package/dist/plugin-sdk/deps-send-whatsapp.runtime-BzO6S-KX.js +57 -0
  147. package/dist/plugin-sdk/{diagnostic-CT7v_kM2.js → diagnostic-Dt2i3afe.js} +2 -2
  148. package/dist/plugin-sdk/{errors-B8oJXuCF.js → errors-CgRPdp3o.js} +1 -1
  149. package/dist/plugin-sdk/{fetch-guard-Or5BCq0E.js → fetch-guard-DyPZh8r2.js} +2 -2
  150. package/dist/plugin-sdk/{fs-safe-DFbwq9CS.js → fs-safe-DqCO1D4C.js} +3 -3
  151. package/dist/plugin-sdk/{image-rycGCqJO.js → image-CQ9TZ9vq.js} +6 -6
  152. package/dist/plugin-sdk/{image-ops-CMsocOob.js → image-ops-sw0uZ0GN.js} +2 -2
  153. package/dist/plugin-sdk/image-runtime-17_mTqsy.js +25 -0
  154. package/dist/plugin-sdk/index.js +50 -50
  155. package/dist/plugin-sdk/{ir-DihI2SIz.js → ir-BVZ5kUMb.js} +7 -7
  156. package/dist/plugin-sdk/{local-roots-1xVosTZ4.js → local-roots-fO3ZgW3G.js} +4 -4
  157. package/dist/plugin-sdk/{logger-Bg4vIUJn.js → logger-DIb2cGHp.js} +2 -2
  158. package/dist/plugin-sdk/{login-YhFrVUWo.js → login-Dg5cxB_3.js} +4 -4
  159. package/dist/plugin-sdk/{login-qr-SpUTuwYv.js → login-qr-C3Vn30cq.js} +5 -5
  160. package/dist/plugin-sdk/{manager-DrzOPeMD.js → manager-BR-TwWTH.js} +8 -8
  161. package/dist/plugin-sdk/manager-runtime-CvI9wF8N.js +15 -0
  162. package/dist/plugin-sdk/{outbound-Cc4cUn9K.js → outbound-1a3Z_QJ2.js} +5 -5
  163. package/dist/plugin-sdk/{outbound-attachment-Dtp3hQgc.js → outbound-attachment-BTQjD4YE.js} +2 -2
  164. package/dist/plugin-sdk/{path-alias-guards-DA0MhfkG.js → path-alias-guards-TnxupPQC.js} +1 -1
  165. package/dist/plugin-sdk/{paths-CP67O8eN.js → paths-B7_75Pdr.js} +1 -1
  166. package/dist/plugin-sdk/{pi-embedded-helpers-BDJ_4Plh.js → pi-embedded-helpers-DZRNadD8.js} +16 -16
  167. package/dist/plugin-sdk/{pi-model-discovery-Mk0GTDJl.js → pi-model-discovery-DGh6xekX.js} +1 -1
  168. package/dist/plugin-sdk/pi-model-discovery-runtime-DjjBdPYt.js +8 -0
  169. package/dist/plugin-sdk/{pi-tools.before-tool-call.runtime-DV72wTDb.js → pi-tools.before-tool-call.runtime-BZ9XgG_x.js} +4 -4
  170. package/dist/plugin-sdk/{plugins-DSs2-fnK.js → plugins-B8pWVYug.js} +4 -4
  171. package/dist/plugin-sdk/{proxy-env-Ib4-LUh-.js → proxy-env-BOlkiW1-.js} +1 -1
  172. package/dist/plugin-sdk/{proxy-fetch-ZPEvp58f.js → proxy-fetch-Dt5BedH8.js} +1 -1
  173. package/dist/plugin-sdk/{pw-ai-DIx2wpkY.js → pw-ai-C17A1o4w.js} +9 -9
  174. package/dist/plugin-sdk/{qmd-manager-Ov9ElEfG.js → qmd-manager-Bei6TaFq.js} +7 -7
  175. package/dist/plugin-sdk/{query-expansion-CzjwW461.js → query-expansion-POz2za8a.js} +4 -4
  176. package/dist/plugin-sdk/{redact-BoNEjbpF.js → redact-9WsNyb7S.js} +1 -1
  177. package/dist/plugin-sdk/{reply-CWWUd_JS.js → reply-BFbijn6_.js} +73 -73
  178. package/dist/plugin-sdk/{resolve-outbound-target-BOkvxZtM.js → resolve-outbound-target-B9iFEh0y.js} +2 -2
  179. package/dist/plugin-sdk/{run-with-concurrency-kVooFCVo.js → run-with-concurrency-DmTrN5JG.js} +1 -1
  180. package/dist/plugin-sdk/runtime-whatsapp-login.runtime-DzhkSmLi.js +10 -0
  181. package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-DyILWezU.js +19 -0
  182. package/dist/plugin-sdk/{send-BP1fSEBR.js → send-BGZo6HW1.js} +5 -5
  183. package/dist/plugin-sdk/{send-D9CSOGul.js → send-BisREGBZ.js} +6 -6
  184. package/dist/plugin-sdk/{send-BeLBlAsQ.js → send-BqkUDZed.js} +13 -13
  185. package/dist/plugin-sdk/{send-DLKxJJYV.js → send-D6_nNvi0.js} +8 -8
  186. package/dist/plugin-sdk/{send-XZ6IXCtL.js → send-Dj7XEcZN.js} +7 -7
  187. package/dist/plugin-sdk/{session-DtLUYWvY.js → session-D4KDs7Hq.js} +3 -3
  188. package/dist/plugin-sdk/{skill-commands-Bv7EZypt.js → skill-commands-D_xeseiI.js} +4 -4
  189. package/dist/plugin-sdk/{skills-BzXN4uev.js → skills-Bs2b3JfV.js} +6 -6
  190. package/dist/plugin-sdk/slash-commands.runtime-CUb5sqqf.js +13 -0
  191. package/dist/plugin-sdk/slash-dispatch.runtime-DCB6bGjB.js +52 -0
  192. package/dist/plugin-sdk/slash-skill-commands.runtime-BqEweE4K.js +16 -0
  193. package/dist/plugin-sdk/{store-DnJhFFW5.js → store-B7ESm9_L.js} +2 -2
  194. package/dist/plugin-sdk/subagent-registry-runtime-CCUW4SbM.js +52 -0
  195. package/dist/plugin-sdk/{tables-CpmqssLF.js → tables-1vhBJPK_.js} +1 -1
  196. package/dist/plugin-sdk/{thinking-1UCPuD9d.js → thinking-DjaClmzi.js} +7 -7
  197. package/dist/plugin-sdk/{tokens-DAL_5WHL.js → tokens-CLE20fRI.js} +1 -1
  198. package/dist/plugin-sdk/{tool-images-RX4QTMnt.js → tool-images-B95xcwiR.js} +2 -2
  199. package/dist/plugin-sdk/web-DeRmHQ4_.js +56 -0
  200. package/dist/plugin-sdk/{whatsapp-actions-BF6ih4Gi.js → whatsapp-actions-BYpcWkTN.js} +17 -17
  201. package/dist/plugin-sdk/whatsapp.js +50 -50
  202. package/dist/{plugins-CmdmAU0K.js → plugins-DXkm70nK.js} +11 -11
  203. package/dist/{plugins-cli-DBtLtIsQ.js → plugins-cli-Cs3UUJew.js} +3 -3
  204. package/dist/{plugins-cli-BMPvpwSo.js → plugins-cli-KPz6APX0.js} +3 -3
  205. package/dist/{program-context-KSeqVkRM.js → program-context-J_FyEsaS.js} +18 -18
  206. package/dist/{program-C6sTShRB.js → program-xNEHPhT8.js} +8 -8
  207. package/dist/{prompt-select-styled-Ba5fC0g1.js → prompt-select-styled-B1LjjgQ0.js} +5 -5
  208. package/dist/{prompt-select-styled-DFhJPiqx.js → prompt-select-styled-BRiogP_P.js} +5 -5
  209. package/dist/{provider-auth-helpers-S2rdI85T.js → provider-auth-helpers-CxUWqt95.js} +1 -1
  210. package/dist/{provider-auth-helpers-BPvZ8xkJ.js → provider-auth-helpers-hhFVhZdv.js} +1 -1
  211. package/dist/{proxy-env-QUJz9VEJ.js → proxy-env-D75CWSOo.js} +1 -1
  212. package/dist/{proxy-fetch-C2v-Utgg.js → proxy-fetch-lH6RsRTE.js} +1 -1
  213. package/dist/{push-apns-BQEPMPtG.js → push-apns-BBkpZyNR.js} +1 -1
  214. package/dist/{push-apns-CGibQhps.js → push-apns-BQjV_93G.js} +1 -1
  215. package/dist/{pw-ai-SYjuzbV6.js → pw-ai-7kHgUGj0.js} +14 -14
  216. package/dist/{pw-ai-zFPBSxaL.js → pw-ai-BmGrTicP.js} +1 -1
  217. package/dist/{qmd-manager-CO-shcLU.js → qmd-manager-BN0siR2Z.js} +10 -10
  218. package/dist/{query-expansion-DlQOkf-g.js → query-expansion-Dzxt6kXo.js} +6 -6
  219. package/dist/{redact-NmPEVjIo.js → redact-DvzicBMu.js} +1 -1
  220. package/dist/{register.agent-DP_2xCaO.js → register.agent-DYq06QHS.js} +8 -8
  221. package/dist/{register.agent-BwhWwpRX.js → register.agent-reU63wQ5.js} +7 -7
  222. package/dist/{register.configure-D8TE-yQn.js → register.configure-C4p9ad2q.js} +10 -10
  223. package/dist/{register.configure-C5i661J4.js → register.configure-DezZ4Q1p.js} +10 -10
  224. package/dist/{register.maintenance-BS2i3S5V.js → register.maintenance-CTvFmkAm.js} +9 -9
  225. package/dist/{register.maintenance-BA4UOg2_.js → register.maintenance-CzMKTC2a.js} +8 -8
  226. package/dist/{register.message-oFI2Mzrd.js → register.message-BmsovYS6.js} +3 -3
  227. package/dist/{register.message-D9hVI5b6.js → register.message-Bp4SDXWk.js} +3 -3
  228. package/dist/{register.onboard-D6wqijOl.js → register.onboard-C39xhpv1.js} +3 -3
  229. package/dist/{register.onboard-OaKr3SnU.js → register.onboard-DZt2kSAg.js} +3 -3
  230. package/dist/{register.setup-DsK_7zih.js → register.setup-04L_8wfA.js} +3 -3
  231. package/dist/{register.setup-Dygx-glo.js → register.setup-DWctFmOd.js} +3 -3
  232. package/dist/{register.status-health-sessions-C6VfEhho.js → register.status-health-sessions-CBPZoj51.js} +4 -4
  233. package/dist/{register.status-health-sessions-BmWcbWPR.js → register.status-health-sessions-N6SFc-UY.js} +4 -4
  234. package/dist/{register.subclis-CLf32krW.js → register.subclis-C3TphbCF.js} +10 -10
  235. package/dist/{reply-ZWkzBiSb.js → reply-CB1p166g.js} +5 -5
  236. package/dist/{run-main-asKkGUqy.js → run-main-7tknx04F.js} +15 -15
  237. package/dist/{run-with-concurrency-FczpX8ng.js → run-with-concurrency-BFR3ReeF.js} +4 -4
  238. package/dist/runtime-whatsapp-login.runtime-DSR-m0FW.js +13 -0
  239. package/dist/runtime-whatsapp-outbound.runtime-Blywd_bv.js +22 -0
  240. package/dist/{send-oS3t6gE6.js → send-C98RfcAb.js} +5 -5
  241. package/dist/{send-DX_O1OHH.js → send-Co5Bqwuo.js} +6 -6
  242. package/dist/{send-BNsV-D2Y.js → send-DjL7KlMV.js} +8 -8
  243. package/dist/{send-C-jb8X9I.js → send-Do7hKDL9.js} +7 -7
  244. package/dist/{send-D-Rnbdzz.js → send-bW7jDv8D.js} +26 -26
  245. package/dist/{server-node-events-DV2yeAp-.js → server-node-events-Ctjzvlem.js} +3 -3
  246. package/dist/{server-node-events-BHv7a_ll.js → server-node-events-DrCKK0J4.js} +3 -3
  247. package/dist/{session-DRyURckG.js → session-QSn69XeJ.js} +8 -8
  248. package/dist/{skill-commands-BrlAf_CG.js → skill-commands-Bi_jchJn.js} +9 -9
  249. package/dist/{skills-DWrRJwa-.js → skills-CTV78w4q.js} +22 -22
  250. package/dist/slash-commands.runtime-63MUmCBt.js +16 -0
  251. package/dist/{slash-dispatch.runtime-DkcAYuyK.js → slash-dispatch.runtime-BL3qA1O3.js} +6 -6
  252. package/dist/{slash-dispatch.runtime-BJOuQOeN.js → slash-dispatch.runtime-DRGqAgwa.js} +2 -2
  253. package/dist/slash-dispatch.runtime-Dh2L_3Tg.js +56 -0
  254. package/dist/{slash-dispatch.runtime-CEAbkOCI.js → slash-dispatch.runtime-uqWhoI6q.js} +2 -2
  255. package/dist/slash-skill-commands.runtime-B3MSSAQ-.js +20 -0
  256. package/dist/{status-Ck8-aQIF.js → status-BkfSGlOi.js} +3 -3
  257. package/dist/{status-CMhW6nGs.js → status-DdW571-j.js} +3 -3
  258. package/dist/{store-BFNH5fXG.js → store-B89Hj8Ub.js} +2 -2
  259. package/dist/{subagent-registry-DQpeidFk.js → subagent-registry-DGrfQVN3.js} +5 -5
  260. package/dist/subagent-registry-runtime-BRNDawlJ.js +56 -0
  261. package/dist/{subagent-registry-runtime-C-jjppV6.js → subagent-registry-runtime-DatTO2LD.js} +2 -2
  262. package/dist/{subagent-registry-runtime-tRRyFZL8.js → subagent-registry-runtime-Dsrz3yIh.js} +2 -2
  263. package/dist/{subagent-registry-runtime-BlRAnw80.js → subagent-registry-runtime-MtjBCcgn.js} +6 -6
  264. package/dist/{subsystem-BaLYRf7D.js → subsystem-6v7sWnAD.js} +14 -14
  265. package/dist/{tables-CnlmCLb3.js → tables-DGHzaXQz.js} +1 -1
  266. package/dist/{target-errors-Df1wB-I7.js → target-errors-CweAa7L9.js} +2 -2
  267. package/dist/{thinking-CTpcVnlx.js → thinking-SdNGqtJE.js} +7 -7
  268. package/dist/{tokens-D2XhLqIz.js → tokens-DfbMVF9y.js} +1 -1
  269. package/dist/{tool-images-CElPu2en.js → tool-images-8BKrL7Bn.js} +2 -2
  270. package/dist/{update-cli-5KzuA6pa.js → update-cli-0UiUaT3q.js} +10 -10
  271. package/dist/{update-cli-CEghYBNP.js → update-cli-C-uyQcFS.js} +9 -9
  272. package/dist/{update-runner-C5XgCwj2.js → update-runner-CT9YRLtn.js} +1 -1
  273. package/dist/{update-runner-C0q8aGFd.js → update-runner-CqVLeGYA.js} +1 -1
  274. package/dist/{web-DBm_uXOl.js → web-B2qXyOb9.js} +3 -3
  275. package/dist/{web-DdrUn13G.js → web-B7kbCskR.js} +55 -55
  276. package/dist/{web-DddJa7ZT.js → web-D1ZoRVB0.js} +6 -6
  277. package/dist/{web-O2WkG3cH.js → web-FqoNMI-k.js} +3 -3
  278. package/dist/{whatsapp-actions-DPszRJ8b.js → whatsapp-actions-BDkbnZVH.js} +21 -21
  279. package/dist/{workspace-TqfVSQuO.js → workspace-kVMIaBrV.js} +20 -20
  280. package/package.json +1 -1
  281. package/dist/api-key-rotation-Dzvqp3Dc.js +0 -181
  282. package/dist/deliver-runtime-BdUlqV9E.js +0 -36
  283. package/dist/deps-send-discord.runtime-R8jUd_2I.js +0 -26
  284. package/dist/deps-send-imessage.runtime-Die0aWtU.js +0 -25
  285. package/dist/deps-send-signal.runtime-Biux_4v4.js +0 -24
  286. package/dist/deps-send-slack.runtime-CkUST2Ky.js +0 -22
  287. package/dist/deps-send-telegram.runtime-CIN5ILBe.js +0 -27
  288. package/dist/deps-send-whatsapp.runtime-DUff9bWS.js +0 -60
  289. package/dist/errors-DfgAh2Ml.js +0 -54
  290. package/dist/image-runtime-irHu11-U.js +0 -29
  291. package/dist/manager-runtime-BISxj7HK.js +0 -18
  292. package/dist/pi-model-discovery-runtime-bzJViQLK.js +0 -11
  293. package/dist/plugin-sdk/accounts-BNuRM3rG.js +0 -288
  294. package/dist/plugin-sdk/accounts-CGTYP7Rh.js +0 -46
  295. package/dist/plugin-sdk/accounts-CcS9IAhD.js +0 -35
  296. package/dist/plugin-sdk/active-listener-CTsLn1AX.js +0 -50
  297. package/dist/plugin-sdk/audio-preflight-CRGLqp-g.js +0 -69
  298. package/dist/plugin-sdk/audio-transcription-runner-RXsskMMk.js +0 -2176
  299. package/dist/plugin-sdk/audit-membership-runtime-B9b-zRwg.js +0 -58
  300. package/dist/plugin-sdk/channel-activity-gPvD1D7S.js +0 -94
  301. package/dist/plugin-sdk/channel-web-LGl1zPJt.js +0 -2256
  302. package/dist/plugin-sdk/chrome-9Y_LcUg1.js +0 -2415
  303. package/dist/plugin-sdk/commands-registry-CcdEPxVg.js +0 -1125
  304. package/dist/plugin-sdk/config-CrQ5bCrw.js +0 -17912
  305. package/dist/plugin-sdk/deliver-D3xr5AkB.js +0 -1694
  306. package/dist/plugin-sdk/deliver-runtime-B79ZQu69.js +0 -32
  307. package/dist/plugin-sdk/deliver-runtime-BdTC7uKE.js +0 -32
  308. package/dist/plugin-sdk/deps-send-discord.runtime-BOQZIqC8.js +0 -23
  309. package/dist/plugin-sdk/deps-send-discord.runtime-CObCNMt3.js +0 -23
  310. package/dist/plugin-sdk/deps-send-imessage.runtime-CuHOc9Ka.js +0 -22
  311. package/dist/plugin-sdk/deps-send-imessage.runtime-DlWgi2DH.js +0 -22
  312. package/dist/plugin-sdk/deps-send-signal.runtime-Cz7FT8J8.js +0 -21
  313. package/dist/plugin-sdk/deps-send-signal.runtime-iPynghkE.js +0 -21
  314. package/dist/plugin-sdk/deps-send-slack.runtime-D4vDoRsg.js +0 -19
  315. package/dist/plugin-sdk/deps-send-slack.runtime-DNTbE5jS.js +0 -19
  316. package/dist/plugin-sdk/deps-send-telegram.runtime-7CR-xtCF.js +0 -24
  317. package/dist/plugin-sdk/deps-send-telegram.runtime-DjTVED_m.js +0 -24
  318. package/dist/plugin-sdk/deps-send-whatsapp.runtime-CRWOIKRC.js +0 -57
  319. package/dist/plugin-sdk/deps-send-whatsapp.runtime-bUi8kghi.js +0 -57
  320. package/dist/plugin-sdk/diagnostic-BXkLYs_9.js +0 -319
  321. package/dist/plugin-sdk/fetch-guard-C55uvn27.js +0 -156
  322. package/dist/plugin-sdk/fs-safe-Dqmpk-Fr.js +0 -352
  323. package/dist/plugin-sdk/image-3xW7IJdq.js +0 -2310
  324. package/dist/plugin-sdk/image-ops-BjK2qZZn.js +0 -584
  325. package/dist/plugin-sdk/image-runtime-CZZJJqcW.js +0 -25
  326. package/dist/plugin-sdk/image-runtime-Cjz368oj.js +0 -25
  327. package/dist/plugin-sdk/ir-CS7uuQhN.js +0 -1296
  328. package/dist/plugin-sdk/local-roots-DmOKwiNW.js +0 -186
  329. package/dist/plugin-sdk/logger-DDdrdbDu.js +0 -1163
  330. package/dist/plugin-sdk/login-BSEeU27Y.js +0 -57
  331. package/dist/plugin-sdk/login-qr-BwWJsDSj.js +0 -320
  332. package/dist/plugin-sdk/manager-DiXPCubI.js +0 -3917
  333. package/dist/plugin-sdk/manager-runtime-CF55pBNe.js +0 -15
  334. package/dist/plugin-sdk/manager-runtime-Ct0m9UJC.js +0 -15
  335. package/dist/plugin-sdk/outbound-attachment-BoFx05zw.js +0 -19
  336. package/dist/plugin-sdk/outbound-cpqK1GFe.js +0 -212
  337. package/dist/plugin-sdk/path-alias-guards-gBhrAn14.js +0 -43
  338. package/dist/plugin-sdk/paths-C6W4VHoa.js +0 -166
  339. package/dist/plugin-sdk/pi-embedded-helpers-C-B9B6Sp.js +0 -9627
  340. package/dist/plugin-sdk/pi-model-discovery-BGEeoPzN.js +0 -134
  341. package/dist/plugin-sdk/pi-model-discovery-runtime-BHZ_Htob.js +0 -8
  342. package/dist/plugin-sdk/pi-model-discovery-runtime-BrwtJHPU.js +0 -8
  343. package/dist/plugin-sdk/pi-tools.before-tool-call.runtime-ByN_xThw.js +0 -354
  344. package/dist/plugin-sdk/plugins-D5cdn70e.js +0 -864
  345. package/dist/plugin-sdk/proxy-fetch-Cf3IUSDw.js +0 -38
  346. package/dist/plugin-sdk/pw-ai-C_QOIuin.js +0 -1938
  347. package/dist/plugin-sdk/qmd-manager-6bozlfFg.js +0 -1448
  348. package/dist/plugin-sdk/query-expansion-eeVz_aEm.js +0 -1011
  349. package/dist/plugin-sdk/redact-DfACyt0X.js +0 -319
  350. package/dist/plugin-sdk/reply-CQUX_haM.js +0 -98828
  351. package/dist/plugin-sdk/resolve-outbound-target-Dbz0O8cR.js +0 -40
  352. package/dist/plugin-sdk/run-with-concurrency-5DMu9szx.js +0 -1994
  353. package/dist/plugin-sdk/runtime-whatsapp-login.runtime-DitS0I1z.js +0 -10
  354. package/dist/plugin-sdk/runtime-whatsapp-login.runtime-OthrtsLL.js +0 -10
  355. package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-CYCr6A3v.js +0 -19
  356. package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-Q2HL0zL3.js +0 -19
  357. package/dist/plugin-sdk/send-BACEu1Un.js +0 -414
  358. package/dist/plugin-sdk/send-BU4OoR7u.js +0 -2587
  359. package/dist/plugin-sdk/send-DbxOJ_BC.js +0 -3135
  360. package/dist/plugin-sdk/send-n932vjT5.js +0 -540
  361. package/dist/plugin-sdk/send-uCPS53j8.js +0 -503
  362. package/dist/plugin-sdk/session-DenDKR_-.js +0 -169
  363. package/dist/plugin-sdk/skill-commands-BK1KDKmS.js +0 -342
  364. package/dist/plugin-sdk/skills-D4am-zkO.js +0 -1428
  365. package/dist/plugin-sdk/slash-commands.runtime-Bx1K1iqP.js +0 -13
  366. package/dist/plugin-sdk/slash-commands.runtime-DWfFqMZw.js +0 -13
  367. package/dist/plugin-sdk/slash-dispatch.runtime-DVn338JI.js +0 -52
  368. package/dist/plugin-sdk/slash-dispatch.runtime-pnWH5AjM.js +0 -52
  369. package/dist/plugin-sdk/slash-skill-commands.runtime-Dbi_YzPO.js +0 -16
  370. package/dist/plugin-sdk/slash-skill-commands.runtime-DxvNWv_E.js +0 -16
  371. package/dist/plugin-sdk/ssrf-2WBi1Tzx.js +0 -202
  372. package/dist/plugin-sdk/store-BKDMuvyn.js +0 -81
  373. package/dist/plugin-sdk/subagent-registry-runtime-FhP0l-Rw.js +0 -52
  374. package/dist/plugin-sdk/subagent-registry-runtime-hH9ADku1.js +0 -52
  375. package/dist/plugin-sdk/tables-CrDYcv_b.js +0 -55
  376. package/dist/plugin-sdk/target-errors-aOwE-MIU.js +0 -195
  377. package/dist/plugin-sdk/thinking-D41FMh9T.js +0 -1206
  378. package/dist/plugin-sdk/tokens-CTIYTLWu.js +0 -52
  379. package/dist/plugin-sdk/tool-images-CWc54lpI.js +0 -274
  380. package/dist/plugin-sdk/web-AtEy-48y.js +0 -56
  381. package/dist/plugin-sdk/web-DjKONHqF.js +0 -56
  382. package/dist/plugin-sdk/whatsapp-actions-DEZcm_CZ.js +0 -80
  383. package/dist/runtime-whatsapp-login.runtime-BqOsE5As.js +0 -13
  384. package/dist/runtime-whatsapp-outbound.runtime-D5S6mxFT.js +0 -22
  385. package/dist/slash-commands.runtime-JqCsKeu2.js +0 -16
  386. package/dist/slash-dispatch.runtime-h9I6EDYB.js +0 -56
  387. package/dist/slash-skill-commands.runtime-C0QZlkpu.js +0 -20
  388. package/dist/subagent-registry-runtime-BxvwRp_3.js +0 -56
@@ -1,1694 +0,0 @@
1
- import { ot as normalizeAccountId, st as normalizeOptionalAccountId } from "./run-with-concurrency-5DMu9szx.js";
2
- import { c as resolveStateDir } from "./paths-8xF5kDne.js";
3
- import { Et as getActivePluginRegistryVersion, It as createInternalHookEvent, Lt as triggerInternalHook, wt as getActivePluginRegistry } from "./config-CrQ5bCrw.js";
4
- import { L as logVerbose, a as createSubsystemLogger } from "./logger-DDdrdbDu.js";
5
- import { d as getChannelDock } from "./thinking-D41FMh9T.js";
6
- import { Ft as parseInlineDirectives, ht as resolveMirroredTranscriptText, i as isMessagingToolDuplicate, mt as appendAssistantMessageToSessionTranscript } from "./pi-embedded-helpers-C-B9B6Sp.js";
7
- import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-D5cdn70e.js";
8
- import { t as getAgentScopedMediaLocalRoots } from "./local-roots-DmOKwiNW.js";
9
- import { c as chunkMarkdownTextWithMode, d as resolveChunkMode, f as resolveTextChunkLimit, g as parseFenceSpans, i as resolveMarkdownTableMode, o as chunkByParagraph } from "./ir-CS7uuQhN.js";
10
- import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN } from "./tokens-CTIYTLWu.js";
11
- import { r as parseTelegramTarget } from "./targets-D46Aqz9j.js";
12
- import { n as generateSecureUuid } from "./secure-random-IkuYAMEf.js";
13
- import { c as markdownToSignalTextChunks, t as sendMessageSignal } from "./send-n932vjT5.js";
14
- import fs from "node:fs";
15
- import path from "node:path";
16
-
17
- //#region src/channels/plugins/media-limits.ts
18
- const MB = 1024 * 1024;
19
- function resolveChannelMediaMaxBytes(params) {
20
- const accountId = normalizeAccountId(params.accountId);
21
- const channelLimit = params.resolveChannelLimitMb({
22
- cfg: params.cfg,
23
- accountId
24
- });
25
- if (channelLimit) return channelLimit * MB;
26
- if (params.cfg.agents?.defaults?.mediaMaxMb) return params.cfg.agents.defaults.mediaMaxMb * MB;
27
- }
28
-
29
- //#endregion
30
- //#region src/plugins/hooks.ts
31
- /**
32
- * Get hooks for a specific hook name, sorted by priority (higher first).
33
- */
34
- function getHooksForName(registry, hookName) {
35
- return registry.typedHooks.filter((h) => h.hookName === hookName).toSorted((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
36
- }
37
- /**
38
- * Create a hook runner for a specific registry.
39
- */
40
- function createHookRunner(registry, options = {}) {
41
- const logger = options.logger;
42
- const catchErrors = options.catchErrors ?? true;
43
- const mergeBeforeModelResolve = (acc, next) => ({
44
- modelOverride: acc?.modelOverride ?? next.modelOverride,
45
- providerOverride: acc?.providerOverride ?? next.providerOverride
46
- });
47
- const mergeBeforePromptBuild = (acc, next) => ({
48
- systemPrompt: next.systemPrompt ?? acc?.systemPrompt,
49
- prependContext: acc?.prependContext && next.prependContext ? `${acc.prependContext}\n\n${next.prependContext}` : next.prependContext ?? acc?.prependContext
50
- });
51
- const mergeSubagentSpawningResult = (acc, next) => {
52
- if (acc?.status === "error") return acc;
53
- if (next.status === "error") return next;
54
- return {
55
- status: "ok",
56
- threadBindingReady: Boolean(acc?.threadBindingReady || next.threadBindingReady)
57
- };
58
- };
59
- const mergeSubagentDeliveryTargetResult = (acc, next) => {
60
- if (acc?.origin) return acc;
61
- return next;
62
- };
63
- const handleHookError = (params) => {
64
- const msg = `[hooks] ${params.hookName} handler from ${params.pluginId} failed: ${String(params.error)}`;
65
- if (catchErrors) {
66
- logger?.error(msg);
67
- return;
68
- }
69
- throw new Error(msg, { cause: params.error });
70
- };
71
- /**
72
- * Run a hook that doesn't return a value (fire-and-forget style).
73
- * All handlers are executed in parallel for performance.
74
- */
75
- async function runVoidHook(hookName, event, ctx) {
76
- const hooks = getHooksForName(registry, hookName);
77
- if (hooks.length === 0) return;
78
- logger?.debug?.(`[hooks] running ${hookName} (${hooks.length} handlers)`);
79
- const promises = hooks.map(async (hook) => {
80
- try {
81
- await hook.handler(event, ctx);
82
- } catch (err) {
83
- handleHookError({
84
- hookName,
85
- pluginId: hook.pluginId,
86
- error: err
87
- });
88
- }
89
- });
90
- await Promise.all(promises);
91
- }
92
- /**
93
- * Run a hook that can return a modifying result.
94
- * Handlers are executed sequentially in priority order, and results are merged.
95
- */
96
- async function runModifyingHook(hookName, event, ctx, mergeResults) {
97
- const hooks = getHooksForName(registry, hookName);
98
- if (hooks.length === 0) return;
99
- logger?.debug?.(`[hooks] running ${hookName} (${hooks.length} handlers, sequential)`);
100
- let result;
101
- for (const hook of hooks) try {
102
- const handlerResult = await hook.handler(event, ctx);
103
- if (handlerResult !== void 0 && handlerResult !== null) if (mergeResults && result !== void 0) result = mergeResults(result, handlerResult);
104
- else result = handlerResult;
105
- } catch (err) {
106
- handleHookError({
107
- hookName,
108
- pluginId: hook.pluginId,
109
- error: err
110
- });
111
- }
112
- return result;
113
- }
114
- /**
115
- * Run before_model_resolve hook.
116
- * Allows plugins to override provider/model before model resolution.
117
- */
118
- async function runBeforeModelResolve(event, ctx) {
119
- return runModifyingHook("before_model_resolve", event, ctx, mergeBeforeModelResolve);
120
- }
121
- /**
122
- * Run before_prompt_build hook.
123
- * Allows plugins to inject context and system prompt before prompt submission.
124
- */
125
- async function runBeforePromptBuild(event, ctx) {
126
- return runModifyingHook("before_prompt_build", event, ctx, mergeBeforePromptBuild);
127
- }
128
- /**
129
- * Run before_agent_start hook.
130
- * Legacy compatibility hook that combines model resolve + prompt build phases.
131
- */
132
- async function runBeforeAgentStart(event, ctx) {
133
- return runModifyingHook("before_agent_start", event, ctx, (acc, next) => ({
134
- ...mergeBeforePromptBuild(acc, next),
135
- ...mergeBeforeModelResolve(acc, next)
136
- }));
137
- }
138
- /**
139
- * Run agent_end hook.
140
- * Allows plugins to analyze completed conversations.
141
- * Runs in parallel (fire-and-forget).
142
- */
143
- async function runAgentEnd(event, ctx) {
144
- return runVoidHook("agent_end", event, ctx);
145
- }
146
- /**
147
- * Run llm_input hook.
148
- * Allows plugins to observe the exact input payload sent to the LLM.
149
- * Runs in parallel (fire-and-forget).
150
- */
151
- async function runLlmInput(event, ctx) {
152
- return runVoidHook("llm_input", event, ctx);
153
- }
154
- /**
155
- * Run llm_output hook.
156
- * Allows plugins to observe the exact output payload returned by the LLM.
157
- * Runs in parallel (fire-and-forget).
158
- */
159
- async function runLlmOutput(event, ctx) {
160
- return runVoidHook("llm_output", event, ctx);
161
- }
162
- /**
163
- * Run before_compaction hook.
164
- */
165
- async function runBeforeCompaction(event, ctx) {
166
- return runVoidHook("before_compaction", event, ctx);
167
- }
168
- /**
169
- * Run after_compaction hook.
170
- */
171
- async function runAfterCompaction(event, ctx) {
172
- return runVoidHook("after_compaction", event, ctx);
173
- }
174
- /**
175
- * Run before_reset hook.
176
- * Fired when /new or /reset clears a session, before messages are lost.
177
- * Runs in parallel (fire-and-forget).
178
- */
179
- async function runBeforeReset(event, ctx) {
180
- return runVoidHook("before_reset", event, ctx);
181
- }
182
- /**
183
- * Run message_received hook.
184
- * Runs in parallel (fire-and-forget).
185
- */
186
- async function runMessageReceived(event, ctx) {
187
- return runVoidHook("message_received", event, ctx);
188
- }
189
- /**
190
- * Run message_sending hook.
191
- * Allows plugins to modify or cancel outgoing messages.
192
- * Runs sequentially.
193
- */
194
- async function runMessageSending(event, ctx) {
195
- return runModifyingHook("message_sending", event, ctx, (acc, next) => ({
196
- content: next.content ?? acc?.content,
197
- cancel: next.cancel ?? acc?.cancel
198
- }));
199
- }
200
- /**
201
- * Run message_sent hook.
202
- * Runs in parallel (fire-and-forget).
203
- */
204
- async function runMessageSent(event, ctx) {
205
- return runVoidHook("message_sent", event, ctx);
206
- }
207
- /**
208
- * Run before_tool_call hook.
209
- * Allows plugins to modify or block tool calls.
210
- * Runs sequentially.
211
- */
212
- async function runBeforeToolCall(event, ctx) {
213
- return runModifyingHook("before_tool_call", event, ctx, (acc, next) => ({
214
- params: next.params ?? acc?.params,
215
- block: next.block ?? acc?.block,
216
- blockReason: next.blockReason ?? acc?.blockReason
217
- }));
218
- }
219
- /**
220
- * Run after_tool_call hook.
221
- * Runs in parallel (fire-and-forget).
222
- */
223
- async function runAfterToolCall(event, ctx) {
224
- return runVoidHook("after_tool_call", event, ctx);
225
- }
226
- /**
227
- * Run tool_result_persist hook.
228
- *
229
- * This hook is intentionally synchronous: it runs in hot paths where session
230
- * transcripts are appended synchronously.
231
- *
232
- * Handlers are executed sequentially in priority order (higher first). Each
233
- * handler may return `{ message }` to replace the message passed to the next
234
- * handler.
235
- */
236
- function runToolResultPersist(event, ctx) {
237
- const hooks = getHooksForName(registry, "tool_result_persist");
238
- if (hooks.length === 0) return;
239
- let current = event.message;
240
- for (const hook of hooks) try {
241
- const out = hook.handler({
242
- ...event,
243
- message: current
244
- }, ctx);
245
- if (out && typeof out.then === "function") {
246
- const msg = `[hooks] tool_result_persist handler from ${hook.pluginId} returned a Promise; this hook is synchronous and the result was ignored.`;
247
- if (catchErrors) {
248
- logger?.warn?.(msg);
249
- continue;
250
- }
251
- throw new Error(msg);
252
- }
253
- const next = out?.message;
254
- if (next) current = next;
255
- } catch (err) {
256
- const msg = `[hooks] tool_result_persist handler from ${hook.pluginId} failed: ${String(err)}`;
257
- if (catchErrors) logger?.error(msg);
258
- else throw new Error(msg, { cause: err });
259
- }
260
- return { message: current };
261
- }
262
- /**
263
- * Run before_message_write hook.
264
- *
265
- * This hook is intentionally synchronous: it runs on the hot path where
266
- * session transcripts are appended synchronously.
267
- *
268
- * Handlers are executed sequentially in priority order (higher first).
269
- * If any handler returns { block: true }, the message is NOT written
270
- * to the session JSONL and we return immediately.
271
- * If a handler returns { message }, the modified message replaces the
272
- * original for subsequent handlers and the final write.
273
- */
274
- function runBeforeMessageWrite(event, ctx) {
275
- const hooks = getHooksForName(registry, "before_message_write");
276
- if (hooks.length === 0) return;
277
- let current = event.message;
278
- for (const hook of hooks) try {
279
- const out = hook.handler({
280
- ...event,
281
- message: current
282
- }, ctx);
283
- if (out && typeof out.then === "function") {
284
- const msg = `[hooks] before_message_write handler from ${hook.pluginId} returned a Promise; this hook is synchronous and the result was ignored.`;
285
- if (catchErrors) {
286
- logger?.warn?.(msg);
287
- continue;
288
- }
289
- throw new Error(msg);
290
- }
291
- const result = out;
292
- if (result?.block) return { block: true };
293
- if (result?.message) current = result.message;
294
- } catch (err) {
295
- const msg = `[hooks] before_message_write handler from ${hook.pluginId} failed: ${String(err)}`;
296
- if (catchErrors) logger?.error(msg);
297
- else throw new Error(msg, { cause: err });
298
- }
299
- if (current !== event.message) return { message: current };
300
- }
301
- /**
302
- * Run session_start hook.
303
- * Runs in parallel (fire-and-forget).
304
- */
305
- async function runSessionStart(event, ctx) {
306
- return runVoidHook("session_start", event, ctx);
307
- }
308
- /**
309
- * Run session_end hook.
310
- * Runs in parallel (fire-and-forget).
311
- */
312
- async function runSessionEnd(event, ctx) {
313
- return runVoidHook("session_end", event, ctx);
314
- }
315
- /**
316
- * Run subagent_spawning hook.
317
- * Runs sequentially so channel plugins can deterministically provision session bindings.
318
- */
319
- async function runSubagentSpawning(event, ctx) {
320
- return runModifyingHook("subagent_spawning", event, ctx, mergeSubagentSpawningResult);
321
- }
322
- /**
323
- * Run subagent_delivery_target hook.
324
- * Runs sequentially so channel plugins can deterministically resolve routing.
325
- */
326
- async function runSubagentDeliveryTarget(event, ctx) {
327
- return runModifyingHook("subagent_delivery_target", event, ctx, mergeSubagentDeliveryTargetResult);
328
- }
329
- /**
330
- * Run subagent_spawned hook.
331
- * Runs in parallel (fire-and-forget).
332
- */
333
- async function runSubagentSpawned(event, ctx) {
334
- return runVoidHook("subagent_spawned", event, ctx);
335
- }
336
- /**
337
- * Run subagent_ended hook.
338
- * Runs in parallel (fire-and-forget).
339
- */
340
- async function runSubagentEnded(event, ctx) {
341
- return runVoidHook("subagent_ended", event, ctx);
342
- }
343
- /**
344
- * Run gateway_start hook.
345
- * Runs in parallel (fire-and-forget).
346
- */
347
- async function runGatewayStart(event, ctx) {
348
- return runVoidHook("gateway_start", event, ctx);
349
- }
350
- /**
351
- * Run gateway_stop hook.
352
- * Runs in parallel (fire-and-forget).
353
- */
354
- async function runGatewayStop(event, ctx) {
355
- return runVoidHook("gateway_stop", event, ctx);
356
- }
357
- /**
358
- * Check if any hooks are registered for a given hook name.
359
- */
360
- function hasHooks(hookName) {
361
- return registry.typedHooks.some((h) => h.hookName === hookName);
362
- }
363
- /**
364
- * Get count of registered hooks for a given hook name.
365
- */
366
- function getHookCount(hookName) {
367
- return registry.typedHooks.filter((h) => h.hookName === hookName).length;
368
- }
369
- return {
370
- runBeforeModelResolve,
371
- runBeforePromptBuild,
372
- runBeforeAgentStart,
373
- runLlmInput,
374
- runLlmOutput,
375
- runAgentEnd,
376
- runBeforeCompaction,
377
- runAfterCompaction,
378
- runBeforeReset,
379
- runMessageReceived,
380
- runMessageSending,
381
- runMessageSent,
382
- runBeforeToolCall,
383
- runAfterToolCall,
384
- runToolResultPersist,
385
- runBeforeMessageWrite,
386
- runSessionStart,
387
- runSessionEnd,
388
- runSubagentSpawning,
389
- runSubagentDeliveryTarget,
390
- runSubagentSpawned,
391
- runSubagentEnded,
392
- runGatewayStart,
393
- runGatewayStop,
394
- hasHooks,
395
- getHookCount
396
- };
397
- }
398
-
399
- //#endregion
400
- //#region src/plugins/hook-runner-global.ts
401
- /**
402
- * Global Plugin Hook Runner
403
- *
404
- * Singleton hook runner that's initialized when plugins are loaded
405
- * and can be called from anywhere in the codebase.
406
- */
407
- const log$1 = createSubsystemLogger("plugins");
408
- let globalHookRunner = null;
409
- let globalRegistry = null;
410
- /**
411
- * Initialize the global hook runner with a plugin registry.
412
- * Called once when plugins are loaded during gateway startup.
413
- */
414
- function initializeGlobalHookRunner(registry) {
415
- globalRegistry = registry;
416
- globalHookRunner = createHookRunner(registry, {
417
- logger: {
418
- debug: (msg) => log$1.debug(msg),
419
- warn: (msg) => log$1.warn(msg),
420
- error: (msg) => log$1.error(msg)
421
- },
422
- catchErrors: true
423
- });
424
- const hookCount = registry.hooks.length;
425
- if (hookCount > 0) log$1.info(`hook runner initialized with ${hookCount} registered hooks`);
426
- }
427
- /**
428
- * Get the global hook runner.
429
- * Returns null if plugins haven't been loaded yet.
430
- */
431
- function getGlobalHookRunner() {
432
- return globalHookRunner;
433
- }
434
-
435
- //#endregion
436
- //#region src/infra/outbound/target-normalization.ts
437
- function normalizeChannelTargetInput(raw) {
438
- return raw.trim();
439
- }
440
- const targetNormalizerCacheByChannelId = /* @__PURE__ */ new Map();
441
- function resolveTargetNormalizer(channelId) {
442
- const version = getActivePluginRegistryVersion();
443
- const cached = targetNormalizerCacheByChannelId.get(channelId);
444
- if (cached?.version === version) return cached.normalizer;
445
- const normalizer = getChannelPlugin(channelId)?.messaging?.normalizeTarget;
446
- targetNormalizerCacheByChannelId.set(channelId, {
447
- version,
448
- normalizer
449
- });
450
- return normalizer;
451
- }
452
- function normalizeTargetForProvider(provider, raw) {
453
- if (!raw) return;
454
- const fallback = raw.trim() || void 0;
455
- if (!fallback) return;
456
- const providerId = normalizeChannelId(provider);
457
- return ((providerId ? resolveTargetNormalizer(providerId) : void 0)?.(raw) ?? fallback) || void 0;
458
- }
459
- function buildTargetResolverSignature(channel) {
460
- const resolver = getChannelPlugin(channel)?.messaging?.targetResolver;
461
- const hint = resolver?.hint ?? "";
462
- const looksLike = resolver?.looksLikeId;
463
- return hashSignature(`${hint}|${looksLike ? looksLike.toString() : ""}`);
464
- }
465
- function hashSignature(value) {
466
- let hash = 5381;
467
- for (let i = 0; i < value.length; i += 1) hash = (hash << 5) + hash ^ value.charCodeAt(i);
468
- return (hash >>> 0).toString(36);
469
- }
470
-
471
- //#endregion
472
- //#region src/auto-reply/reply/reply-tags.ts
473
- function extractReplyToTag(text, currentMessageId) {
474
- const result = parseInlineDirectives(text, {
475
- currentMessageId,
476
- stripAudioTag: false
477
- });
478
- return {
479
- cleaned: result.text,
480
- replyToId: result.replyToId,
481
- replyToCurrent: result.replyToCurrent,
482
- hasTag: result.hasReplyTag
483
- };
484
- }
485
-
486
- //#endregion
487
- //#region src/auto-reply/reply/reply-threading.ts
488
- function resolveReplyToMode(cfg, channel, accountId, chatType) {
489
- const provider = normalizeChannelId(channel);
490
- if (!provider) return "all";
491
- return getChannelDock(provider)?.threading?.resolveReplyToMode?.({
492
- cfg,
493
- accountId,
494
- chatType
495
- }) ?? "all";
496
- }
497
- function createReplyToModeFilter(mode, opts = {}) {
498
- let hasThreaded = false;
499
- return (payload) => {
500
- if (!payload.replyToId) return payload;
501
- if (mode === "off") {
502
- const isExplicit = Boolean(payload.replyToTag) || Boolean(payload.replyToCurrent);
503
- if (opts.allowExplicitReplyTagsWhenOff && isExplicit) return payload;
504
- return {
505
- ...payload,
506
- replyToId: void 0
507
- };
508
- }
509
- if (mode === "all") return payload;
510
- if (hasThreaded) return {
511
- ...payload,
512
- replyToId: void 0
513
- };
514
- hasThreaded = true;
515
- return payload;
516
- };
517
- }
518
- function createReplyToModeFilterForChannel(mode, channel) {
519
- const provider = normalizeChannelId(channel);
520
- const isWebchat = (typeof channel === "string" ? channel.trim().toLowerCase() : void 0) === "webchat";
521
- const dock = provider ? getChannelDock(provider) : void 0;
522
- return createReplyToModeFilter(mode, { allowExplicitReplyTagsWhenOff: provider ? dock?.threading?.allowExplicitReplyTagsWhenOff ?? dock?.threading?.allowTagsWhenOff ?? true : isWebchat });
523
- }
524
-
525
- //#endregion
526
- //#region src/auto-reply/reply/reply-payloads.ts
527
- function resolveReplyThreadingForPayload(params) {
528
- const implicitReplyToId = params.implicitReplyToId?.trim() || void 0;
529
- const currentMessageId = params.currentMessageId?.trim() || void 0;
530
- let resolved = params.payload.replyToId || params.payload.replyToCurrent === false || !implicitReplyToId ? params.payload : {
531
- ...params.payload,
532
- replyToId: implicitReplyToId
533
- };
534
- if (typeof resolved.text === "string" && resolved.text.includes("[[")) {
535
- const { cleaned, replyToId, replyToCurrent, hasTag } = extractReplyToTag(resolved.text, currentMessageId);
536
- resolved = {
537
- ...resolved,
538
- text: cleaned ? cleaned : void 0,
539
- replyToId: replyToId ?? resolved.replyToId,
540
- replyToTag: hasTag || resolved.replyToTag,
541
- replyToCurrent: replyToCurrent || resolved.replyToCurrent
542
- };
543
- }
544
- if (resolved.replyToCurrent && !resolved.replyToId && currentMessageId) resolved = {
545
- ...resolved,
546
- replyToId: currentMessageId
547
- };
548
- return resolved;
549
- }
550
- function applyReplyTagsToPayload(payload, currentMessageId) {
551
- return resolveReplyThreadingForPayload({
552
- payload,
553
- currentMessageId
554
- });
555
- }
556
- function isRenderablePayload(payload) {
557
- return Boolean(payload.text || payload.mediaUrl || payload.mediaUrls && payload.mediaUrls.length > 0 || payload.audioAsVoice || payload.channelData);
558
- }
559
- function shouldSuppressReasoningPayload(payload) {
560
- return payload.isReasoning === true;
561
- }
562
- function applyReplyThreading(params) {
563
- const { payloads, replyToMode, replyToChannel, currentMessageId } = params;
564
- const applyReplyToMode = createReplyToModeFilterForChannel(replyToMode, replyToChannel);
565
- const implicitReplyToId = currentMessageId?.trim() || void 0;
566
- return payloads.map((payload) => resolveReplyThreadingForPayload({
567
- payload,
568
- implicitReplyToId,
569
- currentMessageId
570
- })).filter(isRenderablePayload).map(applyReplyToMode);
571
- }
572
- function filterMessagingToolDuplicates(params) {
573
- const { payloads, sentTexts } = params;
574
- if (sentTexts.length === 0) return payloads;
575
- return payloads.filter((payload) => !isMessagingToolDuplicate(payload.text ?? "", sentTexts));
576
- }
577
- function filterMessagingToolMediaDuplicates(params) {
578
- const normalizeMediaForDedupe = (value) => {
579
- const trimmed = value.trim();
580
- if (!trimmed) return "";
581
- if (!trimmed.toLowerCase().startsWith("file://")) return trimmed;
582
- try {
583
- const parsed = new URL(trimmed);
584
- if (parsed.protocol === "file:") return decodeURIComponent(parsed.pathname || "");
585
- } catch {}
586
- return trimmed.replace(/^file:\/\//i, "");
587
- };
588
- const { payloads, sentMediaUrls } = params;
589
- if (sentMediaUrls.length === 0) return payloads;
590
- const sentSet = new Set(sentMediaUrls.map(normalizeMediaForDedupe).filter(Boolean));
591
- return payloads.map((payload) => {
592
- const mediaUrl = payload.mediaUrl;
593
- const mediaUrls = payload.mediaUrls;
594
- const stripSingle = mediaUrl && sentSet.has(normalizeMediaForDedupe(mediaUrl));
595
- const filteredUrls = mediaUrls?.filter((u) => !sentSet.has(normalizeMediaForDedupe(u)));
596
- if (!stripSingle && (!mediaUrls || filteredUrls?.length === mediaUrls.length)) return payload;
597
- return {
598
- ...payload,
599
- mediaUrl: stripSingle ? void 0 : mediaUrl,
600
- mediaUrls: filteredUrls?.length ? filteredUrls : void 0
601
- };
602
- });
603
- }
604
- const PROVIDER_ALIAS_MAP = { lark: "feishu" };
605
- function normalizeProviderForComparison(value) {
606
- const trimmed = value?.trim();
607
- if (!trimmed) return;
608
- const lowered = trimmed.toLowerCase();
609
- const normalizedChannel = normalizeChannelId(trimmed);
610
- if (normalizedChannel) return normalizedChannel;
611
- return PROVIDER_ALIAS_MAP[lowered] ?? lowered;
612
- }
613
- function normalizeThreadIdForComparison(value) {
614
- const trimmed = value?.trim();
615
- if (!trimmed) return;
616
- if (/^-?\d+$/.test(trimmed)) return String(Number.parseInt(trimmed, 10));
617
- return trimmed.toLowerCase();
618
- }
619
- function resolveTargetProviderForComparison(params) {
620
- const targetProvider = normalizeProviderForComparison(params.targetProvider);
621
- if (!targetProvider || targetProvider === "message") return params.currentProvider;
622
- return targetProvider;
623
- }
624
- function targetsMatchForSuppression(params) {
625
- if (params.provider !== "telegram") return params.targetKey === params.originTarget;
626
- const origin = parseTelegramTarget(params.originTarget);
627
- const target = parseTelegramTarget(params.targetKey);
628
- const targetThreadId = normalizeThreadIdForComparison(params.targetThreadId) ?? (target.messageThreadId != null ? String(target.messageThreadId) : void 0);
629
- const originThreadId = origin.messageThreadId != null ? String(origin.messageThreadId) : void 0;
630
- if (origin.chatId.trim().toLowerCase() !== target.chatId.trim().toLowerCase()) return false;
631
- if (originThreadId && targetThreadId != null) return originThreadId === targetThreadId;
632
- if (originThreadId && targetThreadId == null) return false;
633
- if (!originThreadId && targetThreadId != null) return false;
634
- return true;
635
- }
636
- function shouldSuppressMessagingToolReplies(params) {
637
- const provider = normalizeProviderForComparison(params.messageProvider);
638
- if (!provider) return false;
639
- const originTarget = normalizeTargetForProvider(provider, params.originatingTo);
640
- if (!originTarget) return false;
641
- const originAccount = normalizeOptionalAccountId(params.accountId);
642
- const sentTargets = params.messagingToolSentTargets ?? [];
643
- if (sentTargets.length === 0) return false;
644
- return sentTargets.some((target) => {
645
- const targetProvider = resolveTargetProviderForComparison({
646
- currentProvider: provider,
647
- targetProvider: target?.provider
648
- });
649
- if (targetProvider !== provider) return false;
650
- const targetKey = normalizeTargetForProvider(targetProvider, target.to);
651
- if (!targetKey) return false;
652
- const targetAccount = normalizeOptionalAccountId(target.accountId);
653
- if (originAccount && targetAccount && originAccount !== targetAccount) return false;
654
- return targetsMatchForSuppression({
655
- provider,
656
- originTarget,
657
- targetKey,
658
- targetThreadId: target.threadId
659
- });
660
- });
661
- }
662
-
663
- //#endregion
664
- //#region src/hooks/fire-and-forget.ts
665
- function fireAndForgetHook(task, label, logger = logVerbose) {
666
- task.catch((err) => {
667
- logger(`${label}: ${String(err)}`);
668
- });
669
- }
670
-
671
- //#endregion
672
- //#region src/hooks/message-hook-mappers.ts
673
- function deriveInboundMessageHookContext(ctx, overrides) {
674
- const content = overrides?.content ?? (typeof ctx.BodyForCommands === "string" ? ctx.BodyForCommands : typeof ctx.RawBody === "string" ? ctx.RawBody : typeof ctx.Body === "string" ? ctx.Body : "");
675
- const channelId = (ctx.OriginatingChannel ?? ctx.Surface ?? ctx.Provider ?? "").toLowerCase();
676
- const conversationId = ctx.OriginatingTo ?? ctx.To ?? ctx.From ?? void 0;
677
- const isGroup = Boolean(ctx.GroupSubject || ctx.GroupChannel);
678
- return {
679
- from: ctx.From ?? "",
680
- to: ctx.To,
681
- content,
682
- body: ctx.Body,
683
- bodyForAgent: ctx.BodyForAgent,
684
- transcript: ctx.Transcript,
685
- timestamp: typeof ctx.Timestamp === "number" && Number.isFinite(ctx.Timestamp) ? ctx.Timestamp : void 0,
686
- channelId,
687
- accountId: ctx.AccountId,
688
- conversationId,
689
- messageId: overrides?.messageId ?? ctx.MessageSidFull ?? ctx.MessageSid ?? ctx.MessageSidFirst ?? ctx.MessageSidLast,
690
- senderId: ctx.SenderId,
691
- senderName: ctx.SenderName,
692
- senderUsername: ctx.SenderUsername,
693
- senderE164: ctx.SenderE164,
694
- provider: ctx.Provider,
695
- surface: ctx.Surface,
696
- threadId: ctx.MessageThreadId,
697
- mediaPath: ctx.MediaPath,
698
- mediaType: ctx.MediaType,
699
- originatingChannel: ctx.OriginatingChannel,
700
- originatingTo: ctx.OriginatingTo,
701
- guildId: ctx.GroupSpace,
702
- channelName: ctx.GroupChannel,
703
- isGroup,
704
- groupId: isGroup ? conversationId : void 0
705
- };
706
- }
707
- function buildCanonicalSentMessageHookContext(params) {
708
- return {
709
- to: params.to,
710
- content: params.content,
711
- success: params.success,
712
- error: params.error,
713
- channelId: params.channelId,
714
- accountId: params.accountId,
715
- conversationId: params.conversationId ?? params.to,
716
- messageId: params.messageId,
717
- isGroup: params.isGroup,
718
- groupId: params.groupId
719
- };
720
- }
721
- function toPluginMessageContext(canonical) {
722
- return {
723
- channelId: canonical.channelId,
724
- accountId: canonical.accountId,
725
- conversationId: canonical.conversationId
726
- };
727
- }
728
- function toPluginMessageReceivedEvent(canonical) {
729
- return {
730
- from: canonical.from,
731
- content: canonical.content,
732
- timestamp: canonical.timestamp,
733
- metadata: {
734
- to: canonical.to,
735
- provider: canonical.provider,
736
- surface: canonical.surface,
737
- threadId: canonical.threadId,
738
- originatingChannel: canonical.originatingChannel,
739
- originatingTo: canonical.originatingTo,
740
- messageId: canonical.messageId,
741
- senderId: canonical.senderId,
742
- senderName: canonical.senderName,
743
- senderUsername: canonical.senderUsername,
744
- senderE164: canonical.senderE164,
745
- guildId: canonical.guildId,
746
- channelName: canonical.channelName
747
- }
748
- };
749
- }
750
- function toPluginMessageSentEvent(canonical) {
751
- return {
752
- to: canonical.to,
753
- content: canonical.content,
754
- success: canonical.success,
755
- ...canonical.error ? { error: canonical.error } : {}
756
- };
757
- }
758
- function toInternalMessageReceivedContext(canonical) {
759
- return {
760
- from: canonical.from,
761
- content: canonical.content,
762
- timestamp: canonical.timestamp,
763
- channelId: canonical.channelId,
764
- accountId: canonical.accountId,
765
- conversationId: canonical.conversationId,
766
- messageId: canonical.messageId,
767
- metadata: {
768
- to: canonical.to,
769
- provider: canonical.provider,
770
- surface: canonical.surface,
771
- threadId: canonical.threadId,
772
- senderId: canonical.senderId,
773
- senderName: canonical.senderName,
774
- senderUsername: canonical.senderUsername,
775
- senderE164: canonical.senderE164,
776
- guildId: canonical.guildId,
777
- channelName: canonical.channelName
778
- }
779
- };
780
- }
781
- function toInternalMessageTranscribedContext(canonical, cfg) {
782
- return {
783
- from: canonical.from,
784
- to: canonical.to,
785
- body: canonical.body,
786
- bodyForAgent: canonical.bodyForAgent,
787
- transcript: canonical.transcript ?? "",
788
- timestamp: canonical.timestamp,
789
- channelId: canonical.channelId,
790
- conversationId: canonical.conversationId,
791
- messageId: canonical.messageId,
792
- senderId: canonical.senderId,
793
- senderName: canonical.senderName,
794
- senderUsername: canonical.senderUsername,
795
- provider: canonical.provider,
796
- surface: canonical.surface,
797
- mediaPath: canonical.mediaPath,
798
- mediaType: canonical.mediaType,
799
- cfg
800
- };
801
- }
802
- function toInternalMessagePreprocessedContext(canonical, cfg) {
803
- return {
804
- from: canonical.from,
805
- to: canonical.to,
806
- body: canonical.body,
807
- bodyForAgent: canonical.bodyForAgent,
808
- transcript: canonical.transcript,
809
- timestamp: canonical.timestamp,
810
- channelId: canonical.channelId,
811
- conversationId: canonical.conversationId,
812
- messageId: canonical.messageId,
813
- senderId: canonical.senderId,
814
- senderName: canonical.senderName,
815
- senderUsername: canonical.senderUsername,
816
- provider: canonical.provider,
817
- surface: canonical.surface,
818
- mediaPath: canonical.mediaPath,
819
- mediaType: canonical.mediaType,
820
- isGroup: canonical.isGroup,
821
- groupId: canonical.groupId,
822
- cfg
823
- };
824
- }
825
- function toInternalMessageSentContext(canonical) {
826
- return {
827
- to: canonical.to,
828
- content: canonical.content,
829
- success: canonical.success,
830
- ...canonical.error ? { error: canonical.error } : {},
831
- channelId: canonical.channelId,
832
- accountId: canonical.accountId,
833
- conversationId: canonical.conversationId,
834
- messageId: canonical.messageId,
835
- ...canonical.isGroup != null ? { isGroup: canonical.isGroup } : {},
836
- ...canonical.groupId ? { groupId: canonical.groupId } : {}
837
- };
838
- }
839
-
840
- //#endregion
841
- //#region src/media/audio-tags.ts
842
- /**
843
- * Extract audio mode tag from text.
844
- * Supports [[audio_as_voice]] to send audio as voice bubble instead of file.
845
- * Default is file (preserves backward compatibility).
846
- */
847
- function parseAudioTag(text) {
848
- const result = parseInlineDirectives(text, { stripReplyTags: false });
849
- return {
850
- text: result.text,
851
- audioAsVoice: result.audioAsVoice,
852
- hadTag: result.hasAudioTag
853
- };
854
- }
855
-
856
- //#endregion
857
- //#region src/media/parse.ts
858
- const MEDIA_TOKEN_RE = /\bMEDIA:\s*`?([^\n]+)`?/gi;
859
- function normalizeMediaSource(src) {
860
- return src.startsWith("file://") ? src.replace("file://", "") : src;
861
- }
862
- function cleanCandidate(raw) {
863
- return raw.replace(/^[`"'[{(]+/, "").replace(/[`"'\\})\],]+$/, "");
864
- }
865
- const WINDOWS_DRIVE_RE = /^[a-zA-Z]:[\\/]/;
866
- const SCHEME_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:/;
867
- const HAS_FILE_EXT = /\.\w{1,10}$/;
868
- function isLikelyLocalPath(candidate) {
869
- return candidate.startsWith("/") || candidate.startsWith("./") || candidate.startsWith("../") || candidate.startsWith("~") || WINDOWS_DRIVE_RE.test(candidate) || candidate.startsWith("\\\\") || !SCHEME_RE.test(candidate) && (candidate.includes("/") || candidate.includes("\\"));
870
- }
871
- function isValidMedia(candidate, opts) {
872
- if (!candidate) return false;
873
- if (candidate.length > 4096) return false;
874
- if (!opts?.allowSpaces && /\s/.test(candidate)) return false;
875
- if (/^https?:\/\//i.test(candidate)) return true;
876
- if (isLikelyLocalPath(candidate)) return true;
877
- if (opts?.allowBareFilename && !SCHEME_RE.test(candidate) && HAS_FILE_EXT.test(candidate)) return true;
878
- return false;
879
- }
880
- function unwrapQuoted(value) {
881
- const trimmed = value.trim();
882
- if (trimmed.length < 2) return;
883
- const first = trimmed[0];
884
- if (first !== trimmed[trimmed.length - 1]) return;
885
- if (first !== `"` && first !== "'" && first !== "`") return;
886
- return trimmed.slice(1, -1).trim();
887
- }
888
- function mayContainFenceMarkers(input) {
889
- return input.includes("```") || input.includes("~~~");
890
- }
891
- function isInsideFence(fenceSpans, offset) {
892
- return fenceSpans.some((span) => offset >= span.start && offset < span.end);
893
- }
894
- function splitMediaFromOutput(raw) {
895
- const trimmedRaw = raw.trimEnd();
896
- if (!trimmedRaw.trim()) return { text: "" };
897
- const mayContainMediaToken = /media:/i.test(trimmedRaw);
898
- const mayContainAudioTag = trimmedRaw.includes("[[");
899
- if (!mayContainMediaToken && !mayContainAudioTag) return { text: trimmedRaw };
900
- const media = [];
901
- let foundMediaToken = false;
902
- const hasFenceMarkers = mayContainFenceMarkers(trimmedRaw);
903
- const fenceSpans = hasFenceMarkers ? parseFenceSpans(trimmedRaw) : [];
904
- const lines = trimmedRaw.split("\n");
905
- const keptLines = [];
906
- let lineOffset = 0;
907
- for (const line of lines) {
908
- if (hasFenceMarkers && isInsideFence(fenceSpans, lineOffset)) {
909
- keptLines.push(line);
910
- lineOffset += line.length + 1;
911
- continue;
912
- }
913
- if (!line.trimStart().startsWith("MEDIA:")) {
914
- keptLines.push(line);
915
- lineOffset += line.length + 1;
916
- continue;
917
- }
918
- const matches = Array.from(line.matchAll(MEDIA_TOKEN_RE));
919
- if (matches.length === 0) {
920
- keptLines.push(line);
921
- lineOffset += line.length + 1;
922
- continue;
923
- }
924
- const pieces = [];
925
- let cursor = 0;
926
- for (const match of matches) {
927
- const start = match.index ?? 0;
928
- pieces.push(line.slice(cursor, start));
929
- const payload = match[1];
930
- const unwrapped = unwrapQuoted(payload);
931
- const payloadValue = unwrapped ?? payload;
932
- const parts = unwrapped ? [unwrapped] : payload.split(/\s+/).filter(Boolean);
933
- const mediaStartIndex = media.length;
934
- let validCount = 0;
935
- const invalidParts = [];
936
- let hasValidMedia = false;
937
- for (const part of parts) {
938
- const candidate = normalizeMediaSource(cleanCandidate(part));
939
- if (isValidMedia(candidate, unwrapped ? { allowSpaces: true } : void 0)) {
940
- media.push(candidate);
941
- hasValidMedia = true;
942
- foundMediaToken = true;
943
- validCount += 1;
944
- } else invalidParts.push(part);
945
- }
946
- const trimmedPayload = payloadValue.trim();
947
- const looksLikeLocalPath = isLikelyLocalPath(trimmedPayload) || trimmedPayload.startsWith("file://");
948
- if (!unwrapped && validCount === 1 && invalidParts.length > 0 && /\s/.test(payloadValue) && looksLikeLocalPath) {
949
- const fallback = normalizeMediaSource(cleanCandidate(payloadValue));
950
- if (isValidMedia(fallback, { allowSpaces: true })) {
951
- media.splice(mediaStartIndex, media.length - mediaStartIndex, fallback);
952
- hasValidMedia = true;
953
- foundMediaToken = true;
954
- validCount = 1;
955
- invalidParts.length = 0;
956
- }
957
- }
958
- if (!hasValidMedia) {
959
- const fallback = normalizeMediaSource(cleanCandidate(payloadValue));
960
- if (isValidMedia(fallback, {
961
- allowSpaces: true,
962
- allowBareFilename: true
963
- })) {
964
- media.push(fallback);
965
- hasValidMedia = true;
966
- foundMediaToken = true;
967
- invalidParts.length = 0;
968
- }
969
- }
970
- if (hasValidMedia) {
971
- if (invalidParts.length > 0) pieces.push(invalidParts.join(" "));
972
- } else if (looksLikeLocalPath) foundMediaToken = true;
973
- else pieces.push(match[0]);
974
- cursor = start + match[0].length;
975
- }
976
- pieces.push(line.slice(cursor));
977
- const cleanedLine = pieces.join("").replace(/[ \t]{2,}/g, " ").trim();
978
- if (cleanedLine) keptLines.push(cleanedLine);
979
- lineOffset += line.length + 1;
980
- }
981
- let cleanedText = keptLines.join("\n").replace(/[ \t]+\n/g, "\n").replace(/[ \t]{2,}/g, " ").replace(/\n{2,}/g, "\n").trim();
982
- const audioTagResult = parseAudioTag(cleanedText);
983
- const hasAudioAsVoice = audioTagResult.audioAsVoice;
984
- if (audioTagResult.hadTag) cleanedText = audioTagResult.text.replace(/\n{2,}/g, "\n").trim();
985
- if (media.length === 0) {
986
- const result = { text: foundMediaToken || hasAudioAsVoice ? cleanedText : trimmedRaw };
987
- if (hasAudioAsVoice) result.audioAsVoice = true;
988
- return result;
989
- }
990
- return {
991
- text: cleanedText,
992
- mediaUrls: media,
993
- mediaUrl: media[0],
994
- ...hasAudioAsVoice ? { audioAsVoice: true } : {}
995
- };
996
- }
997
-
998
- //#endregion
999
- //#region src/auto-reply/reply/reply-directives.ts
1000
- function parseReplyDirectives(raw, options = {}) {
1001
- const split = splitMediaFromOutput(raw);
1002
- let text = split.text ?? "";
1003
- const replyParsed = parseInlineDirectives(text, {
1004
- currentMessageId: options.currentMessageId,
1005
- stripAudioTag: false,
1006
- stripReplyTags: true
1007
- });
1008
- if (replyParsed.hasReplyTag) text = replyParsed.text;
1009
- const silentToken = options.silentToken ?? SILENT_REPLY_TOKEN;
1010
- const isSilent = isSilentReplyText(text, silentToken);
1011
- if (isSilent) text = "";
1012
- return {
1013
- text,
1014
- mediaUrls: split.mediaUrls,
1015
- mediaUrl: split.mediaUrl,
1016
- replyToId: replyParsed.replyToId,
1017
- replyToCurrent: replyParsed.replyToCurrent,
1018
- replyToTag: replyParsed.hasReplyTag,
1019
- audioAsVoice: split.audioAsVoice,
1020
- isSilent
1021
- };
1022
- }
1023
-
1024
- //#endregion
1025
- //#region src/infra/outbound/abort.ts
1026
- /**
1027
- * Utility for checking AbortSignal state and throwing a standard AbortError.
1028
- */
1029
- /**
1030
- * Throws an AbortError if the given signal has been aborted.
1031
- * Use at async checkpoints to support cancellation.
1032
- */
1033
- function throwIfAborted(abortSignal) {
1034
- if (abortSignal?.aborted) {
1035
- const err = /* @__PURE__ */ new Error("Operation aborted");
1036
- err.name = "AbortError";
1037
- throw err;
1038
- }
1039
- }
1040
-
1041
- //#endregion
1042
- //#region src/channels/plugins/registry-loader.ts
1043
- function createChannelRegistryLoader(resolveValue) {
1044
- const cache = /* @__PURE__ */ new Map();
1045
- let lastRegistry = null;
1046
- return async (id) => {
1047
- const registry = getActivePluginRegistry();
1048
- if (registry !== lastRegistry) {
1049
- cache.clear();
1050
- lastRegistry = registry;
1051
- }
1052
- const cached = cache.get(id);
1053
- if (cached) return cached;
1054
- const pluginEntry = registry?.channels.find((entry) => entry.plugin.id === id);
1055
- if (!pluginEntry) return;
1056
- const resolved = resolveValue(pluginEntry);
1057
- if (resolved) cache.set(id, resolved);
1058
- return resolved;
1059
- };
1060
- }
1061
-
1062
- //#endregion
1063
- //#region src/channels/plugins/outbound/load.ts
1064
- const loadOutboundAdapterFromRegistry = createChannelRegistryLoader((entry) => entry.plugin.outbound);
1065
- async function loadChannelOutboundAdapter(id) {
1066
- return loadOutboundAdapterFromRegistry(id);
1067
- }
1068
-
1069
- //#endregion
1070
- //#region src/infra/outbound/delivery-queue.ts
1071
- const QUEUE_DIRNAME = "delivery-queue";
1072
- const FAILED_DIRNAME = "failed";
1073
- function resolveQueueDir(stateDir) {
1074
- const base = stateDir ?? resolveStateDir();
1075
- return path.join(base, QUEUE_DIRNAME);
1076
- }
1077
- function resolveFailedDir(stateDir) {
1078
- return path.join(resolveQueueDir(stateDir), FAILED_DIRNAME);
1079
- }
1080
- /** Ensure the queue directory (and failed/ subdirectory) exist. */
1081
- async function ensureQueueDir(stateDir) {
1082
- const queueDir = resolveQueueDir(stateDir);
1083
- await fs.promises.mkdir(queueDir, {
1084
- recursive: true,
1085
- mode: 448
1086
- });
1087
- await fs.promises.mkdir(resolveFailedDir(stateDir), {
1088
- recursive: true,
1089
- mode: 448
1090
- });
1091
- return queueDir;
1092
- }
1093
- async function enqueueDelivery(params, stateDir) {
1094
- const queueDir = await ensureQueueDir(stateDir);
1095
- const id = generateSecureUuid();
1096
- const entry = {
1097
- id,
1098
- enqueuedAt: Date.now(),
1099
- channel: params.channel,
1100
- to: params.to,
1101
- accountId: params.accountId,
1102
- payloads: params.payloads,
1103
- threadId: params.threadId,
1104
- replyToId: params.replyToId,
1105
- bestEffort: params.bestEffort,
1106
- gifPlayback: params.gifPlayback,
1107
- silent: params.silent,
1108
- mirror: params.mirror,
1109
- retryCount: 0
1110
- };
1111
- const filePath = path.join(queueDir, `${id}.json`);
1112
- const tmp = `${filePath}.${process.pid}.tmp`;
1113
- const json = JSON.stringify(entry, null, 2);
1114
- await fs.promises.writeFile(tmp, json, {
1115
- encoding: "utf-8",
1116
- mode: 384
1117
- });
1118
- await fs.promises.rename(tmp, filePath);
1119
- return id;
1120
- }
1121
- /** Remove a successfully delivered entry from the queue. */
1122
- async function ackDelivery(id, stateDir) {
1123
- const filePath = path.join(resolveQueueDir(stateDir), `${id}.json`);
1124
- try {
1125
- await fs.promises.unlink(filePath);
1126
- } catch (err) {
1127
- if ((err && typeof err === "object" && "code" in err ? String(err.code) : null) !== "ENOENT") throw err;
1128
- }
1129
- }
1130
- /** Update a queue entry after a failed delivery attempt. */
1131
- async function failDelivery(id, error, stateDir) {
1132
- const filePath = path.join(resolveQueueDir(stateDir), `${id}.json`);
1133
- const raw = await fs.promises.readFile(filePath, "utf-8");
1134
- const entry = JSON.parse(raw);
1135
- entry.retryCount += 1;
1136
- entry.lastAttemptAt = Date.now();
1137
- entry.lastError = error;
1138
- const tmp = `${filePath}.${process.pid}.tmp`;
1139
- await fs.promises.writeFile(tmp, JSON.stringify(entry, null, 2), {
1140
- encoding: "utf-8",
1141
- mode: 384
1142
- });
1143
- await fs.promises.rename(tmp, filePath);
1144
- }
1145
-
1146
- //#endregion
1147
- //#region src/infra/outbound/payloads.ts
1148
- function mergeMediaUrls(...lists) {
1149
- const seen = /* @__PURE__ */ new Set();
1150
- const merged = [];
1151
- for (const list of lists) {
1152
- if (!list) continue;
1153
- for (const entry of list) {
1154
- const trimmed = entry?.trim();
1155
- if (!trimmed) continue;
1156
- if (seen.has(trimmed)) continue;
1157
- seen.add(trimmed);
1158
- merged.push(trimmed);
1159
- }
1160
- }
1161
- return merged;
1162
- }
1163
- function normalizeReplyPayloadsForDelivery(payloads) {
1164
- const normalized = [];
1165
- for (const payload of payloads) {
1166
- if (shouldSuppressReasoningPayload(payload)) continue;
1167
- const parsed = parseReplyDirectives(payload.text ?? "");
1168
- const explicitMediaUrls = payload.mediaUrls ?? parsed.mediaUrls;
1169
- const explicitMediaUrl = payload.mediaUrl ?? parsed.mediaUrl;
1170
- const mergedMedia = mergeMediaUrls(explicitMediaUrls, explicitMediaUrl ? [explicitMediaUrl] : void 0);
1171
- const resolvedMediaUrl = (explicitMediaUrls?.length ?? 0) > 1 ? void 0 : explicitMediaUrl;
1172
- const next = {
1173
- ...payload,
1174
- text: parsed.text ?? "",
1175
- mediaUrls: mergedMedia.length ? mergedMedia : void 0,
1176
- mediaUrl: resolvedMediaUrl,
1177
- replyToId: payload.replyToId ?? parsed.replyToId,
1178
- replyToTag: payload.replyToTag || parsed.replyToTag,
1179
- replyToCurrent: payload.replyToCurrent || parsed.replyToCurrent,
1180
- audioAsVoice: Boolean(payload.audioAsVoice || parsed.audioAsVoice)
1181
- };
1182
- if (parsed.isSilent && mergedMedia.length === 0) continue;
1183
- if (!isRenderablePayload(next)) continue;
1184
- normalized.push(next);
1185
- }
1186
- return normalized;
1187
- }
1188
- function normalizeOutboundPayloads(payloads) {
1189
- const normalizedPayloads = [];
1190
- for (const payload of normalizeReplyPayloadsForDelivery(payloads)) {
1191
- const mediaUrls = payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : []);
1192
- const channelData = payload.channelData;
1193
- const hasChannelData = Boolean(channelData && Object.keys(channelData).length > 0);
1194
- const text = payload.text ?? "";
1195
- if (!text && mediaUrls.length === 0 && !hasChannelData) continue;
1196
- normalizedPayloads.push({
1197
- text,
1198
- mediaUrls,
1199
- ...hasChannelData ? { channelData } : {}
1200
- });
1201
- }
1202
- return normalizedPayloads;
1203
- }
1204
- function normalizeOutboundPayloadsForJson(payloads) {
1205
- const normalized = [];
1206
- for (const payload of normalizeReplyPayloadsForDelivery(payloads)) normalized.push({
1207
- text: payload.text ?? "",
1208
- mediaUrl: payload.mediaUrl ?? null,
1209
- mediaUrls: payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : void 0),
1210
- channelData: payload.channelData
1211
- });
1212
- return normalized;
1213
- }
1214
- function formatOutboundPayloadLog(payload) {
1215
- const lines = [];
1216
- if (payload.text) lines.push(payload.text.trimEnd());
1217
- for (const url of payload.mediaUrls) lines.push(`MEDIA:${url}`);
1218
- return lines.join("\n");
1219
- }
1220
-
1221
- //#endregion
1222
- //#region src/infra/outbound/sanitize-text.ts
1223
- /**
1224
- * Sanitize model output for plain-text messaging surfaces.
1225
- *
1226
- * LLMs occasionally produce HTML tags (`<br>`, `<b>`, `<i>`, etc.) that render
1227
- * correctly on web but appear as literal text on WhatsApp, Signal, SMS, and IRC.
1228
- *
1229
- * Converts common inline HTML to lightweight-markup equivalents used by
1230
- * WhatsApp/Signal/Telegram and strips any remaining tags.
1231
- *
1232
- * @see https://github.com/squidclaw/squidclaw/issues/31884
1233
- * @see https://github.com/squidclaw/squidclaw/issues/18558
1234
- */
1235
- /** Channels where HTML tags should be converted/stripped. */
1236
- const PLAIN_TEXT_SURFACES = new Set([
1237
- "whatsapp",
1238
- "signal",
1239
- "sms",
1240
- "irc",
1241
- "telegram",
1242
- "imessage",
1243
- "googlechat"
1244
- ]);
1245
- /** Returns `true` when the channel cannot render raw HTML. */
1246
- function isPlainTextSurface(channelId) {
1247
- return PLAIN_TEXT_SURFACES.has(channelId.toLowerCase());
1248
- }
1249
- /**
1250
- * Convert common HTML tags to their plain-text/lightweight-markup equivalents
1251
- * and strip anything that remains.
1252
- *
1253
- * The function is intentionally conservative — it only targets tags that models
1254
- * are known to produce and avoids false positives on angle brackets in normal
1255
- * prose (e.g. `a < b`).
1256
- */
1257
- function sanitizeForPlainText(text) {
1258
- return text.replace(/<((?:https?:\/\/|mailto:)[^<>\s]+)>/gi, "$1").replace(/<br\s*\/?>/gi, "\n").replace(/<\/?(p|div)>/gi, "\n").replace(/<(b|strong)>(.*?)<\/\1>/gi, "*$2*").replace(/<(i|em)>(.*?)<\/\1>/gi, "_$2_").replace(/<(s|strike|del)>(.*?)<\/\1>/gi, "~$2~").replace(/<code>(.*?)<\/code>/gi, "`$1`").replace(/<h[1-6][^>]*>(.*?)<\/h[1-6]>/gi, "\n*$1*\n").replace(/<li[^>]*>(.*?)<\/li>/gi, "• $1\n").replace(/<\/?[a-z][a-z0-9]*\b[^>]*>/gi, "").replace(/\n{3,}/g, "\n\n");
1259
- }
1260
-
1261
- //#endregion
1262
- //#region src/infra/outbound/deliver.ts
1263
- const log = createSubsystemLogger("outbound/deliver");
1264
- const TELEGRAM_TEXT_LIMIT = 4096;
1265
- async function createChannelHandler(params) {
1266
- const outbound = await loadChannelOutboundAdapter(params.channel);
1267
- const handler = createPluginHandler({
1268
- ...params,
1269
- outbound
1270
- });
1271
- if (!handler) throw new Error(`Outbound not configured for channel: ${params.channel}`);
1272
- return handler;
1273
- }
1274
- function createPluginHandler(params) {
1275
- const outbound = params.outbound;
1276
- if (!outbound?.sendText || !outbound?.sendMedia) return null;
1277
- const baseCtx = createChannelOutboundContextBase(params);
1278
- const sendText = outbound.sendText;
1279
- const sendMedia = outbound.sendMedia;
1280
- const chunker = outbound.chunker ?? null;
1281
- const chunkerMode = outbound.chunkerMode;
1282
- const resolveCtx = (overrides) => ({
1283
- ...baseCtx,
1284
- replyToId: overrides?.replyToId ?? baseCtx.replyToId,
1285
- threadId: overrides?.threadId ?? baseCtx.threadId
1286
- });
1287
- return {
1288
- chunker,
1289
- chunkerMode,
1290
- textChunkLimit: outbound.textChunkLimit,
1291
- sendPayload: outbound.sendPayload ? async (payload, overrides) => outbound.sendPayload({
1292
- ...resolveCtx(overrides),
1293
- text: payload.text ?? "",
1294
- mediaUrl: payload.mediaUrl,
1295
- payload
1296
- }) : void 0,
1297
- sendText: async (text, overrides) => sendText({
1298
- ...resolveCtx(overrides),
1299
- text
1300
- }),
1301
- sendMedia: async (caption, mediaUrl, overrides) => sendMedia({
1302
- ...resolveCtx(overrides),
1303
- text: caption,
1304
- mediaUrl
1305
- })
1306
- };
1307
- }
1308
- function createChannelOutboundContextBase(params) {
1309
- return {
1310
- cfg: params.cfg,
1311
- to: params.to,
1312
- accountId: params.accountId,
1313
- replyToId: params.replyToId,
1314
- threadId: params.threadId,
1315
- identity: params.identity,
1316
- gifPlayback: params.gifPlayback,
1317
- deps: params.deps,
1318
- silent: params.silent,
1319
- mediaLocalRoots: params.mediaLocalRoots
1320
- };
1321
- }
1322
- const isAbortError = (err) => err instanceof Error && err.name === "AbortError";
1323
- function hasMediaPayload(payload) {
1324
- return Boolean(payload.mediaUrl) || (payload.mediaUrls?.length ?? 0) > 0;
1325
- }
1326
- function hasChannelDataPayload(payload) {
1327
- return Boolean(payload.channelData && Object.keys(payload.channelData).length > 0);
1328
- }
1329
- function normalizePayloadForChannelDelivery(payload, channelId) {
1330
- const hasMedia = hasMediaPayload(payload);
1331
- const hasChannelData = hasChannelDataPayload(payload);
1332
- const rawText = typeof payload.text === "string" ? payload.text : "";
1333
- const normalizedText = channelId === "whatsapp" ? rawText.replace(/^(?:[ \t]*\r?\n)+/, "") : rawText;
1334
- if (!normalizedText.trim()) {
1335
- if (!hasMedia && !hasChannelData) return null;
1336
- return {
1337
- ...payload,
1338
- text: ""
1339
- };
1340
- }
1341
- if (normalizedText === rawText) return payload;
1342
- return {
1343
- ...payload,
1344
- text: normalizedText
1345
- };
1346
- }
1347
- function normalizePayloadsForChannelDelivery(payloads, channel) {
1348
- const normalizedPayloads = [];
1349
- for (const payload of normalizeReplyPayloadsForDelivery(payloads)) {
1350
- let sanitizedPayload = payload;
1351
- if (isPlainTextSurface(channel) && payload.text) {
1352
- if (!(channel === "telegram" && payload.channelData)) sanitizedPayload = {
1353
- ...payload,
1354
- text: sanitizeForPlainText(payload.text)
1355
- };
1356
- }
1357
- const normalized = normalizePayloadForChannelDelivery(sanitizedPayload, channel);
1358
- if (normalized) normalizedPayloads.push(normalized);
1359
- }
1360
- return normalizedPayloads;
1361
- }
1362
- function buildPayloadSummary(payload) {
1363
- return {
1364
- text: payload.text ?? "",
1365
- mediaUrls: payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : []),
1366
- channelData: payload.channelData
1367
- };
1368
- }
1369
- function createMessageSentEmitter(params) {
1370
- const hasMessageSentHooks = params.hookRunner?.hasHooks("message_sent") ?? false;
1371
- const canEmitInternalHook = Boolean(params.sessionKeyForInternalHooks);
1372
- const emitMessageSent = (event) => {
1373
- if (!hasMessageSentHooks && !canEmitInternalHook) return;
1374
- const canonical = buildCanonicalSentMessageHookContext({
1375
- to: params.to,
1376
- content: event.content,
1377
- success: event.success,
1378
- error: event.error,
1379
- channelId: params.channel,
1380
- accountId: params.accountId ?? void 0,
1381
- conversationId: params.to,
1382
- messageId: event.messageId,
1383
- isGroup: params.mirrorIsGroup,
1384
- groupId: params.mirrorGroupId
1385
- });
1386
- if (hasMessageSentHooks) fireAndForgetHook(params.hookRunner.runMessageSent(toPluginMessageSentEvent(canonical), toPluginMessageContext(canonical)), "deliverOutboundPayloads: message_sent plugin hook failed", (message) => {
1387
- log.warn(message);
1388
- });
1389
- if (!canEmitInternalHook) return;
1390
- fireAndForgetHook(triggerInternalHook(createInternalHookEvent("message", "sent", params.sessionKeyForInternalHooks, toInternalMessageSentContext(canonical))), "deliverOutboundPayloads: message:sent internal hook failed", (message) => {
1391
- log.warn(message);
1392
- });
1393
- };
1394
- return {
1395
- emitMessageSent,
1396
- hasMessageSentHooks
1397
- };
1398
- }
1399
- async function applyMessageSendingHook(params) {
1400
- if (!params.enabled) return {
1401
- cancelled: false,
1402
- payload: params.payload,
1403
- payloadSummary: params.payloadSummary
1404
- };
1405
- try {
1406
- const sendingResult = await params.hookRunner.runMessageSending({
1407
- to: params.to,
1408
- content: params.payloadSummary.text,
1409
- metadata: {
1410
- channel: params.channel,
1411
- accountId: params.accountId,
1412
- mediaUrls: params.payloadSummary.mediaUrls
1413
- }
1414
- }, {
1415
- channelId: params.channel,
1416
- accountId: params.accountId ?? void 0
1417
- });
1418
- if (sendingResult?.cancel) return {
1419
- cancelled: true,
1420
- payload: params.payload,
1421
- payloadSummary: params.payloadSummary
1422
- };
1423
- if (sendingResult?.content == null) return {
1424
- cancelled: false,
1425
- payload: params.payload,
1426
- payloadSummary: params.payloadSummary
1427
- };
1428
- return {
1429
- cancelled: false,
1430
- payload: {
1431
- ...params.payload,
1432
- text: sendingResult.content
1433
- },
1434
- payloadSummary: {
1435
- ...params.payloadSummary,
1436
- text: sendingResult.content
1437
- }
1438
- };
1439
- } catch {
1440
- return {
1441
- cancelled: false,
1442
- payload: params.payload,
1443
- payloadSummary: params.payloadSummary
1444
- };
1445
- }
1446
- }
1447
- async function deliverOutboundPayloads(params) {
1448
- const { channel, to, payloads } = params;
1449
- const queueId = params.skipQueue ? null : await enqueueDelivery({
1450
- channel,
1451
- to,
1452
- accountId: params.accountId,
1453
- payloads,
1454
- threadId: params.threadId,
1455
- replyToId: params.replyToId,
1456
- bestEffort: params.bestEffort,
1457
- gifPlayback: params.gifPlayback,
1458
- silent: params.silent,
1459
- mirror: params.mirror
1460
- }).catch(() => null);
1461
- let hadPartialFailure = false;
1462
- const wrappedParams = params.onError ? {
1463
- ...params,
1464
- onError: (err, payload) => {
1465
- hadPartialFailure = true;
1466
- params.onError(err, payload);
1467
- }
1468
- } : params;
1469
- try {
1470
- const results = await deliverOutboundPayloadsCore(wrappedParams);
1471
- if (queueId) if (hadPartialFailure) await failDelivery(queueId, "partial delivery failure (bestEffort)").catch(() => {});
1472
- else await ackDelivery(queueId).catch(() => {});
1473
- return results;
1474
- } catch (err) {
1475
- if (queueId) if (isAbortError(err)) await ackDelivery(queueId).catch(() => {});
1476
- else await failDelivery(queueId, err instanceof Error ? err.message : String(err)).catch(() => {});
1477
- throw err;
1478
- }
1479
- }
1480
- /** Core delivery logic (extracted for queue wrapper). */
1481
- async function deliverOutboundPayloadsCore(params) {
1482
- const { cfg, channel, to, payloads } = params;
1483
- const accountId = params.accountId;
1484
- const deps = params.deps;
1485
- const abortSignal = params.abortSignal;
1486
- const sendSignal = params.deps?.sendSignal ?? sendMessageSignal;
1487
- const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg, params.session?.agentId ?? params.mirror?.agentId);
1488
- const results = [];
1489
- const handler = await createChannelHandler({
1490
- cfg,
1491
- channel,
1492
- to,
1493
- deps,
1494
- accountId,
1495
- replyToId: params.replyToId,
1496
- threadId: params.threadId,
1497
- identity: params.identity,
1498
- gifPlayback: params.gifPlayback,
1499
- silent: params.silent,
1500
- mediaLocalRoots
1501
- });
1502
- const configuredTextLimit = handler.chunker ? resolveTextChunkLimit(cfg, channel, accountId, { fallbackLimit: handler.textChunkLimit }) : void 0;
1503
- const textLimit = channel === "telegram" && typeof configuredTextLimit === "number" ? Math.min(configuredTextLimit, TELEGRAM_TEXT_LIMIT) : configuredTextLimit;
1504
- const chunkMode = handler.chunker ? resolveChunkMode(cfg, channel, accountId) : "length";
1505
- const isSignalChannel = channel === "signal";
1506
- const signalTableMode = isSignalChannel ? resolveMarkdownTableMode({
1507
- cfg,
1508
- channel: "signal",
1509
- accountId
1510
- }) : "code";
1511
- const signalMaxBytes = isSignalChannel ? resolveChannelMediaMaxBytes({
1512
- cfg,
1513
- resolveChannelLimitMb: ({ cfg, accountId }) => cfg.channels?.signal?.accounts?.[accountId]?.mediaMaxMb ?? cfg.channels?.signal?.mediaMaxMb,
1514
- accountId
1515
- }) : void 0;
1516
- const sendTextChunks = async (text, overrides) => {
1517
- throwIfAborted(abortSignal);
1518
- if (!handler.chunker || textLimit === void 0) {
1519
- results.push(await handler.sendText(text, overrides));
1520
- return;
1521
- }
1522
- if (chunkMode === "newline") {
1523
- const blockChunks = (handler.chunkerMode ?? "text") === "markdown" ? chunkMarkdownTextWithMode(text, textLimit, "newline") : chunkByParagraph(text, textLimit);
1524
- if (!blockChunks.length && text) blockChunks.push(text);
1525
- for (const blockChunk of blockChunks) {
1526
- const chunks = handler.chunker(blockChunk, textLimit);
1527
- if (!chunks.length && blockChunk) chunks.push(blockChunk);
1528
- for (const chunk of chunks) {
1529
- throwIfAborted(abortSignal);
1530
- results.push(await handler.sendText(chunk, overrides));
1531
- }
1532
- }
1533
- return;
1534
- }
1535
- const chunks = handler.chunker(text, textLimit);
1536
- for (const chunk of chunks) {
1537
- throwIfAborted(abortSignal);
1538
- results.push(await handler.sendText(chunk, overrides));
1539
- }
1540
- };
1541
- const sendSignalText = async (text, styles) => {
1542
- throwIfAborted(abortSignal);
1543
- return {
1544
- channel: "signal",
1545
- ...await sendSignal(to, text, {
1546
- cfg,
1547
- maxBytes: signalMaxBytes,
1548
- accountId: accountId ?? void 0,
1549
- textMode: "plain",
1550
- textStyles: styles
1551
- })
1552
- };
1553
- };
1554
- const sendSignalTextChunks = async (text) => {
1555
- throwIfAborted(abortSignal);
1556
- let signalChunks = textLimit === void 0 ? markdownToSignalTextChunks(text, Number.POSITIVE_INFINITY, { tableMode: signalTableMode }) : markdownToSignalTextChunks(text, textLimit, { tableMode: signalTableMode });
1557
- if (signalChunks.length === 0 && text) signalChunks = [{
1558
- text,
1559
- styles: []
1560
- }];
1561
- for (const chunk of signalChunks) {
1562
- throwIfAborted(abortSignal);
1563
- results.push(await sendSignalText(chunk.text, chunk.styles));
1564
- }
1565
- };
1566
- const sendSignalMedia = async (caption, mediaUrl) => {
1567
- throwIfAborted(abortSignal);
1568
- const formatted = markdownToSignalTextChunks(caption, Number.POSITIVE_INFINITY, { tableMode: signalTableMode })[0] ?? {
1569
- text: caption,
1570
- styles: []
1571
- };
1572
- return {
1573
- channel: "signal",
1574
- ...await sendSignal(to, formatted.text, {
1575
- cfg,
1576
- mediaUrl,
1577
- maxBytes: signalMaxBytes,
1578
- accountId: accountId ?? void 0,
1579
- textMode: "plain",
1580
- textStyles: formatted.styles,
1581
- mediaLocalRoots
1582
- })
1583
- };
1584
- };
1585
- const normalizedPayloads = normalizePayloadsForChannelDelivery(payloads, channel);
1586
- const hookRunner = getGlobalHookRunner();
1587
- const sessionKeyForInternalHooks = params.mirror?.sessionKey ?? params.session?.key;
1588
- const mirrorIsGroup = params.mirror?.isGroup;
1589
- const mirrorGroupId = params.mirror?.groupId;
1590
- const { emitMessageSent, hasMessageSentHooks } = createMessageSentEmitter({
1591
- hookRunner,
1592
- channel,
1593
- to,
1594
- accountId,
1595
- sessionKeyForInternalHooks,
1596
- mirrorIsGroup,
1597
- mirrorGroupId
1598
- });
1599
- const hasMessageSendingHooks = hookRunner?.hasHooks("message_sending") ?? false;
1600
- if (hasMessageSentHooks && params.session?.agentId && !sessionKeyForInternalHooks) log.warn("deliverOutboundPayloads: session.agentId present without session key; internal message:sent hook will be skipped", {
1601
- channel,
1602
- to,
1603
- agentId: params.session.agentId
1604
- });
1605
- for (const payload of normalizedPayloads) {
1606
- let payloadSummary = buildPayloadSummary(payload);
1607
- try {
1608
- throwIfAborted(abortSignal);
1609
- const hookResult = await applyMessageSendingHook({
1610
- hookRunner,
1611
- enabled: hasMessageSendingHooks,
1612
- payload,
1613
- payloadSummary,
1614
- to,
1615
- channel,
1616
- accountId
1617
- });
1618
- if (hookResult.cancelled) continue;
1619
- const effectivePayload = hookResult.payload;
1620
- payloadSummary = hookResult.payloadSummary;
1621
- params.onPayload?.(payloadSummary);
1622
- const sendOverrides = {
1623
- replyToId: effectivePayload.replyToId ?? params.replyToId ?? void 0,
1624
- threadId: params.threadId ?? void 0
1625
- };
1626
- if (handler.sendPayload && effectivePayload.channelData) {
1627
- const delivery = await handler.sendPayload(effectivePayload, sendOverrides);
1628
- results.push(delivery);
1629
- emitMessageSent({
1630
- success: true,
1631
- content: payloadSummary.text,
1632
- messageId: delivery.messageId
1633
- });
1634
- continue;
1635
- }
1636
- if (payloadSummary.mediaUrls.length === 0) {
1637
- const beforeCount = results.length;
1638
- if (isSignalChannel) await sendSignalTextChunks(payloadSummary.text);
1639
- else await sendTextChunks(payloadSummary.text, sendOverrides);
1640
- const messageId = results.at(-1)?.messageId;
1641
- emitMessageSent({
1642
- success: results.length > beforeCount,
1643
- content: payloadSummary.text,
1644
- messageId
1645
- });
1646
- continue;
1647
- }
1648
- let first = true;
1649
- let lastMessageId;
1650
- for (const url of payloadSummary.mediaUrls) {
1651
- throwIfAborted(abortSignal);
1652
- const caption = first ? payloadSummary.text : "";
1653
- first = false;
1654
- if (isSignalChannel) {
1655
- const delivery = await sendSignalMedia(caption, url);
1656
- results.push(delivery);
1657
- lastMessageId = delivery.messageId;
1658
- } else {
1659
- const delivery = await handler.sendMedia(caption, url, sendOverrides);
1660
- results.push(delivery);
1661
- lastMessageId = delivery.messageId;
1662
- }
1663
- }
1664
- emitMessageSent({
1665
- success: true,
1666
- content: payloadSummary.text,
1667
- messageId: lastMessageId
1668
- });
1669
- } catch (err) {
1670
- emitMessageSent({
1671
- success: false,
1672
- content: payloadSummary.text,
1673
- error: err instanceof Error ? err.message : String(err)
1674
- });
1675
- if (!params.bestEffort) throw err;
1676
- params.onError?.(err, payloadSummary);
1677
- }
1678
- }
1679
- if (params.mirror && results.length > 0) {
1680
- const mirrorText = resolveMirroredTranscriptText({
1681
- text: params.mirror.text,
1682
- mediaUrls: params.mirror.mediaUrls
1683
- });
1684
- if (mirrorText) await appendAssistantMessageToSessionTranscript({
1685
- agentId: params.mirror.agentId,
1686
- sessionKey: params.mirror.sessionKey,
1687
- text: mirrorText
1688
- });
1689
- }
1690
- return results;
1691
- }
1692
-
1693
- //#endregion
1694
- export { resolveChannelMediaMaxBytes as A, createReplyToModeFilterForChannel as C, normalizeTargetForProvider as D, normalizeChannelTargetInput as E, getGlobalHookRunner as O, shouldSuppressReasoningPayload as S, buildTargetResolverSignature as T, applyReplyThreading as _, normalizeReplyPayloadsForDelivery as a, isRenderablePayload as b, splitMediaFromOutput as c, toInternalMessageReceivedContext as d, toInternalMessageTranscribedContext as f, applyReplyTagsToPayload as g, fireAndForgetHook as h, normalizeOutboundPayloadsForJson as i, initializeGlobalHookRunner as k, deriveInboundMessageHookContext as l, toPluginMessageReceivedEvent as m, formatOutboundPayloadLog as n, throwIfAborted as o, toPluginMessageContext as p, normalizeOutboundPayloads as r, parseReplyDirectives as s, deliverOutboundPayloads as t, toInternalMessagePreprocessedContext as u, filterMessagingToolDuplicates as v, resolveReplyToMode as w, shouldSuppressMessagingToolReplies as x, filterMessagingToolMediaDuplicates as y };