abtars 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (386) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/bundle/_registry.generated-KQODGKTQ.js +36 -0
  3. package/bundle/{_registry.generated-M4WY2MMI.js.map → _registry.generated-KQODGKTQ.js.map} +1 -1
  4. package/bundle/abtars-browser.js +8 -7
  5. package/bundle/abtars-browser.js.map +1 -1
  6. package/bundle/abtars-cli.js +646 -73
  7. package/bundle/abtars-cli.js.map +4 -4
  8. package/bundle/abtars-restart.js +7 -6
  9. package/bundle/abtars-rss.js +2 -1
  10. package/bundle/abtars-rss.js.map +1 -1
  11. package/bundle/abtars-task.js +9 -8
  12. package/bundle/abtars-task.js.map +1 -1
  13. package/bundle/abtars.js +103 -96
  14. package/bundle/abtars.js.map +2 -2
  15. package/bundle/{agent-api-rate-limit-OQNFMXTZ.js → agent-api-rate-limit-7R5TX2F2.js} +7 -6
  16. package/bundle/{agent-api-rate-limit-OQNFMXTZ.js.map → agent-api-rate-limit-7R5TX2F2.js.map} +1 -1
  17. package/bundle/agent-registry-5M77ZOMV.js +19 -0
  18. package/bundle/agent-registry-VJMNIQ5W.js +19 -0
  19. package/bundle/{anthropic-adapter-2APTH3LA.js → anthropic-adapter-IBY3NPXW.js} +4 -3
  20. package/bundle/{anthropic-adapter-2APTH3LA.js.map → anthropic-adapter-IBY3NPXW.js.map} +1 -1
  21. package/bundle/{bridge-lock-transport-4AC2G5G6.js → bridge-lock-transport-HO545SBK.js} +9 -8
  22. package/bundle/browse-delivery-64GQIUHG.js +18 -0
  23. package/bundle/browser-EXR5OQGK.js +19 -0
  24. package/bundle/capability-HIE7UGFU.js +18 -0
  25. package/bundle/{chunk-BUUVFUPO.js → chunk-2BY6I4P5.js} +5 -4
  26. package/bundle/{chunk-BUUVFUPO.js.map → chunk-2BY6I4P5.js.map} +1 -1
  27. package/bundle/{chunk-Y6XAEX2Q.js → chunk-2F6XKG7Y.js} +15 -9
  28. package/bundle/chunk-2F6XKG7Y.js.map +7 -0
  29. package/bundle/{chunk-V76TVMCM.js → chunk-3MO2MDXJ.js} +5 -4
  30. package/bundle/{chunk-V76TVMCM.js.map → chunk-3MO2MDXJ.js.map} +1 -1
  31. package/bundle/{chunk-6UCRKRWR.js → chunk-6XX4OAAM.js} +22 -21
  32. package/bundle/chunk-6XX4OAAM.js.map +7 -0
  33. package/bundle/{chunk-XREWVCUO.js → chunk-7CHLS36W.js} +16 -148
  34. package/bundle/chunk-7CHLS36W.js.map +7 -0
  35. package/bundle/{chunk-NWDBD4PA.js → chunk-7K2YZTLD.js} +3 -2
  36. package/bundle/{chunk-JCJS4ZIB.js → chunk-AQVOAQQI.js} +5 -4
  37. package/bundle/{chunk-JCJS4ZIB.js.map → chunk-AQVOAQQI.js.map} +1 -1
  38. package/bundle/chunk-AUQD2PKM.js +136 -0
  39. package/bundle/chunk-AUQD2PKM.js.map +7 -0
  40. package/bundle/{chunk-YOCTDKKL.js → chunk-BYDUMHXT.js} +4 -3
  41. package/bundle/{chunk-YOCTDKKL.js.map → chunk-BYDUMHXT.js.map} +1 -1
  42. package/bundle/{chunk-RVE2N7FA.js → chunk-CELR236Q.js} +5 -4
  43. package/bundle/{chunk-RVE2N7FA.js.map → chunk-CELR236Q.js.map} +1 -1
  44. package/bundle/{chunk-2XU2X4OI.js → chunk-CUQA2AJT.js} +3 -2
  45. package/bundle/{chunk-2XU2X4OI.js.map → chunk-CUQA2AJT.js.map} +1 -1
  46. package/bundle/chunk-DMPR5MYT.js +183 -0
  47. package/bundle/chunk-DMPR5MYT.js.map +7 -0
  48. package/bundle/{chunk-BHMZ4RCC.js → chunk-DY3R7LDW.js} +55 -54
  49. package/bundle/{chunk-BHMZ4RCC.js.map → chunk-DY3R7LDW.js.map} +1 -1
  50. package/bundle/{chunk-AR6GO6YC.js → chunk-ELRAH7VL.js} +5 -4
  51. package/bundle/{chunk-AR6GO6YC.js.map → chunk-ELRAH7VL.js.map} +1 -1
  52. package/bundle/{chunk-FMWKEPM7.js → chunk-EX2SRTUE.js} +5 -4
  53. package/bundle/{chunk-FMWKEPM7.js.map → chunk-EX2SRTUE.js.map} +1 -1
  54. package/bundle/{chunk-JW6RU47G.js → chunk-FVQGP5YO.js} +8 -7
  55. package/bundle/{chunk-JW6RU47G.js.map → chunk-FVQGP5YO.js.map} +1 -1
  56. package/bundle/{chunk-GRNENTPA.js → chunk-G6IXMYIO.js} +4 -3
  57. package/bundle/{chunk-GRNENTPA.js.map → chunk-G6IXMYIO.js.map} +1 -1
  58. package/bundle/{chunk-6NR3OHEW.js → chunk-H2RZ4NEJ.js} +6 -5
  59. package/bundle/{chunk-6NR3OHEW.js.map → chunk-H2RZ4NEJ.js.map} +1 -1
  60. package/bundle/chunk-HVKJN3AG.js +189 -0
  61. package/bundle/chunk-HVKJN3AG.js.map +7 -0
  62. package/bundle/{chunk-265TPOPC.js → chunk-HXJRZWKA.js} +3 -2
  63. package/bundle/{chunk-265TPOPC.js.map → chunk-HXJRZWKA.js.map} +1 -1
  64. package/bundle/chunk-IU3RI5E4.js +645 -0
  65. package/bundle/chunk-IU3RI5E4.js.map +7 -0
  66. package/bundle/{chunk-GST5T3WZ.js → chunk-J5YIMCLT.js} +6 -5
  67. package/bundle/{chunk-GST5T3WZ.js.map → chunk-J5YIMCLT.js.map} +1 -1
  68. package/bundle/chunk-JAJ3DUQ2.js +30 -0
  69. package/bundle/{chunk-OP7BTAWY.js.map → chunk-JAJ3DUQ2.js.map} +1 -1
  70. package/bundle/chunk-JHF25OOG.js +645 -0
  71. package/bundle/chunk-JHF25OOG.js.map +7 -0
  72. package/bundle/{chunk-MPX525QO.js → chunk-JRG4EFMP.js} +5 -4
  73. package/bundle/{chunk-MPX525QO.js.map → chunk-JRG4EFMP.js.map} +1 -1
  74. package/bundle/{chunk-VVEDVGCR.js → chunk-JU3UBWLN.js} +17 -16
  75. package/bundle/{chunk-VVEDVGCR.js.map → chunk-JU3UBWLN.js.map} +1 -1
  76. package/bundle/{chunk-QBGBT5QS.js → chunk-JX3ZZU3O.js} +5 -4
  77. package/bundle/{chunk-QBGBT5QS.js.map → chunk-JX3ZZU3O.js.map} +1 -1
  78. package/bundle/{chunk-6SETMHNN.js → chunk-K7P74UNQ.js} +8 -7
  79. package/bundle/{chunk-6SETMHNN.js.map → chunk-K7P74UNQ.js.map} +1 -1
  80. package/bundle/{chunk-AZJIODTQ.js → chunk-KED3G7HS.js} +6 -5
  81. package/bundle/{chunk-AZJIODTQ.js.map → chunk-KED3G7HS.js.map} +1 -1
  82. package/bundle/chunk-KI2ROWAH.js +3707 -0
  83. package/bundle/chunk-KI2ROWAH.js.map +7 -0
  84. package/bundle/{chunk-UHRP745J.js → chunk-L7YHV5DL.js} +6 -5
  85. package/bundle/{chunk-UHRP745J.js.map → chunk-L7YHV5DL.js.map} +1 -1
  86. package/bundle/{chunk-BSSBCSCL.js → chunk-LD5BMLHG.js} +11 -10
  87. package/bundle/{chunk-BSSBCSCL.js.map → chunk-LD5BMLHG.js.map} +1 -1
  88. package/bundle/{chunk-2UPU3OW6.js → chunk-LYEAHE5V.js} +5 -4
  89. package/bundle/{chunk-2UPU3OW6.js.map → chunk-LYEAHE5V.js.map} +1 -1
  90. package/bundle/{chunk-3B7BBE4F.js → chunk-MCGEXAG5.js} +8 -7
  91. package/bundle/{chunk-3B7BBE4F.js.map → chunk-MCGEXAG5.js.map} +1 -1
  92. package/bundle/{chunk-X76UX47U.js → chunk-MJ6PHMOK.js} +4 -3
  93. package/bundle/{chunk-X76UX47U.js.map → chunk-MJ6PHMOK.js.map} +1 -1
  94. package/bundle/{chunk-LSPKJQCI.js → chunk-MV6CJFWR.js} +3 -2
  95. package/bundle/{chunk-LSPKJQCI.js.map → chunk-MV6CJFWR.js.map} +1 -1
  96. package/bundle/chunk-MZWMYN4O.js +17 -0
  97. package/bundle/{chunk-M6VBAPNT.js.map → chunk-MZWMYN4O.js.map} +1 -1
  98. package/bundle/{chunk-HX7Y7EYP.js → chunk-NIRYBWUW.js} +4 -3
  99. package/bundle/{chunk-HX7Y7EYP.js.map → chunk-NIRYBWUW.js.map} +1 -1
  100. package/bundle/{chunk-3E545J66.js → chunk-OW64RUE5.js} +3 -2
  101. package/bundle/{chunk-3E545J66.js.map → chunk-OW64RUE5.js.map} +1 -1
  102. package/bundle/chunk-P56PLAIC.js +126 -0
  103. package/bundle/chunk-P56PLAIC.js.map +7 -0
  104. package/bundle/{chunk-TZHIDLDS.js → chunk-P6PN34XD.js} +5 -4
  105. package/bundle/{chunk-TZHIDLDS.js.map → chunk-P6PN34XD.js.map} +1 -1
  106. package/bundle/{chunk-2UENBO6M.js → chunk-PF5UQ64X.js} +9 -8
  107. package/bundle/{chunk-2UENBO6M.js.map → chunk-PF5UQ64X.js.map} +1 -1
  108. package/bundle/{chunk-6CPN4IGS.js → chunk-PQ62LZNA.js} +9 -8
  109. package/bundle/{chunk-6CPN4IGS.js.map → chunk-PQ62LZNA.js.map} +1 -1
  110. package/bundle/{chunk-UCQ2WC3B.js → chunk-PQW5QBPY.js} +15 -8
  111. package/bundle/chunk-PQW5QBPY.js.map +7 -0
  112. package/bundle/{chunk-D2DCBO6M.js → chunk-R36WIOYX.js} +3 -2
  113. package/bundle/{chunk-D2DCBO6M.js.map → chunk-R36WIOYX.js.map} +1 -1
  114. package/bundle/chunk-RB3X66KM.js +386 -0
  115. package/bundle/chunk-RB3X66KM.js.map +7 -0
  116. package/bundle/{chunk-GUQVJC3U.js → chunk-RE3F3CFW.js} +7 -6
  117. package/bundle/{chunk-GUQVJC3U.js.map → chunk-RE3F3CFW.js.map} +1 -1
  118. package/bundle/chunk-RWUINZUQ.js +19 -0
  119. package/bundle/chunk-RWUINZUQ.js.map +7 -0
  120. package/bundle/{chunk-NT3OBORC.js → chunk-S54DBUZ4.js} +10 -9
  121. package/bundle/{chunk-NT3OBORC.js.map → chunk-S54DBUZ4.js.map} +1 -1
  122. package/bundle/{chunk-CWOHNFUV.js → chunk-SY67HM2Y.js} +3 -2
  123. package/bundle/{chunk-CWOHNFUV.js.map → chunk-SY67HM2Y.js.map} +1 -1
  124. package/bundle/{chunk-BQ2L4GMG.js → chunk-TBLYGCPQ.js} +4 -3
  125. package/bundle/{chunk-BQ2L4GMG.js.map → chunk-TBLYGCPQ.js.map} +1 -1
  126. package/bundle/chunk-TCBMBX3Z.js +183 -0
  127. package/bundle/chunk-TCBMBX3Z.js.map +7 -0
  128. package/bundle/chunk-TXRWQIQQ.js +3707 -0
  129. package/bundle/chunk-TXRWQIQQ.js.map +7 -0
  130. package/bundle/chunk-U34CSHFS.js +645 -0
  131. package/bundle/chunk-U34CSHFS.js.map +7 -0
  132. package/bundle/{chunk-CEVRHKJY.js → chunk-UDZIZB5F.js} +6 -5
  133. package/bundle/{chunk-CEVRHKJY.js.map → chunk-UDZIZB5F.js.map} +1 -1
  134. package/bundle/{chunk-W6FAL35D.js → chunk-VA5WKN3Z.js} +7 -6
  135. package/bundle/{chunk-W6FAL35D.js.map → chunk-VA5WKN3Z.js.map} +1 -1
  136. package/bundle/{chunk-X6TERNVJ.js → chunk-WX7GHGFX.js} +10 -9
  137. package/bundle/{chunk-X6TERNVJ.js.map → chunk-WX7GHGFX.js.map} +1 -1
  138. package/bundle/{chunk-PNEDC45Y.js → chunk-XETTJVEU.js} +4 -3
  139. package/bundle/{chunk-PNEDC45Y.js.map → chunk-XETTJVEU.js.map} +1 -1
  140. package/bundle/{chunk-PLCY3GFH.js → chunk-XLLSPBBT.js} +5 -4
  141. package/bundle/{chunk-PLCY3GFH.js.map → chunk-XLLSPBBT.js.map} +1 -1
  142. package/bundle/{chunk-ZXPXCDA6.js → chunk-XOCP5BMO.js} +6 -5
  143. package/bundle/{chunk-ZXPXCDA6.js.map → chunk-XOCP5BMO.js.map} +1 -1
  144. package/bundle/chunk-ZEY6YZAB.js +138 -0
  145. package/bundle/chunk-ZEY6YZAB.js.map +7 -0
  146. package/bundle/{chunk-MW6WDLU7.js → chunk-ZZR3JZHR.js} +10 -9
  147. package/bundle/{chunk-MW6WDLU7.js.map → chunk-ZZR3JZHR.js.map} +1 -1
  148. package/bundle/commands-AIL4XOIZ.js +33 -0
  149. package/bundle/commands-K77NVSXZ.js +32 -0
  150. package/bundle/commands-V6RSVC4Y.js +32 -0
  151. package/bundle/completion-buffer-S3LXDZG2.js +14 -0
  152. package/bundle/config-C6VHRJQ7.js +20 -0
  153. package/bundle/{config-show-ERTATR6E.js → config-show-ZTXX27FW.js} +4 -3
  154. package/bundle/{config-show-ERTATR6E.js.map → config-show-ZTXX27FW.js.map} +1 -1
  155. package/bundle/{context-HCEGZNDC.js → context-OCS7HLJP.js} +5 -4
  156. package/bundle/{context-HCEGZNDC.js.map → context-OCS7HLJP.js.map} +1 -1
  157. package/bundle/daemon-NPKYZ3CJ.js +292 -0
  158. package/bundle/daemon-NPKYZ3CJ.js.map +7 -0
  159. package/bundle/delegation-tools-PF7RD2RW.js +28 -0
  160. package/bundle/{deploy-lib-import-32ZFKHWP.js → deploy-lib-import-ODLDL2DB.js} +5 -4
  161. package/bundle/digital-signature-PNY4TR2W.js +14 -0
  162. package/bundle/{direct-api-transport-YR7SXXNN.js → direct-api-transport-EADHM67Z.js} +21 -20
  163. package/bundle/{direct-api-transport-YR7SXXNN.js.map → direct-api-transport-EADHM67Z.js.map} +1 -1
  164. package/bundle/direct-api-transport-SLJ2Z6NX.js +861 -0
  165. package/bundle/direct-api-transport-SLJ2Z6NX.js.map +7 -0
  166. package/bundle/{discord-adapter-YYWVMPPU.js → discord-adapter-FBJOJSTW.js} +25 -24
  167. package/bundle/{discord-adapter-YYWVMPPU.js.map → discord-adapter-FBJOJSTW.js.map} +1 -1
  168. package/bundle/discord-adapter-IJISVHUE.js +585 -0
  169. package/bundle/discord-adapter-IJISVHUE.js.map +7 -0
  170. package/bundle/discord-adapter-UYOCKRDF.js +586 -0
  171. package/bundle/discord-adapter-UYOCKRDF.js.map +7 -0
  172. package/bundle/{dist-MTMKARCP.js → dist-J3T4XVKX.js} +4 -3
  173. package/bundle/{dist-MTMKARCP.js.map → dist-J3T4XVKX.js.map} +1 -1
  174. package/bundle/{dns-wakeup-27M7D2MR.js → dns-wakeup-RYOCQ6GR.js} +6 -5
  175. package/bundle/{dns-wakeup-27M7D2MR.js.map → dns-wakeup-RYOCQ6GR.js.map} +1 -1
  176. package/bundle/{doctor-QNUSDY73.js → doctor-R54GZPKL.js} +10 -9
  177. package/bundle/{doctor-QNUSDY73.js.map → doctor-R54GZPKL.js.map} +1 -1
  178. package/bundle/{ensure-invariants-NMXNS476.js → ensure-invariants-K2ZUZ6NR.js} +7 -6
  179. package/bundle/{ensure-invariants-NMXNS476.js.map → ensure-invariants-K2ZUZ6NR.js.map} +1 -1
  180. package/bundle/ensure-invariants-KUXIW73S.js +50 -0
  181. package/bundle/ensure-invariants-KUXIW73S.js.map +7 -0
  182. package/bundle/env-schema-DGD6QWPA.js +20 -0
  183. package/bundle/{esm-DDP6NCZG.js → esm-PFOJARXA.js} +5 -4
  184. package/bundle/{esm-DDP6NCZG.js.map → esm-PFOJARXA.js.map} +1 -1
  185. package/bundle/{fallback-policy-L4QV2PEJ.js → fallback-policy-SR6ED5I3.js} +4 -3
  186. package/bundle/{fallback-policy-L4QV2PEJ.js.map → fallback-policy-SR6ED5I3.js.map} +1 -1
  187. package/bundle/{health-check-SPA7NT6N.js → health-check-RJ2SUJYL.js} +4 -3
  188. package/bundle/{health-check-SPA7NT6N.js.map → health-check-RJ2SUJYL.js.map} +1 -1
  189. package/bundle/hook-system-POI5VRIX.js +18 -0
  190. package/bundle/hotskills-6ECHLXTJ.js +13 -0
  191. package/bundle/install-24XR5FO5.js +13 -0
  192. package/bundle/install-AJ7VW76P.js +13 -0
  193. package/bundle/{install-log-IAPHYKD4.js → install-log-Q6RUHKWC.js} +4 -3
  194. package/bundle/{install-log-IAPHYKD4.js.map → install-log-Q6RUHKWC.js.map} +1 -1
  195. package/bundle/{install-manifest-SPQRUNXL.js → install-manifest-MCJCAYSR.js} +9 -7
  196. package/bundle/install-manifest-MCJCAYSR.js.map +7 -0
  197. package/bundle/install-manifest-ZETY4AFS.js +104 -0
  198. package/bundle/install-manifest-ZETY4AFS.js.map +7 -0
  199. package/bundle/{install-validate-PVLZXYLQ.js → install-validate-H74LUCE2.js} +4 -3
  200. package/bundle/{install-validate-PVLZXYLQ.js.map → install-validate-H74LUCE2.js.map} +1 -1
  201. package/bundle/{irc-adapter-OI5UZSQF.js → irc-adapter-RKRUSZXB.js} +7 -6
  202. package/bundle/{irc-adapter-OI5UZSQF.js.map → irc-adapter-RKRUSZXB.js.map} +1 -1
  203. package/bundle/{irc-config-55YO6EGB.js → irc-config-6VY67UPQ.js} +8 -7
  204. package/bundle/{irc-config-55YO6EGB.js.map → irc-config-6VY67UPQ.js.map} +1 -1
  205. package/bundle/{logs-ZNYXX5PA.js → logs-EK4HYRKR.js} +4 -3
  206. package/bundle/{logs-ZNYXX5PA.js.map → logs-EK4HYRKR.js.map} +1 -1
  207. package/bundle/{media-utils-XNNDTYFI.js → media-utils-QBY5WBF3.js} +8 -7
  208. package/bundle/{media-utils-XNNDTYFI.js.map → media-utils-QBY5WBF3.js.map} +1 -1
  209. package/bundle/message-pipeline-ANSMPK5O.js +34 -0
  210. package/bundle/message-pipeline-HXZMRGXZ.js +34 -0
  211. package/bundle/message-pipeline-XUUTGPFH.js +35 -0
  212. package/bundle/meta.json +1828 -1650
  213. package/bundle/model-health-registry-7ECZFCW4.js +12 -0
  214. package/bundle/model-health-registry-LDC76RPP.js +12 -0
  215. package/bundle/notification-OJ4YE4VG.js +14 -0
  216. package/bundle/{openrouter-credits-EDY7ETAU.js → openrouter-credits-L45SYKT3.js} +7 -6
  217. package/bundle/{openrouter-credits-EDY7ETAU.js.map → openrouter-credits-L45SYKT3.js.map} +1 -1
  218. package/bundle/{passwd-RRFV4CC5.js → passwd-QSHZJ2CG.js} +4 -3
  219. package/bundle/{passwd-RRFV4CC5.js.map → passwd-QSHZJ2CG.js.map} +1 -1
  220. package/bundle/paths-ZJYIDND2.js +18 -0
  221. package/bundle/{peer-client-52XYMNI7.js → peer-client-T44VI7NB.js} +13 -12
  222. package/bundle/{peer-client-52XYMNI7.js.map → peer-client-T44VI7NB.js.map} +1 -1
  223. package/bundle/peer-config-D5A4454H.js +17 -0
  224. package/bundle/{peer-sessions-EAXTNQ36.js → peer-sessions-MY2YVXHC.js} +4 -3
  225. package/bundle/{peer-sessions-EAXTNQ36.js.map → peer-sessions-MY2YVXHC.js.map} +1 -1
  226. package/bundle/{pending-callback-RIMQZ7FJ.js → pending-callback-6KLBSHLX.js} +4 -3
  227. package/bundle/{pending-callback-RIMQZ7FJ.js.map → pending-callback-6KLBSHLX.js.map} +1 -1
  228. package/bundle/phase-transport-43NP5XBK.js +23 -0
  229. package/bundle/phase-transport-GNUZI6EW.js +23 -0
  230. package/bundle/phase-transport-Q7K6V3VZ.js +23 -0
  231. package/bundle/phase-transport-SLJXIAY5.js +23 -0
  232. package/bundle/{responses-adapter-AAQTY3K4.js → responses-adapter-DAV2JUL7.js} +4 -3
  233. package/bundle/{responses-adapter-AAQTY3K4.js.map → responses-adapter-DAV2JUL7.js.map} +1 -1
  234. package/bundle/{restore-ZE3SEPSS.js → restore-ROJF22R2.js} +5 -4
  235. package/bundle/{restore-ZE3SEPSS.js.map → restore-ROJF22R2.js.map} +1 -1
  236. package/bundle/{self-healer-utils-DMUUXC47.js → self-healer-utils-7NFH22VJ.js} +7 -6
  237. package/bundle/{self-healer-utils-DMUUXC47.js.map → self-healer-utils-7NFH22VJ.js.map} +1 -1
  238. package/bundle/skill-stats-IPVKMWN3.js +23 -0
  239. package/bundle/sleep-4NVWZHVN.js +20 -0
  240. package/bundle/soul-bundle-7EYTEKFE.js +15 -0
  241. package/bundle/soul-loader-7FN7WDHM.js +18 -0
  242. package/bundle/soul-loader-K237NP4T.js +17 -0
  243. package/bundle/soul-loader-K237NP4T.js.map +7 -0
  244. package/bundle/soul-loader-UVJ6HZM3.js +17 -0
  245. package/bundle/soul-loader-UVJ6HZM3.js.map +7 -0
  246. package/bundle/src-Z3WR7SRT.js +9 -0
  247. package/bundle/src-Z3WR7SRT.js.map +7 -0
  248. package/bundle/{sse-parser-anthropic-P7CE2MH2.js → sse-parser-anthropic-H42TTLBD.js} +7 -6
  249. package/bundle/{sse-parser-anthropic-P7CE2MH2.js.map → sse-parser-anthropic-H42TTLBD.js.map} +1 -1
  250. package/bundle/{sse-parser-responses-EQQA5FWN.js → sse-parser-responses-WG2LY2ML.js} +7 -6
  251. package/bundle/{sse-parser-responses-EQQA5FWN.js.map → sse-parser-responses-WG2LY2ML.js.map} +1 -1
  252. package/bundle/{ssrf-guard-FZCBYIVW.js → ssrf-guard-E2KBBC5E.js} +7 -6
  253. package/bundle/{ssrf-guard-FZCBYIVW.js.map → ssrf-guard-E2KBBC5E.js.map} +1 -1
  254. package/bundle/{start-FH3GRMJ4.js → start-4IWBKLWO.js} +4 -3
  255. package/bundle/{start-FH3GRMJ4.js.map → start-4IWBKLWO.js.map} +1 -1
  256. package/bundle/{stream-single-WSG4D53C.js → stream-single-RFJNUTL6.js} +4 -3
  257. package/bundle/{stream-single-WSG4D53C.js.map → stream-single-RFJNUTL6.js.map} +1 -1
  258. package/bundle/stt-CF3CPFDC.js +15 -0
  259. package/bundle/stt-CF3CPFDC.js.map +7 -0
  260. package/bundle/subagent-runtime-P7GCFBM3.js +13 -0
  261. package/bundle/subagent-runtime-P7GCFBM3.js.map +7 -0
  262. package/bundle/subagent-runtime-USNPO4WF.js +13 -0
  263. package/bundle/subagent-runtime-USNPO4WF.js.map +7 -0
  264. package/bundle/subagent-runtime-XS2ZXYOZ.js +13 -0
  265. package/bundle/subagent-runtime-XS2ZXYOZ.js.map +7 -0
  266. package/bundle/{system-message-T5R3EYYN.js → system-message-TALP6GP2.js} +6 -5
  267. package/bundle/{system-message-T5R3EYYN.js.map → system-message-TALP6GP2.js.map} +1 -1
  268. package/bundle/{system-status-KQ6KHFJ6.js → system-status-2CR5OUDY.js} +10 -9
  269. package/bundle/{system-status-KQ6KHFJ6.js.map → system-status-2CR5OUDY.js.map} +1 -1
  270. package/bundle/task-store-KIBFZL5A.js +23 -0
  271. package/bundle/task-store-KIBFZL5A.js.map +7 -0
  272. package/bundle/{telegram-adapter-2V3XUMT5.js → telegram-adapter-ISQRW7PN.js} +34 -33
  273. package/bundle/{telegram-adapter-2V3XUMT5.js.map → telegram-adapter-ISQRW7PN.js.map} +1 -1
  274. package/bundle/telegram-adapter-QCD7AG5D.js +1062 -0
  275. package/bundle/telegram-adapter-QCD7AG5D.js.map +7 -0
  276. package/bundle/telegram-adapter-Y3PVA25S.js +1061 -0
  277. package/bundle/telegram-adapter-Y3PVA25S.js.map +7 -0
  278. package/bundle/telegram-adapter-YAXSK2RT.js +1062 -0
  279. package/bundle/telegram-adapter-YAXSK2RT.js.map +7 -0
  280. package/bundle/tool-registry-DFCCGZCB.js +39 -0
  281. package/bundle/tool-registry-DFCCGZCB.js.map +7 -0
  282. package/bundle/tool-sandbox-OZMXJZLQ.js +21 -0
  283. package/bundle/tool-sandbox-OZMXJZLQ.js.map +7 -0
  284. package/bundle/{transport-config-YLXU33RO.js → transport-config-ANPS2RYT.js} +11 -10
  285. package/bundle/transport-config-ANPS2RYT.js.map +7 -0
  286. package/bundle/update-check-O5MS6B3L.js +13 -0
  287. package/bundle/update-check-O5MS6B3L.js.map +7 -0
  288. package/bundle/usage-tracker-S4Z2G2K5.js +18 -0
  289. package/bundle/usage-tracker-S4Z2G2K5.js.map +7 -0
  290. package/bundle/user-registry-GTAJIW6E.js +17 -0
  291. package/bundle/user-registry-GTAJIW6E.js.map +7 -0
  292. package/config/.env +2 -0
  293. package/config/auto-fix.json +14 -0
  294. package/config/irc.json.example +30 -0
  295. package/config/models.json.example +229 -0
  296. package/config/peers.json.example +12 -0
  297. package/config/schemas/irc.schema.json +42 -0
  298. package/config/schemas/models.schema.json +17 -0
  299. package/config/schemas/peers.schema.json +35 -0
  300. package/config/schemas/transport.schema.json +35 -0
  301. package/config/schemas/users.schema.json +22 -0
  302. package/config/transport.default.json +30 -0
  303. package/config/transport.json.example +102 -0
  304. package/config/users.json.example +11 -0
  305. package/install-manifest.json +148 -0
  306. package/package.json +4 -2
  307. package/scripts/abtars-daemon.service +1 -0
  308. package/scripts/watchdog.sh +1 -1
  309. package/bundle/_registry.generated-M4WY2MMI.js +0 -35
  310. package/bundle/agent-registry-LT4JNQH6.js +0 -18
  311. package/bundle/browse-delivery-JXBY36GK.js +0 -17
  312. package/bundle/browser-ELNDVPLC.js +0 -18
  313. package/bundle/capability-CIL3G4FI.js +0 -17
  314. package/bundle/chunk-5R2ANXQ7.js +0 -510
  315. package/bundle/chunk-5R2ANXQ7.js.map +0 -7
  316. package/bundle/chunk-6UCRKRWR.js.map +0 -7
  317. package/bundle/chunk-M6VBAPNT.js +0 -16
  318. package/bundle/chunk-OP7BTAWY.js +0 -29
  319. package/bundle/chunk-UCQ2WC3B.js.map +0 -7
  320. package/bundle/chunk-XREWVCUO.js.map +0 -7
  321. package/bundle/chunk-Y6XAEX2Q.js.map +0 -7
  322. package/bundle/commands-BHVUOU3V.js +0 -31
  323. package/bundle/completion-buffer-P253ONKF.js +0 -13
  324. package/bundle/config-RGSDAPZN.js +0 -19
  325. package/bundle/delegation-tools-GYTS2D6A.js +0 -27
  326. package/bundle/digital-signature-OFCGSHWO.js +0 -13
  327. package/bundle/env-schema-2KBHBDGN.js +0 -19
  328. package/bundle/hook-system-6Q5YTR53.js +0 -17
  329. package/bundle/hotskills-K7BM4YLB.js +0 -12
  330. package/bundle/install-6HRZVKUM.js +0 -15
  331. package/bundle/install-manifest-SPQRUNXL.js.map +0 -7
  332. package/bundle/message-pipeline-LLH5SYMO.js +0 -33
  333. package/bundle/model-health-registry-35LQNVQR.js +0 -11
  334. package/bundle/notification-Y5S5MMLV.js +0 -13
  335. package/bundle/paths-G33RZWZ7.js +0 -17
  336. package/bundle/peer-config-VK6EDLN5.js +0 -16
  337. package/bundle/phase-transport-KYERDL2O.js +0 -22
  338. package/bundle/skill-stats-LLEXEXLR.js +0 -22
  339. package/bundle/sleep-OYIUOVQD.js +0 -19
  340. package/bundle/soul-loader-54WCVNLJ.js +0 -16
  341. package/bundle/src-JL4PVO23.js +0 -8
  342. package/bundle/stt-2UH3RITX.js +0 -14
  343. package/bundle/subagent-runtime-LE2ZXH3G.js +0 -12
  344. package/bundle/task-store-K7CQDEPI.js +0 -22
  345. package/bundle/tool-registry-MU3OX4UI.js +0 -38
  346. package/bundle/tool-sandbox-VYOK4ZOA.js +0 -20
  347. package/bundle/update-QCW5LXRN.js +0 -13
  348. package/bundle/update-check-27KZSAP6.js +0 -12
  349. package/bundle/usage-tracker-OVVEVMOY.js +0 -17
  350. package/bundle/user-registry-D4SD73UV.js +0 -16
  351. /package/bundle/{agent-registry-LT4JNQH6.js.map → agent-registry-5M77ZOMV.js.map} +0 -0
  352. /package/bundle/{bridge-lock-transport-4AC2G5G6.js.map → agent-registry-VJMNIQ5W.js.map} +0 -0
  353. /package/bundle/{browse-delivery-JXBY36GK.js.map → bridge-lock-transport-HO545SBK.js.map} +0 -0
  354. /package/bundle/{browser-ELNDVPLC.js.map → browse-delivery-64GQIUHG.js.map} +0 -0
  355. /package/bundle/{capability-CIL3G4FI.js.map → browser-EXR5OQGK.js.map} +0 -0
  356. /package/bundle/{chunk-NWDBD4PA.js.map → capability-HIE7UGFU.js.map} +0 -0
  357. /package/bundle/{commands-BHVUOU3V.js.map → chunk-7K2YZTLD.js.map} +0 -0
  358. /package/bundle/{completion-buffer-P253ONKF.js.map → commands-AIL4XOIZ.js.map} +0 -0
  359. /package/bundle/{config-RGSDAPZN.js.map → commands-K77NVSXZ.js.map} +0 -0
  360. /package/bundle/{delegation-tools-GYTS2D6A.js.map → commands-V6RSVC4Y.js.map} +0 -0
  361. /package/bundle/{deploy-lib-import-32ZFKHWP.js.map → completion-buffer-S3LXDZG2.js.map} +0 -0
  362. /package/bundle/{digital-signature-OFCGSHWO.js.map → config-C6VHRJQ7.js.map} +0 -0
  363. /package/bundle/{env-schema-2KBHBDGN.js.map → delegation-tools-PF7RD2RW.js.map} +0 -0
  364. /package/bundle/{hook-system-6Q5YTR53.js.map → deploy-lib-import-ODLDL2DB.js.map} +0 -0
  365. /package/bundle/{hotskills-K7BM4YLB.js.map → digital-signature-PNY4TR2W.js.map} +0 -0
  366. /package/bundle/{install-6HRZVKUM.js.map → env-schema-DGD6QWPA.js.map} +0 -0
  367. /package/bundle/{message-pipeline-LLH5SYMO.js.map → hook-system-POI5VRIX.js.map} +0 -0
  368. /package/bundle/{model-health-registry-35LQNVQR.js.map → hotskills-6ECHLXTJ.js.map} +0 -0
  369. /package/bundle/{notification-Y5S5MMLV.js.map → install-24XR5FO5.js.map} +0 -0
  370. /package/bundle/{paths-G33RZWZ7.js.map → install-AJ7VW76P.js.map} +0 -0
  371. /package/bundle/{peer-config-VK6EDLN5.js.map → message-pipeline-ANSMPK5O.js.map} +0 -0
  372. /package/bundle/{phase-transport-KYERDL2O.js.map → message-pipeline-HXZMRGXZ.js.map} +0 -0
  373. /package/bundle/{skill-stats-LLEXEXLR.js.map → message-pipeline-XUUTGPFH.js.map} +0 -0
  374. /package/bundle/{sleep-OYIUOVQD.js.map → model-health-registry-7ECZFCW4.js.map} +0 -0
  375. /package/bundle/{soul-loader-54WCVNLJ.js.map → model-health-registry-LDC76RPP.js.map} +0 -0
  376. /package/bundle/{src-JL4PVO23.js.map → notification-OJ4YE4VG.js.map} +0 -0
  377. /package/bundle/{stt-2UH3RITX.js.map → paths-ZJYIDND2.js.map} +0 -0
  378. /package/bundle/{subagent-runtime-LE2ZXH3G.js.map → peer-config-D5A4454H.js.map} +0 -0
  379. /package/bundle/{task-store-K7CQDEPI.js.map → phase-transport-43NP5XBK.js.map} +0 -0
  380. /package/bundle/{tool-registry-MU3OX4UI.js.map → phase-transport-GNUZI6EW.js.map} +0 -0
  381. /package/bundle/{tool-sandbox-VYOK4ZOA.js.map → phase-transport-Q7K6V3VZ.js.map} +0 -0
  382. /package/bundle/{transport-config-YLXU33RO.js.map → phase-transport-SLJXIAY5.js.map} +0 -0
  383. /package/bundle/{update-QCW5LXRN.js.map → skill-stats-IPVKMWN3.js.map} +0 -0
  384. /package/bundle/{update-check-27KZSAP6.js.map → sleep-4NVWZHVN.js.map} +0 -0
  385. /package/bundle/{usage-tracker-OVVEVMOY.js.map → soul-bundle-7EYTEKFE.js.map} +0 -0
  386. /package/bundle/{user-registry-D4SD73UV.js.map → soul-loader-7FN7WDHM.js.map} +0 -0
@@ -0,0 +1,1062 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
3
+ import {
4
+ BOT_COMMANDS,
5
+ ResponseFormatter,
6
+ SecurityGate,
7
+ emojiToScore
8
+ } from "./chunk-R36WIOYX.js";
9
+ import {
10
+ cleanResponse,
11
+ formatReactionSignal,
12
+ handleInboundMessage,
13
+ resetAndPrepare,
14
+ routeReaction
15
+ } from "./chunk-DY3R7LDW.js";
16
+ import "./chunk-NIRYBWUW.js";
17
+ import "./chunk-3MO2MDXJ.js";
18
+ import "./chunk-WX7GHGFX.js";
19
+ import "./chunk-RWUINZUQ.js";
20
+ import "./chunk-P56PLAIC.js";
21
+ import {
22
+ loadUsers
23
+ } from "./chunk-J5YIMCLT.js";
24
+ import "./chunk-JAJ3DUQ2.js";
25
+ import "./chunk-G6IXMYIO.js";
26
+ import "./chunk-UDZIZB5F.js";
27
+ import "./chunk-XLLSPBBT.js";
28
+ import "./chunk-MZWMYN4O.js";
29
+ import {
30
+ init_log_and_swallow,
31
+ logAndSwallow
32
+ } from "./chunk-EX2SRTUE.js";
33
+ import {
34
+ getEnv,
35
+ init_env_schema
36
+ } from "./chunk-AQVOAQQI.js";
37
+ import {
38
+ init_logger,
39
+ logDebug,
40
+ logError,
41
+ logInfo,
42
+ logWarn
43
+ } from "./chunk-2BY6I4P5.js";
44
+ import {
45
+ abtarsHome,
46
+ init_paths
47
+ } from "./chunk-MJ6PHMOK.js";
48
+ import "./chunk-7K2YZTLD.js";
49
+
50
+ // src/platforms/telegram/telegram-adapter.ts
51
+ init_paths();
52
+
53
+ // src/platforms/telegram/telegram-api.ts
54
+ init_env_schema();
55
+ init_logger();
56
+ init_log_and_swallow();
57
+ import { readFileSync } from "node:fs";
58
+ import { basename } from "node:path";
59
+ var TAG = "telegram-api";
60
+ var TelegramApi = class _TelegramApi {
61
+ baseUrl;
62
+ token;
63
+ constructor(botToken) {
64
+ this.token = botToken;
65
+ this.baseUrl = `https://api.telegram.org/bot${botToken}`;
66
+ }
67
+ /** Get bot info. */
68
+ async getMe() {
69
+ const res = await this.call("getMe", {});
70
+ return res;
71
+ }
72
+ async getChat(chatId) {
73
+ const res = await this.call("getChat", { chat_id: chatId });
74
+ return res;
75
+ }
76
+ /** Get file path for downloading. */
77
+ async getFile(fileId) {
78
+ const res = await this.call("getFile", { file_id: fileId });
79
+ return res;
80
+ }
81
+ /** Download a file by its file_path (from getFile). Returns the raw buffer. */
82
+ async downloadFile(filePath) {
83
+ const url = `https://api.telegram.org/file/bot${this.token}/${filePath}`;
84
+ const response = await this.fetchWithRetry(
85
+ (signal) => fetch(url, { signal }),
86
+ { method: "downloadFile", timeoutMs: getEnv().telegramFileTimeoutMs, retryable4xx: false }
87
+ );
88
+ const arrayBuffer = await response.arrayBuffer();
89
+ return Buffer.from(arrayBuffer);
90
+ }
91
+ /** Send a text message. Returns the sent message_id. */
92
+ async sendMessage(chatId, text, options) {
93
+ const body = { chat_id: chatId, text, ...options };
94
+ const res = await this.call("sendMessage", body);
95
+ return res.message_id;
96
+ }
97
+ /** Edit an existing message's text. */
98
+ async editMessageText(chatId, messageId, text, options) {
99
+ await this.call("editMessageText", { chat_id: chatId, message_id: messageId, text, ...options });
100
+ }
101
+ /** Acknowledge a callback query (inline keyboard press). */
102
+ async answerCallbackQuery(callbackQueryId) {
103
+ await this.call("answerCallbackQuery", { callback_query_id: callbackQueryId });
104
+ }
105
+ /** Send a chat action (typing indicator, etc.). */
106
+ async sendChatAction(chatId, action = "typing", messageThreadId) {
107
+ const body = { chat_id: chatId, action };
108
+ if (messageThreadId) body.message_thread_id = messageThreadId;
109
+ await this.call("sendChatAction", body);
110
+ }
111
+ /** Set an emoji reaction on a message. Pass empty array to remove. */
112
+ async setMessageReaction(chatId, messageId, reaction) {
113
+ await this.call("setMessageReaction", {
114
+ chat_id: chatId,
115
+ message_id: messageId,
116
+ reaction
117
+ });
118
+ }
119
+ /** Send a voice note (OGG Opus). Returns the sent message_id. */
120
+ async sendVoice(chatId, audioBuffer, options) {
121
+ const makeForm = () => {
122
+ const form = new FormData();
123
+ form.append("chat_id", String(chatId));
124
+ const blob = new Blob([audioBuffer], { type: "audio/webm" });
125
+ form.append("voice", blob, "voice.webm");
126
+ if (options?.message_thread_id) form.append("message_thread_id", String(options.message_thread_id));
127
+ return form;
128
+ };
129
+ const response = await this.fetchWithRetry(
130
+ (signal) => fetch(`${this.baseUrl}/sendVoice`, { method: "POST", body: makeForm(), signal }),
131
+ { method: "sendVoice" }
132
+ );
133
+ const json = await response.json();
134
+ if (!json.ok) throw new Error("Telegram API sendVoice returned ok=false");
135
+ return json.result.message_id;
136
+ }
137
+ /** Send a file from disk as a Telegram document. Returns the sent message_id. */
138
+ async sendDocument(chatId, filePath, caption, options) {
139
+ const buf = readFileSync(filePath);
140
+ const fileName = basename(filePath);
141
+ const makeForm = () => {
142
+ const form = new FormData();
143
+ form.append("chat_id", String(chatId));
144
+ const blob = new Blob([buf], { type: "text/markdown" });
145
+ form.append("document", blob, fileName);
146
+ if (caption) form.append("caption", caption.slice(0, 1024));
147
+ if (options?.message_thread_id) form.append("message_thread_id", String(options.message_thread_id));
148
+ return form;
149
+ };
150
+ const response = await this.fetchWithRetry(
151
+ (signal) => fetch(`${this.baseUrl}/sendDocument`, { method: "POST", body: makeForm(), signal }),
152
+ { method: "sendDocument", timeoutMs: getEnv().telegramFileTimeoutMs }
153
+ );
154
+ const json = await response.json();
155
+ if (!json.ok) throw new Error("Telegram API sendDocument returned ok=false");
156
+ return json.result.message_id;
157
+ }
158
+ /** Register bot command menu (shown when user types /). */
159
+ async setMyCommands(commands) {
160
+ await this.call("setMyCommands", { commands });
161
+ }
162
+ /** Long-poll for updates. */
163
+ async getUpdates(offset, timeout, signal) {
164
+ const body = {
165
+ offset,
166
+ timeout,
167
+ allowed_updates: [
168
+ "message",
169
+ "callback_query",
170
+ "message_reaction"
171
+ ]
172
+ };
173
+ return await this.call("getUpdates", body, signal, (timeout + 10) * 1e3);
174
+ }
175
+ static MAX_ATTEMPTS = 3;
176
+ static BACKOFF = [1e3, 3e3, 9e3];
177
+ static PERMANENT_ERRORS = [
178
+ /chat not found/i,
179
+ /bot was blocked/i,
180
+ /user is deactivated/i,
181
+ /chat_id is empty/i,
182
+ /forbidden/i,
183
+ /not enough rights/i,
184
+ /CHAT_WRITE_FORBIDDEN/i,
185
+ /have no rights/i,
186
+ /wrong file_path/i,
187
+ /file is temporarily unavailable/i
188
+ ];
189
+ static isPermanent(msg) {
190
+ return this.PERMANENT_ERRORS.some((re) => re.test(msg));
191
+ }
192
+ static isTransient(msg) {
193
+ return /429|5\d\d|bad gateway|service unavailable|timeout|timed out|ETIMEDOUT|ECONNRESET|ECONNREFUSED|socket hang up|network/i.test(msg);
194
+ }
195
+ /**
196
+ * Retry + timeout wrapper for any Telegram fetch. Returns the Response on 2xx,
197
+ * throws on non-OK or transient-exhaustion. Factory MUST build a fresh request
198
+ * per attempt (required for FormData; single-use in some runtimes).
199
+ */
200
+ async fetchWithRetry(requestFn, opts) {
201
+ const timeoutMs = opts.timeoutMs ?? getEnv().telegramTimeoutMs;
202
+ for (let attempt = 0; attempt < _TelegramApi.MAX_ATTEMPTS; attempt++) {
203
+ const ctrl = new AbortController();
204
+ const timer = setTimeout(() => ctrl.abort(new Error("telegram timeout")), timeoutMs);
205
+ const composed = opts.outerSignal ? AbortSignal.any([opts.outerSignal, ctrl.signal]) : ctrl.signal;
206
+ try {
207
+ const response = await requestFn(composed);
208
+ if (!response.ok) {
209
+ const text = await response.text().catch((err2) => {
210
+ logAndSwallow(TAG, "read TG API error body", err2);
211
+ return "";
212
+ });
213
+ const err = new Error(`Telegram API ${opts.method} failed (${response.status}): ${text}`);
214
+ if (response.status >= 400 && response.status < 500 && !opts.retryable4xx) throw err;
215
+ throw err;
216
+ }
217
+ return response;
218
+ } catch (err) {
219
+ const msg = err instanceof Error ? err.message : String(err);
220
+ if (_TelegramApi.isPermanent(msg) || opts.outerSignal?.aborted) throw err;
221
+ if (!opts.retryable4xx && /failed \([4]\d\d\)/.test(msg)) throw err;
222
+ if (attempt < _TelegramApi.MAX_ATTEMPTS - 1 && _TelegramApi.isTransient(msg)) {
223
+ logDebug(TAG, `${opts.method} attempt ${attempt + 1}/${_TelegramApi.MAX_ATTEMPTS} \u2014 ${msg.slice(0, 80)}`);
224
+ await new Promise((r) => setTimeout(r, _TelegramApi.BACKOFF[attempt]));
225
+ continue;
226
+ }
227
+ throw err;
228
+ } finally {
229
+ clearTimeout(timer);
230
+ }
231
+ }
232
+ throw new Error(`Telegram API ${opts.method}: unreachable`);
233
+ }
234
+ async call(method, body, signal, timeoutMs) {
235
+ const response = await this.fetchWithRetry(
236
+ (composed) => fetch(`${this.baseUrl}/${method}`, {
237
+ method: "POST",
238
+ headers: { "Content-Type": "application/json" },
239
+ body: JSON.stringify(body),
240
+ signal: composed
241
+ }),
242
+ { method, timeoutMs, outerSignal: signal }
243
+ );
244
+ const json = await response.json();
245
+ if (!json.ok) throw new Error(`Telegram API ${method} returned ok=false`);
246
+ return json.result;
247
+ }
248
+ };
249
+
250
+ // src/platforms/telegram/telegram-poller.ts
251
+ init_logger();
252
+ var TelegramPoller = class {
253
+ api;
254
+ pollTimeout;
255
+ onUpdate;
256
+ offsetStore;
257
+ offset = 0;
258
+ running = false;
259
+ abortController = null;
260
+ /** Timestamp of last successful poll cycle. */
261
+ lastPollAt = Date.now();
262
+ constructor(api, pollTimeoutS, onUpdate, offsetStore) {
263
+ this.api = api;
264
+ this.pollTimeout = pollTimeoutS;
265
+ this.onUpdate = onUpdate;
266
+ this.offsetStore = offsetStore ?? { read: async () => 0, write: async () => {
267
+ } };
268
+ }
269
+ /** Start the long-poll loop. Non-blocking — runs in background. */
270
+ async start() {
271
+ if (this.running) return;
272
+ this.offset = await this.offsetStore.read();
273
+ this.running = true;
274
+ this.poll().catch((err) => {
275
+ logError("poller", "Fatal error in poll loop", err);
276
+ });
277
+ }
278
+ /** Stop polling. Cancels any in-flight request. */
279
+ stop() {
280
+ this.running = false;
281
+ this.abortController?.abort();
282
+ this.abortController = null;
283
+ }
284
+ /** Inject a synthetic update into the handler (used for queued messages after sleep). */
285
+ injectUpdate(update) {
286
+ void this.onUpdate(update);
287
+ }
288
+ async poll() {
289
+ let failures = 0;
290
+ while (this.running) {
291
+ try {
292
+ this.abortController = new AbortController();
293
+ const updates = await this.api.getUpdates(
294
+ this.offset,
295
+ this.pollTimeout,
296
+ this.abortController.signal
297
+ );
298
+ failures = 0;
299
+ this.lastPollAt = Date.now();
300
+ if (updates.length > 0) {
301
+ const sorted = [...updates].sort((a, b) => a.update_id - b.update_id);
302
+ for (const update of sorted) {
303
+ try {
304
+ const result = this.onUpdate(update);
305
+ if (result instanceof Promise) {
306
+ result.catch((err) => logError("poller", "Error in update handler", err));
307
+ }
308
+ } catch (err) {
309
+ logError("poller", "Error in update handler (sync)", err);
310
+ }
311
+ }
312
+ this.offset = sorted[sorted.length - 1].update_id + 1;
313
+ await this.offsetStore.write(this.offset);
314
+ }
315
+ } catch (err) {
316
+ if (!this.running) break;
317
+ failures++;
318
+ const baseDelay = Math.min(2 ** failures * 1e3, 6e4);
319
+ const jitter = Math.random() * baseDelay;
320
+ const delay = baseDelay + jitter;
321
+ const is409 = String(err).includes("409") || String(err).includes("terminated by other getUpdates");
322
+ const log = is409 ? failures >= 50 ? logError : logWarn : failures < 3 ? logWarn : logError;
323
+ if (is409 && failures < 50) {
324
+ log("poller", `409 conflict (attempt ${failures}) \u2014 another instance running, backing off`);
325
+ } else {
326
+ log("poller", `Error (attempt ${failures}), retrying in ${Math.round(delay)}ms`, err);
327
+ }
328
+ await sleep(delay);
329
+ }
330
+ }
331
+ }
332
+ };
333
+ function sleep(ms) {
334
+ return new Promise((resolve) => setTimeout(resolve, ms));
335
+ }
336
+
337
+ // src/platforms/telegram/offset-store.ts
338
+ init_log_and_swallow();
339
+ import { readFile, writeFile, rename, mkdir } from "node:fs/promises";
340
+ import { dirname } from "node:path";
341
+ var TAG2 = "offset_store";
342
+ function createFileOffsetStore(filePath) {
343
+ let pending = Promise.resolve();
344
+ return {
345
+ async read() {
346
+ try {
347
+ const raw = await readFile(filePath, "utf-8");
348
+ const val = parseInt(raw.trim(), 10);
349
+ return Number.isFinite(val) ? val : 0;
350
+ } catch (err) {
351
+ logAndSwallow(TAG2, "read offset file", err);
352
+ return 0;
353
+ }
354
+ },
355
+ write(offset) {
356
+ pending = pending.then(async () => {
357
+ const tmp = filePath + ".tmp";
358
+ await mkdir(dirname(filePath), { recursive: true });
359
+ await writeFile(tmp, String(offset), "utf-8");
360
+ await rename(tmp, filePath);
361
+ }).catch((err) => logAndSwallow(TAG2, "write offset file", err));
362
+ return pending;
363
+ }
364
+ };
365
+ }
366
+
367
+ // src/platforms/telegram/telegram-adapter.ts
368
+ init_logger();
369
+ init_log_and_swallow();
370
+
371
+ // src/platforms/telegram/telegram-model-picker.ts
372
+ init_env_schema();
373
+ init_log_and_swallow();
374
+ var TAG3 = "telegram";
375
+ var MODEL_PREFIXES = ["mb:", "mslot:", "mprov:", "mpos:", "mprov2:", "mset:", "model:"];
376
+ function isModelPickerCallback(data) {
377
+ return MODEL_PREFIXES.some((p) => data.startsWith(p));
378
+ }
379
+ async function handleModelPickerCallback(data, chatId, api, state, deps) {
380
+ if (data.startsWith("mb:")) {
381
+ const target = data.slice(3);
382
+ if (!target) {
383
+ await api.sendMessage(chatId, "\u{1F44C} Cancelled.");
384
+ return;
385
+ }
386
+ if (target === "a") {
387
+ const AGENT_LABELS = [
388
+ { key: "professor", label: "Professor" },
389
+ { key: "dreamy", label: "Dreamy (sleep)" },
390
+ { key: "browsie", label: "Browsie (browse)" },
391
+ { key: "coding", label: "Cody (coding)" }
392
+ ];
393
+ const buttons = AGENT_LABELS.map((a) => [{ text: a.label, callback_data: `mslot:${a.key}` }]);
394
+ buttons.push([{ text: "\u2190 Cancel", callback_data: "mb:" }]);
395
+ await api.sendMessage(chatId, "\u{1F916} Which agent to change?", { reply_markup: { inline_keyboard: buttons } });
396
+ return;
397
+ }
398
+ if (target.startsWith("p:")) {
399
+ const agent = target.slice(2);
400
+ const { loadTransport, resolveAgent, getAvailableProviders, getModelsForProvider } = await import("./transport-config-ANPS2RYT.js");
401
+ const tc = loadTransport();
402
+ if (!tc) {
403
+ await api.sendMessage(chatId, "\u274C transport.json not loaded");
404
+ return;
405
+ }
406
+ let providers = getAvailableProviders(tc).filter((p) => p.config.transport !== "tmux");
407
+ if (providers.length === 0) {
408
+ await api.sendMessage(chatId, "\u274C No compatible providers");
409
+ return;
410
+ }
411
+ const currentProvider = resolveAgent(agent, tc)?.providerName;
412
+ const prefix = agent === "professor" ? "mprov2:professor" : `mprov:${agent}`;
413
+ const buttons = providers.map((p) => {
414
+ const count = getModelsForProvider(p.name).length;
415
+ const label = p.name === currentProvider ? `\u2705 ${p.name} (${count})` : `${p.name} (${count})`;
416
+ return [{ text: label, callback_data: `${prefix}:${p.name}` }];
417
+ });
418
+ buttons.push([{ text: "\u2190 Back", callback_data: "mb:a" }]);
419
+ await api.sendMessage(chatId, `\u{1F50C} Pick provider:`, { reply_markup: { inline_keyboard: buttons } });
420
+ return;
421
+ }
422
+ if (target.startsWith("s:")) {
423
+ const slot = target.slice(2);
424
+ state._pendingSlot = slot;
425
+ const { loadTransport, resolveAgent, getAvailableProviders, getModelsForProvider } = await import("./transport-config-ANPS2RYT.js");
426
+ const tc = loadTransport();
427
+ if (!tc) {
428
+ await api.sendMessage(chatId, "\u274C transport.json not loaded");
429
+ return;
430
+ }
431
+ let providers = getAvailableProviders(tc).filter((p) => p.config.transport !== "tmux");
432
+ const currentProvider = resolveAgent("professor", tc)?.providerName;
433
+ const slotLabel = slot === "professor" ? "Main" : slot.replace("professor_fb", "Fb");
434
+ const buttons = providers.map((p) => {
435
+ const count = getModelsForProvider(p.name).length;
436
+ const label = p.name === currentProvider ? `\u2705 ${p.name} (${count})` : `${p.name} (${count})`;
437
+ return [{ text: label, callback_data: `mprov2:${slot}:${p.name}` }];
438
+ });
439
+ buttons.push([{ text: "\u2190 Back", callback_data: "mslot:professor" }]);
440
+ await api.sendMessage(chatId, `\u{1F50C} Provider for ${slotLabel}:`, { reply_markup: { inline_keyboard: buttons } });
441
+ return;
442
+ }
443
+ } else if (data.startsWith("mslot:")) {
444
+ const agent = data.slice(6);
445
+ const { loadTransport, resolveAgent, getAvailableProviders, getModelsForProvider } = await import("./transport-config-ANPS2RYT.js");
446
+ const tc = loadTransport();
447
+ if (!tc) {
448
+ await api.sendMessage(chatId, "\u274C transport.json not loaded");
449
+ return;
450
+ }
451
+ if (agent === "professor") {
452
+ const profResolved = resolveAgent("professor", tc);
453
+ const fallbacks = tc.agents["professor"]?.fallbacks ?? [];
454
+ const slots = [
455
+ { label: `\u2605 Main: ${profResolved?.model ?? "?"}`, key: `mpos:professor::professor` }
456
+ ];
457
+ for (let i = 0; i < fallbacks.length; i++) {
458
+ slots.push({ label: `\u21B3 Fb${i + 1}: ${fallbacks[i].model}`, key: `mpos:professor::professor_fb${i + 1}` });
459
+ }
460
+ if (fallbacks.length < 3) {
461
+ slots.push({ label: `\u21B3 Fb${fallbacks.length + 1}: (add)`, key: `mpos:professor::professor_fb${fallbacks.length + 1}` });
462
+ }
463
+ const buttons2 = slots.map((s) => [{ text: s.label, callback_data: s.key }]);
464
+ buttons2.push([{ text: "\u2190 Back", callback_data: "mb:a" }]);
465
+ await api.sendMessage(chatId, `\u{1F3AF} Which slot?`, { reply_markup: { inline_keyboard: buttons2 } });
466
+ return;
467
+ }
468
+ let providers = getAvailableProviders(tc).filter((p) => p.config.transport !== "tmux");
469
+ if (providers.length === 0) {
470
+ await api.sendMessage(chatId, "\u274C No compatible providers");
471
+ return;
472
+ }
473
+ const currentProvider = resolveAgent(agent, tc)?.providerName;
474
+ const buttons = providers.map((p) => {
475
+ const count = getModelsForProvider(p.name).length;
476
+ const label = p.name === currentProvider ? `\u2705 ${p.name} (${count})` : `${p.name} (${count})`;
477
+ return [{ text: label, callback_data: `mprov:${agent}:${p.name}` }];
478
+ });
479
+ buttons.push([{ text: "\u2190 Back", callback_data: "mb:a" }]);
480
+ await api.sendMessage(chatId, `\u{1F50C} Pick provider:`, { reply_markup: { inline_keyboard: buttons } });
481
+ } else if (data.startsWith("mprov:")) {
482
+ const [, agent, providerName] = data.split(":");
483
+ const { loadTransport, getModelsForProvider, formatRank, formatCost } = await import("./transport-config-ANPS2RYT.js");
484
+ const tc = loadTransport();
485
+ let models = getModelsForProvider(providerName);
486
+ const providerConfig = tc?.providers[providerName];
487
+ if (providerConfig?.transport === "api") models = models.filter((m) => !m.entry.status || m.entry.status === "alive");
488
+ if (models.length === 0) {
489
+ await api.sendMessage(chatId, `\u274C No alive models for ${providerName}`);
490
+ return;
491
+ }
492
+ state._pendingSlot = agent;
493
+ state._modelPickerCache = models.map((m) => m.id);
494
+ const buttons = models.map((m, i) => [{ text: `${m.id} (${formatRank(m.entry.rank)}, ${formatCost(m.entry.cost)})`, callback_data: `mset:${providerName}:${i}` }]);
495
+ buttons.push([{ text: "\u2190 Back", callback_data: `mb:p:${agent}` }]);
496
+ await api.sendMessage(chatId, `\u{1F4CB} Models on ${providerName}:`, { reply_markup: { inline_keyboard: buttons } });
497
+ } else if (data.startsWith("mpos:")) {
498
+ const [, , , slot] = data.split(":");
499
+ const { loadTransport, resolveAgent, getAvailableProviders, getModelsForProvider } = await import("./transport-config-ANPS2RYT.js");
500
+ const tc = loadTransport();
501
+ if (!tc) {
502
+ await api.sendMessage(chatId, "\u274C transport.json not loaded");
503
+ return;
504
+ }
505
+ let providers = getAvailableProviders(tc).filter((p) => p.config.transport !== "tmux");
506
+ const profResolved = resolveAgent("professor", tc);
507
+ const mainTransport = profResolved?.provider.transport;
508
+ if (slot && slot.startsWith("professor_fb") && mainTransport) {
509
+ if (mainTransport === "api") {
510
+ providers = providers.filter((p) => p.config.transport === "api");
511
+ } else {
512
+ providers = providers.filter((p) => p.name === profResolved.providerName);
513
+ }
514
+ }
515
+ if (providers.length === 0) {
516
+ await api.sendMessage(chatId, "\u274C No compatible providers for this slot");
517
+ return;
518
+ }
519
+ const currentProvider = profResolved?.providerName;
520
+ const slotLabel = slot === "professor" ? "Main" : slot.replace("professor_fb", "Fb");
521
+ const buttons = providers.map((p) => {
522
+ const count = getModelsForProvider(p.name).length;
523
+ const label = p.name === currentProvider ? `\u2705 ${p.name} (${count})` : `${p.name} (${count})`;
524
+ return [{ text: label, callback_data: `mprov2:${slot}:${p.name}` }];
525
+ });
526
+ buttons.push([{ text: "\u2190 Back", callback_data: "mslot:professor" }]);
527
+ await api.sendMessage(chatId, `\u{1F50C} Provider for ${slotLabel}:`, { reply_markup: { inline_keyboard: buttons } });
528
+ } else if (data.startsWith("mprov2:")) {
529
+ const [, slot, providerName] = data.split(":");
530
+ const { getModelsForProvider, formatRank, formatCost, loadTransport } = await import("./transport-config-ANPS2RYT.js");
531
+ const tc = loadTransport();
532
+ const providerConfig = tc?.providers[providerName];
533
+ let models = getModelsForProvider(providerName);
534
+ if (providerConfig?.transport === "api") models = models.filter((m) => !m.entry.status || m.entry.status === "alive");
535
+ if (models.length === 0) {
536
+ await api.sendMessage(chatId, `\u274C No alive models for ${providerName}`);
537
+ return;
538
+ }
539
+ state._pendingSlot = slot;
540
+ const slotLabel = slot === "professor" ? "Main" : slot.replace("professor_fb", "Fb");
541
+ state._modelPickerCache = models.map((m) => m.id);
542
+ const buttons = models.map((m, i) => [{ text: `${m.id} (${formatRank(m.entry.rank)}, ${formatCost(m.entry.cost)})`, callback_data: `mset:${providerName}:${i}` }]);
543
+ buttons.push([{ text: "\u2190 Back", callback_data: `mb:s:${slot}` }]);
544
+ await api.sendMessage(chatId, `\u{1F4CB} Pick model for ${slotLabel}:`, { reply_markup: { inline_keyboard: buttons } });
545
+ } else if (data.startsWith("mset:")) {
546
+ const parts = data.split(":");
547
+ const providerName = parts[1];
548
+ const modelIdx = parseInt(parts[2], 10);
549
+ const model = Number.isFinite(modelIdx) && state._modelPickerCache[modelIdx] ? state._modelPickerCache[modelIdx] : parts.slice(2).join(":");
550
+ const slot = state._pendingSlot ?? "professor";
551
+ state._pendingSlot = void 0;
552
+ state._modelPickerCache = [];
553
+ const { loadTransport, writeTransportConfig, resolveAgent, getModelsForProvider, validateProviderReady, formatValidationError } = await import("./transport-config-ANPS2RYT.js");
554
+ const tc = loadTransport();
555
+ if (!tc) {
556
+ await api.sendMessage(chatId, "\u274C transport.json not loaded");
557
+ return;
558
+ }
559
+ const validModels = getModelsForProvider(providerName);
560
+ if (!validModels.some((m) => m.id === model)) {
561
+ await api.sendMessage(chatId, `\u274C ${model} is not available on ${providerName}. Pick another.`);
562
+ return;
563
+ }
564
+ const providerConfig = tc.providers[providerName];
565
+ if (!providerConfig) {
566
+ await api.sendMessage(chatId, `\u274C Provider ${providerName} not found`);
567
+ return;
568
+ }
569
+ const validation = validateProviderReady(providerName, providerConfig, getEnv());
570
+ if (!validation.ok) {
571
+ await api.sendMessage(chatId, formatValidationError(providerName, validation));
572
+ return;
573
+ }
574
+ if (providerConfig?.transport === "api") {
575
+ try {
576
+ const endpoint = providerConfig.endpoint ?? "";
577
+ const apiKey = getEnv().getApiKey(providerConfig.apiKeyEnv ?? "API_KEY");
578
+ const headers = {};
579
+ if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
580
+ const res = await fetch(`${endpoint}/models`, { headers, signal: AbortSignal.timeout(5e3) });
581
+ if (!res.ok) {
582
+ await api.sendMessage(chatId, `\u26A0\uFE0F ${providerName} unreachable (${res.status}). Try another?`);
583
+ return;
584
+ }
585
+ } catch (err) {
586
+ logAndSwallow(TAG3, "provider reachability check", err);
587
+ await api.sendMessage(chatId, `\u26A0\uFE0F ${providerName} unreachable. Try another?`);
588
+ return;
589
+ }
590
+ }
591
+ const agentKey = slot.startsWith("professor_fb") ? "professor" : slot;
592
+ const fbIndex = slot === "professor_fb1" ? 0 : slot === "professor_fb2" ? 1 : slot === "professor_fb3" ? 2 : -1;
593
+ if (fbIndex >= 0) {
594
+ if (!tc.agents["professor"]) tc.agents["professor"] = { model: "", provider: "" };
595
+ if (!tc.agents["professor"].fallbacks) tc.agents["professor"].fallbacks = [];
596
+ tc.agents["professor"].fallbacks[fbIndex] = { model, provider: providerName };
597
+ const { cleanDemotedModels } = await import("./transport-config-ANPS2RYT.js");
598
+ cleanDemotedModels(tc, model);
599
+ writeTransportConfig(tc, `professor fallback ${fbIndex + 1} \u2192 ${model} (${providerName})`);
600
+ await api.sendMessage(chatId, `\u2705 Fallback ${fbIndex + 1} \u2192 ${model} (${providerName})`);
601
+ } else {
602
+ const oldProvider = tc.agents[agentKey]?.provider;
603
+ tc.agents[agentKey] = { ...tc.agents[agentKey], model, provider: providerName };
604
+ const { cleanDemotedModels } = await import("./transport-config-ANPS2RYT.js");
605
+ cleanDemotedModels(tc, model);
606
+ writeTransportConfig(tc, `${agentKey} \u2192 ${model} (${providerName})`);
607
+ const providerChanged = oldProvider !== providerName;
608
+ const isProfessor = agentKey === "professor";
609
+ let oldType;
610
+ let newType;
611
+ let newResolved;
612
+ if (isProfessor && providerChanged) {
613
+ const oldResolved = resolveAgent("_old", { ...tc, agents: { ...tc.agents, _old: { model: "", provider: oldProvider } } });
614
+ newResolved = resolveAgent("_new", { ...tc, agents: { ...tc.agents, _new: { model, provider: providerName } } });
615
+ oldType = oldResolved?.provider.transport ?? "api";
616
+ newType = newResolved?.provider.transport ?? "api";
617
+ if (oldType !== newType) {
618
+ const resetAgents = [];
619
+ for (const [a, assignment] of Object.entries(tc.agents)) {
620
+ if (a === "professor") continue;
621
+ const ap = tc.providers[assignment.provider];
622
+ if (ap && ap.transport !== newType) {
623
+ tc.agents[a] = { model, provider: providerName };
624
+ resetAgents.push(a);
625
+ }
626
+ }
627
+ if (resetAgents.length > 0) writeTransportConfig(tc, `cascade: ${resetAgents.join(", ")} \u2192 ${providerName}`);
628
+ }
629
+ }
630
+ if (isProfessor && !providerChanged && "setModel" in deps.transport) {
631
+ await deps.transport.setModel(model);
632
+ await api.sendMessage(chatId, `\u2705 Switched to ${model}`);
633
+ } else if (isProfessor && providerChanged && oldType === newType && "switchProvider" in deps.transport) {
634
+ try {
635
+ const { FallbackPolicy } = await import("./fallback-policy-SR6ED5I3.js");
636
+ const { ModelHealthRegistry } = await import("./model-health-registry-7ECZFCW4.js");
637
+ const apiKey = getEnv().getApiKey(newResolved?.provider.apiKeyEnv ?? "API_KEY");
638
+ const candidates = [{ endpoint: newResolved.provider.endpoint, apiKey, model, maxContext: newResolved.contextWindow }];
639
+ for (const fb of tc.agents["professor"]?.fallbacks ?? []) {
640
+ const fbRes = resolveAgent("_fb", { ...tc, agents: { ...tc.agents, _fb: { model: fb.model, provider: fb.provider } } });
641
+ if (fbRes) candidates.push({ endpoint: fbRes.provider.endpoint, apiKey: fbRes.provider.apiKeyEnv ? getEnv().getApiKey(fbRes.provider.apiKeyEnv) : apiKey, model: fb.model, maxContext: fbRes.contextWindow });
642
+ }
643
+ const registry = deps.transport.policy?.registry ?? new ModelHealthRegistry();
644
+ const policy = new FallbackPolicy(candidates, registry);
645
+ deps.transport.switchProvider({ endpoint: newResolved.provider.endpoint, apiKey, model, maxContext: newResolved.contextWindow, policy });
646
+ } catch (err) {
647
+ await api.sendMessage(chatId, `\u26A0\uFE0F Hot swap failed: ${err instanceof Error ? err.message : String(err)}. Use /reset to apply.`);
648
+ return;
649
+ }
650
+ try {
651
+ await api.sendMessage(chatId, `\u2705 Switched to ${model} (${providerName})`);
652
+ } catch (err) {
653
+ logAndSwallow(TAG3, "sendMessage model switch confirm", err);
654
+ }
655
+ } else if (isProfessor && providerChanged) {
656
+ const cascadeNote = oldType !== newType ? " Subagents also reset." : "";
657
+ try {
658
+ if (deps.pipeline.rebuildTransport) await deps.pipeline.rebuildTransport();
659
+ await deps.resetSessionForModelSwitch(chatId, "cross-transport-switch");
660
+ await api.sendMessage(chatId, `\u{1F504} Switched to ${model} (${providerName}). Transport rebuilt.${cascadeNote}`);
661
+ } catch (err) {
662
+ await api.sendMessage(chatId, `\u26A0\uFE0F Transport rebuild failed: ${err instanceof Error ? err.message : String(err)}. Try /reset manually.`);
663
+ }
664
+ } else {
665
+ await api.sendMessage(chatId, `\u2705 ${agentKey} \u2192 ${model} (${providerName})`);
666
+ }
667
+ }
668
+ } else if (data.startsWith("model:")) {
669
+ const newModel = data.slice(6);
670
+ if ("setModel" in deps.transport && typeof deps.transport.setModel === "function") {
671
+ try {
672
+ await deps.transport.setModel(newModel);
673
+ await deps.resetSessionForModelSwitch(chatId);
674
+ await api.sendMessage(chatId, `\u{1F916} Model switched \u2192 ${newModel}`);
675
+ } catch (err) {
676
+ await api.sendMessage(chatId, `\u274C Model switch failed: ${err instanceof Error ? err.message : String(err)}`);
677
+ }
678
+ }
679
+ }
680
+ }
681
+
682
+ // src/platforms/telegram/telegram-adapter.ts
683
+ var TELEGRAM_CAPABILITIES = { voice: true, reactions: true, typing: true, threads: true };
684
+ var TAG4 = "telegram";
685
+ var TelegramAdapter = class {
686
+ name = "telegram";
687
+ capabilities = TELEGRAM_CAPABILITIES;
688
+ api;
689
+ securityGate;
690
+ formatter = new ResponseFormatter();
691
+ config;
692
+ deps;
693
+ poller = null;
694
+ botUsername = "";
695
+ _pendingSlot;
696
+ _modelPickerCache = [];
697
+ constructor(config, deps) {
698
+ this.api = new TelegramApi(config.botToken);
699
+ this.securityGate = new SecurityGate(loadUsers());
700
+ this.config = config;
701
+ this.deps = deps;
702
+ }
703
+ /** Send a system notification to a chat (fire-and-forget). */
704
+ sendNotification(chatId, text) {
705
+ this.api.sendMessage(parseInt(chatId, 10), text).catch((err) => logAndSwallow(TAG4, "sendNotification", err));
706
+ }
707
+ /** Reset session after model switch — saves idle state, clears buffer, marks pendingStart. */
708
+ async resetSessionForModelSwitch(chatId, reason = "model-switch") {
709
+ await this.api.sendMessage(chatId, "Resetting session\u2026");
710
+ const p = this.deps.pipeline;
711
+ const sessionKey = `telegram:${chatId}`;
712
+ const bufKey = `telegram:${chatId}`;
713
+ await p.idleSave.save(sessionKey, chatId);
714
+ await resetAndPrepare({
715
+ transport: this.deps.transport,
716
+ sessionKey,
717
+ reason,
718
+ sessions: p.sessions,
719
+ conversationBuffer: this.deps.conversationBuffer,
720
+ bufKey
721
+ });
722
+ if (p.memoryConfig.memoryEnabled) {
723
+ const reg = loadUsers();
724
+ const user = reg.byPlatformId.get(String(chatId));
725
+ if (user) p.updateCtxStart(p.memoryConfig.memoryDir, user.userId);
726
+ }
727
+ }
728
+ async start() {
729
+ const botInfo = await this.api.getMe();
730
+ this.botUsername = botInfo.username?.toLowerCase() ?? "";
731
+ logInfo(TAG4, `\u{1F916} Bot: @${botInfo.username}`);
732
+ await this.api.setMyCommands(BOT_COMMANDS.map((c) => ({ command: c.name, description: c.description }))).catch((err) => logWarn(TAG4, `setMyCommands failed: ${err instanceof Error ? err.message : String(err)}`));
733
+ const home = abtarsHome();
734
+ const offsetStore = createFileOffsetStore(`${home}/state/telegram-offset`);
735
+ this.poller = new TelegramPoller(this.api, this.config.pollTimeoutS, (u) => this.handleUpdate(u), offsetStore);
736
+ await this.poller.start();
737
+ }
738
+ stop() {
739
+ this.poller?.stop();
740
+ this.poller = null;
741
+ }
742
+ authorize(msg) {
743
+ return this.securityGate.authorizeById(msg.senderId);
744
+ }
745
+ async sendMessage(channelId, text, opts) {
746
+ const chatId = parseInt(channelId, 10);
747
+ const sendOpts = {};
748
+ if (opts?.threadId) sendOpts.message_thread_id = parseInt(opts.threadId, 10);
749
+ if (opts?.parseMode) sendOpts.parse_mode = opts.parseMode;
750
+ if (opts?.reply_markup) sendOpts.reply_markup = opts.reply_markup;
751
+ return this.api.sendMessage(chatId, text, sendOpts);
752
+ }
753
+ async editMessage(channelId, messageId, text) {
754
+ const chatId = parseInt(channelId, 10);
755
+ await this.api.editMessageText(chatId, messageId, text);
756
+ }
757
+ chunkResponse(text) {
758
+ return this.formatter.chunkText(text);
759
+ }
760
+ async sendTyping(channelId, threadId) {
761
+ await this.api.sendChatAction(parseInt(channelId, 10), "typing", threadId ? parseInt(threadId, 10) : void 0);
762
+ }
763
+ async setReaction(channelId, messageId, emoji) {
764
+ if (messageId <= 0) return;
765
+ try {
766
+ const reaction = emoji ? [{ type: "emoji", emoji }] : [];
767
+ await this.api.setMessageReaction(parseInt(channelId, 10), messageId, reaction);
768
+ } catch (err) {
769
+ logDebug(TAG4, `React failed (${emoji || "remove"}): ${err instanceof Error ? err.message : String(err)}`);
770
+ }
771
+ }
772
+ async downloadVoice(fileId) {
773
+ const fileInfo = await this.api.getFile(fileId);
774
+ if (!fileInfo.file_path) throw new Error("No file_path returned");
775
+ return this.api.downloadFile(fileInfo.file_path);
776
+ }
777
+ async sendVoice(channelId, audio, opts) {
778
+ const sendOpts = {};
779
+ if (opts?.threadId) sendOpts.message_thread_id = parseInt(opts.threadId, 10);
780
+ await this.api.sendVoice(parseInt(channelId, 10), audio, sendOpts);
781
+ }
782
+ /** Send a file from disk as a Telegram document. */
783
+ async sendDocument(channelId, filePath, caption, opts) {
784
+ const sendOpts = {};
785
+ if (opts?.threadId) sendOpts.message_thread_id = parseInt(opts.threadId, 10);
786
+ return this.api.sendDocument(parseInt(channelId, 10), filePath, caption, sendOpts);
787
+ }
788
+ injectMessage(msg) {
789
+ if (!this.poller) return;
790
+ this.poller.injectUpdate({
791
+ update_id: 0,
792
+ message: {
793
+ message_id: 0,
794
+ from: { id: parseInt(msg.channelId, 10), is_bot: false, first_name: "queued" },
795
+ chat: { id: parseInt(msg.channelId, 10), type: "private" },
796
+ date: Math.floor(Date.now() / 1e3),
797
+ text: msg.text,
798
+ ...msg.threadId ? { message_thread_id: parseInt(msg.threadId, 10) } : {}
799
+ }
800
+ });
801
+ }
802
+ // --- Internal: Telegram update handler ---
803
+ async handleUpdate(update) {
804
+ logDebug(TAG4, `Update: ${JSON.stringify(update).slice(0, 200)}`);
805
+ if (update.callback_query) {
806
+ const data = update.callback_query.data ?? "";
807
+ const chatId2 = update.callback_query.message?.chat?.id;
808
+ this.api.answerCallbackQuery(update.callback_query.id).catch((err) => logAndSwallow(TAG4, "answerCallbackQuery", err));
809
+ if (!chatId2) return;
810
+ try {
811
+ if (isModelPickerCallback(data)) {
812
+ await handleModelPickerCallback(data, chatId2, this.api, this, {
813
+ transport: this.deps.transport,
814
+ pipeline: this.deps.pipeline,
815
+ resetSessionForModelSwitch: (cid, reason) => this.resetSessionForModelSwitch(cid, reason)
816
+ });
817
+ } else if (data.startsWith("model:")) {
818
+ const newModel = data.slice(6);
819
+ const transport = this.deps.transport;
820
+ if ("setModel" in transport && typeof transport.setModel === "function") {
821
+ try {
822
+ await transport.setModel(newModel);
823
+ await this.resetSessionForModelSwitch(chatId2);
824
+ if (chatId2) await this.api.sendMessage(chatId2, `\u{1F916} Model switched \u2192 ${newModel}`);
825
+ } catch (err) {
826
+ if (chatId2) await this.api.sendMessage(chatId2, `\u274C Model switch failed: ${err instanceof Error ? err.message : String(err)}`);
827
+ }
828
+ }
829
+ }
830
+ } catch (err) {
831
+ logWarn(TAG4, `Callback handler error: ${err instanceof Error ? err.message : String(err)}`);
832
+ this.api.sendMessage(chatId2, `\u26A0\uFE0F Action failed \u2014 try again.`).catch((err2) => logAndSwallow(TAG4, "sendMessage action failed", err2));
833
+ }
834
+ return;
835
+ }
836
+ if (update.message_reaction) {
837
+ await this.handleReaction(update);
838
+ return;
839
+ }
840
+ const message = update.message;
841
+ if (!message?.from) return;
842
+ const hasText = Boolean(message.text);
843
+ const hasVoice = Boolean(message.voice || message.audio);
844
+ const hasPhoto = Boolean(message.photo?.length);
845
+ const hasDocument = Boolean(message.document);
846
+ if (!hasText && !hasVoice && !hasPhoto && !hasDocument) return;
847
+ const chatId = message.chat.id;
848
+ const isGroup = message.chat.type === "group" || message.chat.type === "supergroup";
849
+ const threadId = isGroup ? message.message_thread_id : void 0;
850
+ const messageId = message.message_id;
851
+ const senderName = message.from.first_name || message.from.username || `id:${message.from.id}`;
852
+ const bufKey = threadId != null ? `tg:${chatId}:${threadId}` : `tg:${chatId}`;
853
+ let text = message.text ?? "";
854
+ let isVoiceNote = false;
855
+ let voiceFileId;
856
+ if (hasVoice && !hasText) {
857
+ if (!this.deps.pipeline.sttConfig) {
858
+ if (isGroup) {
859
+ this.deps.conversationBuffer.push(bufKey, senderName, "[voice note - STT disabled]");
860
+ } else if (this.securityGate.authorizeById(String(message.from?.id))) {
861
+ await this.api.sendMessage(chatId, "\u{1F3A4} Voice notes require STT (set GROQ_API_KEY).", { message_thread_id: threadId });
862
+ }
863
+ return;
864
+ }
865
+ if (!this.securityGate.authorizeById(String(message.from?.id))) {
866
+ if (isGroup) this.deps.conversationBuffer.push(bufKey, senderName, "[voice note]");
867
+ return;
868
+ }
869
+ if (isGroup) {
870
+ try {
871
+ await this.setReaction(String(chatId), messageId, "\u{1F440}");
872
+ const voiceFile = message.voice || message.audio;
873
+ const audioBuffer = await this.downloadVoice(voiceFile.file_id);
874
+ const { transcribeAudio } = await import("./stt-CF3CPFDC.js");
875
+ const result = await transcribeAudio(audioBuffer, "voice.ogg", this.deps.pipeline.sttConfig);
876
+ const transcript = result.text;
877
+ if (!transcript) {
878
+ await this.setReaction(String(chatId), messageId, "");
879
+ this.deps.conversationBuffer.push(bufKey, senderName, "[voice note - empty]");
880
+ return;
881
+ }
882
+ const mentionRe = new RegExp(`@?${this.botUsername}\\b`, "i");
883
+ if (!mentionRe.test(transcript) && !transcript.startsWith("/")) {
884
+ await this.setReaction(String(chatId), messageId, "");
885
+ this.deps.conversationBuffer.push(bufKey, senderName, `[voice] ${transcript}`);
886
+ logDebug(TAG4, `Buffered voice transcript: "${transcript.slice(0, 60)}"`);
887
+ return;
888
+ }
889
+ text = transcript.replace(mentionRe, "").trim();
890
+ isVoiceNote = true;
891
+ if (!text) {
892
+ await this.setReaction(String(chatId), messageId, "");
893
+ return;
894
+ }
895
+ } catch (err) {
896
+ logError(TAG4, "Voice transcription failed", err);
897
+ await this.setReaction(String(chatId), messageId, "");
898
+ return;
899
+ }
900
+ } else {
901
+ isVoiceNote = true;
902
+ voiceFileId = (message.voice || message.audio).file_id;
903
+ }
904
+ }
905
+ if (!isVoiceNote && isGroup) {
906
+ const mentionRe = new RegExp(`@${this.botUsername}\\b`, "i");
907
+ const isMention = mentionRe.test(text);
908
+ const isCommand = text.startsWith("/");
909
+ if (!isMention && !isCommand) {
910
+ this.deps.conversationBuffer.push(bufKey, senderName, text);
911
+ logDebug(TAG4, `Buffered group msg from ${senderName}: "${text.slice(0, 60)}"`);
912
+ return;
913
+ }
914
+ if (isMention) {
915
+ text = text.replace(mentionRe, "").trim();
916
+ if (!text) return;
917
+ }
918
+ }
919
+ if (!isVoiceNote && !this.securityGate.authorizeById(String(message.from?.id))) {
920
+ if (isGroup) this.deps.conversationBuffer.push(bufKey, senderName, text);
921
+ logWarn(TAG4, `Unauthorized user ${message.from.id}`);
922
+ return;
923
+ }
924
+ let mediaPath;
925
+ if ((hasPhoto || hasDocument) && this.securityGate.authorizeById(String(message.from?.id))) {
926
+ try {
927
+ const { saveInboundMedia } = await import("./media-utils-QBY5WBF3.js");
928
+ let fileId;
929
+ let extHint;
930
+ let claimedMime;
931
+ if (hasPhoto) {
932
+ const photo = message.photo[message.photo.length - 1];
933
+ fileId = photo.file_id;
934
+ extHint = ".jpg";
935
+ } else {
936
+ fileId = message.document.file_id;
937
+ extHint = message.document.file_name ? "." + (message.document.file_name.split(".").pop() ?? "") : void 0;
938
+ claimedMime = message.document.mime_type;
939
+ }
940
+ const buf = await this.downloadVoice(fileId);
941
+ const saved = await saveInboundMedia(buf, chatId, { extHint, claimedMime });
942
+ if (saved) {
943
+ mediaPath = saved.path;
944
+ if (!text) text = message.caption ?? `User sent a ${saved.isImage ? "photo" : "file"}.`;
945
+ } else {
946
+ if (!text) text = "\u26A0\uFE0F File too large (max 16MB).";
947
+ }
948
+ } catch (err) {
949
+ logWarn(TAG4, `Media download failed: ${err instanceof Error ? err.message : String(err)}`);
950
+ if (!text) text = "\u26A0\uFE0F Failed to download media.";
951
+ }
952
+ }
953
+ const reply = message.reply_to_message;
954
+ if (reply?.text) {
955
+ const replyFrom = reply.from?.first_name ?? "someone";
956
+ text = `[Replying to ${replyFrom}: "${reply.text.slice(0, 500)}"]
957
+ ${text}`;
958
+ }
959
+ if (reply?.photo?.length && !mediaPath && this.securityGate.authorizeById(String(message.from?.id))) {
960
+ try {
961
+ const { saveInboundMedia } = await import("./media-utils-QBY5WBF3.js");
962
+ const photo = reply.photo[reply.photo.length - 1];
963
+ const buf = await this.downloadVoice(photo.file_id);
964
+ const saved = await saveInboundMedia(buf, chatId, { extHint: ".jpg" });
965
+ if (saved) mediaPath = saved.path;
966
+ } catch (err) {
967
+ logWarn(TAG4, `Reply-to-photo download failed: ${err instanceof Error ? err.message : String(err)}`);
968
+ }
969
+ }
970
+ const resolvedUser = loadUsers().byPlatformId.get("telegram:" + message.from.id)?.userId ?? "unknown";
971
+ const inbound = {
972
+ platform: "telegram",
973
+ channelId: String(chatId),
974
+ userId: resolvedUser,
975
+ senderId: String(message.from.id),
976
+ senderName,
977
+ text,
978
+ timestamp: message.date * 1e3,
979
+ threadId: threadId != null ? String(threadId) : void 0,
980
+ messageId,
981
+ isGroup,
982
+ isVoice: isVoiceNote,
983
+ voiceFileId,
984
+ mediaPath,
985
+ rawPlatformData: message
986
+ };
987
+ if (text.startsWith("/") && !text.startsWith("//")) {
988
+ handleInboundMessage(inbound, this, this.deps.pipeline).catch((err) => {
989
+ logError(TAG4, `Command dispatch error: ${err instanceof Error ? err.message : String(err)}`);
990
+ });
991
+ return;
992
+ }
993
+ await handleInboundMessage(inbound, this, this.deps.pipeline);
994
+ }
995
+ async handleReaction(update) {
996
+ const reaction = update.message_reaction;
997
+ const user = reaction.user;
998
+ if (!user) {
999
+ logDebug(TAG4, "Reaction update missing user field");
1000
+ return;
1001
+ }
1002
+ if (user.is_bot) return;
1003
+ const oldEmojis = new Set(reaction.old_reaction.map((r) => r.emoji));
1004
+ const added = reaction.new_reaction.filter((r) => !oldEmojis.has(r.emoji));
1005
+ if (added.length === 0) return;
1006
+ const senderName = user.first_name || user.username || `id:${user.id}`;
1007
+ const emojis = added.map((r) => r.emoji);
1008
+ logInfo(TAG4, `Reaction ${emojis.join("")} from ${senderName} on msg ${reaction.message_id}`);
1009
+ const isAuthorized = this.securityGate.authorizeById(String(user.id));
1010
+ const signal = formatReactionSignal(senderName, emojis);
1011
+ const chatId = reaction.chat.id;
1012
+ const route = routeReaction(isAuthorized, reaction.chat.type);
1013
+ if (isAuthorized && this.deps.memory) {
1014
+ const score = emojiToScore(emojis[0]);
1015
+ const updated = this.deps.memory.updateEmotionByPlatformId(loadUsers().byPlatformId.get(`telegram:${chatId}`)?.userId ?? "master", reaction.message_id, score);
1016
+ if (updated) logDebug(TAG4, `Emotion score ${score} set on platform msg ${reaction.message_id}`);
1017
+ }
1018
+ if (route === "discard") {
1019
+ logDebug(TAG4, `Unauthorized reaction from user ${user.id}, discarding`);
1020
+ return;
1021
+ }
1022
+ if (route === "buffer") {
1023
+ const bufKey = `tg:${chatId}`;
1024
+ this.deps.conversationBuffer.push(bufKey, senderName, signal);
1025
+ logDebug(TAG4, `Buffered reaction signal for group ${chatId}`);
1026
+ } else {
1027
+ const reactionUser = loadUsers().byPlatformId.get("telegram:" + user.id)?.userId ?? "unknown";
1028
+ const activeId = this.deps.sessionManager.getActiveSessionId(reactionUser, "telegram");
1029
+ const { sessions } = this.deps.pipeline;
1030
+ const entry = sessions.getOrCreate(activeId);
1031
+ if (entry.busy) {
1032
+ entry.queue.push({ msg: { userId: reactionUser, channelId: String(chatId), senderName, senderId: String(user.id), text: signal, messageId: reaction.message_id, platform: "telegram", timestamp: Date.now(), isGroup: false, isVoice: false }, adapter: this });
1033
+ logDebug(TAG4, `Queued reaction signal for busy ${activeId} (${entry.queue.length} pending)`);
1034
+ } else {
1035
+ try {
1036
+ const response = await this.deps.transport.sendPrompt(activeId, signal, void 0, reactionUser);
1037
+ logDebug(TAG4, `Sent reaction signal to transport for chat ${chatId}`);
1038
+ if (response) {
1039
+ const { text, reactionEmoji, noReply } = cleanResponse(response);
1040
+ if (noReply) {
1041
+ } else if (reactionEmoji) {
1042
+ try {
1043
+ await this.api.setMessageReaction(chatId, reaction.message_id, [{ type: "emoji", emoji: reactionEmoji }]);
1044
+ } catch {
1045
+ await this.sendMessage(String(chatId), reactionEmoji);
1046
+ }
1047
+ } else if (text.trim()) {
1048
+ await this.sendMessage(String(chatId), text.trim());
1049
+ }
1050
+ }
1051
+ } catch (err) {
1052
+ logError(TAG4, `Failed to send reaction signal for chat ${chatId}`, err);
1053
+ }
1054
+ }
1055
+ }
1056
+ }
1057
+ };
1058
+ export {
1059
+ TELEGRAM_CAPABILITIES,
1060
+ TelegramAdapter
1061
+ };
1062
+ //# sourceMappingURL=telegram-adapter-QCD7AG5D.js.map