@rubytech/create-maxy-code 0.1.581 → 0.1.583

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 (453) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/routine-templates/dist/index.d.ts +1 -1
  3. package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/routine-templates/dist/index.js +5 -1
  5. package/payload/platform/lib/routine-templates/dist/index.js.map +1 -1
  6. package/payload/platform/lib/routine-templates/src/index.ts +4 -0
  7. package/payload/platform/lib/telegram-managed-bot/dist/index.d.ts +269 -0
  8. package/payload/platform/lib/telegram-managed-bot/dist/index.d.ts.map +1 -0
  9. package/payload/platform/lib/telegram-managed-bot/dist/index.js +351 -0
  10. package/payload/platform/lib/telegram-managed-bot/dist/index.js.map +1 -0
  11. package/payload/platform/lib/telegram-managed-bot/src/__tests__/managed-bot.test.ts +251 -0
  12. package/payload/platform/lib/telegram-managed-bot/src/index.ts +529 -0
  13. package/payload/platform/lib/telegram-managed-bot/tsconfig.json +9 -0
  14. package/payload/platform/lib/telegram-managed-bot/vitest.config.ts +9 -0
  15. package/payload/platform/lib/telegram-reach/dist/index.d.ts +80 -0
  16. package/payload/platform/lib/telegram-reach/dist/index.d.ts.map +1 -0
  17. package/payload/platform/lib/telegram-reach/dist/index.js +211 -0
  18. package/payload/platform/lib/telegram-reach/dist/index.js.map +1 -0
  19. package/payload/platform/lib/telegram-reach/src/__tests__/telegram-reach.test.ts +216 -0
  20. package/payload/platform/lib/telegram-reach/src/index.ts +262 -0
  21. package/payload/platform/lib/telegram-reach/tsconfig.json +9 -0
  22. package/payload/platform/lib/telegram-reach/vitest.config.ts +9 -0
  23. package/payload/platform/package.json +2 -2
  24. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  25. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +9 -0
  26. package/payload/platform/plugins/admin/hooks/__tests__/preference-consult-directive.test.sh +26 -0
  27. package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +20 -3
  28. package/payload/platform/plugins/admin/hooks/preference-consult-directive.sh +50 -5
  29. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +181 -9
  30. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +17 -0
  31. package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.d.ts +2 -0
  32. package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.d.ts.map +1 -0
  33. package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.js +100 -0
  34. package/payload/platform/plugins/contacts/mcp/dist/__tests__/telegram-user-id.test.js.map +1 -0
  35. package/payload/platform/plugins/contacts/mcp/dist/index.js +11 -5
  36. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
  37. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +5 -0
  38. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -1
  39. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +21 -4
  40. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
  41. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +5 -0
  42. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
  43. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +29 -1
  44. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
  45. package/payload/platform/plugins/contacts/mcp/vitest.config.ts +14 -0
  46. package/payload/platform/plugins/docs/references/admin-ui.md +20 -4
  47. package/payload/platform/plugins/docs/references/calendar-booking.md +2 -0
  48. package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +15 -0
  49. package/payload/platform/plugins/docs/references/telegram-guide.md +143 -4
  50. package/payload/platform/plugins/filesystem/PLUGIN.md +2 -2
  51. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.d.ts +2 -0
  52. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.d.ts.map +1 -0
  53. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.js +108 -0
  54. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/account-schema.test.js.map +1 -0
  55. package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.d.ts +17 -0
  56. package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.d.ts.map +1 -0
  57. package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.js +162 -0
  58. package/payload/platform/plugins/filesystem/mcp/dist/lib/account-schema.js.map +1 -0
  59. package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.d.ts +2 -0
  60. package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.d.ts.map +1 -0
  61. package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.js +116 -0
  62. package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/schema-fence.test.js.map +1 -0
  63. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -1
  64. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +9 -0
  65. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -1
  66. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -1
  67. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +10 -0
  68. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -1
  69. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js +64 -1
  70. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js.map +1 -1
  71. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts +5 -0
  72. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts.map +1 -1
  73. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js +28 -6
  74. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js.map +1 -1
  75. package/payload/platform/plugins/memory/references/schema-knowledge-work.md +1 -1
  76. package/payload/platform/plugins/scheduling/PLUGIN.md +19 -3
  77. package/payload/platform/plugins/scheduling/mcp/dist/index.js +7 -2
  78. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  79. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js +53 -6
  80. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js.map +1 -1
  81. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +38 -0
  82. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
  83. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.d.ts +2 -0
  84. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.d.ts.map +1 -0
  85. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.js +102 -0
  86. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-uid-stamp.test.js.map +1 -0
  87. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-audit.test.js +43 -9
  88. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-audit.test.js.map +1 -1
  89. package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +50 -0
  90. package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -1
  91. package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +47 -1
  92. package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -1
  93. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +5 -3
  94. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
  95. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +18 -3
  96. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
  97. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts +40 -0
  98. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts.map +1 -1
  99. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js +132 -41
  100. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js.map +1 -1
  101. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +14 -1
  102. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  103. package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +61 -1
  104. package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
  105. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +258 -8
  106. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -1
  107. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.d.ts +2 -0
  108. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.d.ts.map +1 -0
  109. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.js +67 -0
  110. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-trash-filter.test.js.map +1 -0
  111. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +206 -3
  112. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
  113. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -1
  114. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +8 -1
  115. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -1
  116. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +29 -21
  117. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
  118. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +94 -14
  119. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
  120. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
  121. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +6 -1
  122. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
  123. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts.map +1 -1
  124. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js +7 -2
  125. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js.map +1 -1
  126. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
  127. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +46 -3
  128. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
  129. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +30 -0
  130. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
  131. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +69 -6
  132. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
  133. package/payload/platform/plugins/telegram/PLUGIN.md +49 -1
  134. package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-census.test.js +3 -3
  135. package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-guard.test.js +28 -2
  136. package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-guard.test.js.map +1 -1
  137. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.d.ts +2 -0
  138. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.d.ts.map +1 -0
  139. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.js +140 -0
  140. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-business-connection.test.js.map +1 -0
  141. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js +93 -5
  142. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js.map +1 -1
  143. package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.d.ts +2 -0
  144. package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.d.ts.map +1 -0
  145. package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.js +326 -0
  146. package/payload/platform/plugins/telegram/mcp/dist/__tests__/bot-provision-tool.test.js.map +1 -0
  147. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.d.ts +2 -0
  148. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.d.ts.map +1 -0
  149. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.js +173 -0
  150. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-business.test.js.map +1 -0
  151. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js +79 -0
  152. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js.map +1 -1
  153. package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.d.ts +2 -0
  154. package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.d.ts.map +1 -0
  155. package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.js +34 -0
  156. package/payload/platform/plugins/telegram/mcp/dist/__tests__/chat-send-policy.test.js.map +1 -0
  157. package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.d.ts +2 -0
  158. package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.d.ts.map +1 -0
  159. package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.js +93 -0
  160. package/payload/platform/plugins/telegram/mcp/dist/__tests__/reach-tool.test.js.map +1 -0
  161. package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.js +15 -1
  162. package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.js.map +1 -1
  163. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js +245 -0
  164. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js.map +1 -1
  165. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.js +10 -1
  166. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.js.map +1 -1
  167. package/payload/platform/plugins/telegram/mcp/dist/index.js +26 -4
  168. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  169. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +19 -0
  170. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -1
  171. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +41 -1
  172. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -1
  173. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +15 -20
  174. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -1
  175. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +27 -32
  176. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -1
  177. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts +13 -0
  178. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts.map +1 -1
  179. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js +22 -1
  180. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js.map +1 -1
  181. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.d.ts.map +1 -1
  182. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.js +6 -0
  183. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.js.map +1 -1
  184. package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.d.ts +1 -1
  185. package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.d.ts.map +1 -1
  186. package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.js +22 -2
  187. package/payload/platform/plugins/telegram/mcp/dist/lib/api-guard.js.map +1 -1
  188. package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.d.ts +38 -0
  189. package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.d.ts.map +1 -0
  190. package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.js +56 -0
  191. package/payload/platform/plugins/telegram/mcp/dist/lib/business-connection-store.js.map +1 -0
  192. package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.d.ts +55 -0
  193. package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.d.ts.map +1 -0
  194. package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.js +116 -0
  195. package/payload/platform/plugins/telegram/mcp/dist/lib/business-window-store.js.map +1 -0
  196. package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.d.ts +54 -0
  197. package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.d.ts.map +1 -0
  198. package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.js +90 -0
  199. package/payload/platform/plugins/telegram/mcp/dist/lib/chat-send-policy.js.map +1 -0
  200. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts +2 -28
  201. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts.map +1 -1
  202. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js +8 -53
  203. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js.map +1 -1
  204. package/payload/platform/plugins/telegram/mcp/dist/tools/api.d.ts.map +1 -1
  205. package/payload/platform/plugins/telegram/mcp/dist/tools/api.js +19 -0
  206. package/payload/platform/plugins/telegram/mcp/dist/tools/api.js.map +1 -1
  207. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.d.ts.map +1 -1
  208. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.js +79 -10
  209. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.js.map +1 -1
  210. package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.d.ts +64 -0
  211. package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.d.ts.map +1 -0
  212. package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.js +217 -0
  213. package/payload/platform/plugins/telegram/mcp/dist/tools/bot-provision.js.map +1 -0
  214. package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts +7 -0
  215. package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts.map +1 -1
  216. package/payload/platform/plugins/telegram/mcp/dist/tools/card.js +56 -0
  217. package/payload/platform/plugins/telegram/mcp/dist/tools/card.js.map +1 -1
  218. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.d.ts.map +1 -1
  219. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.js +15 -0
  220. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.js.map +1 -1
  221. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.d.ts.map +1 -1
  222. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.js +12 -0
  223. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.js.map +1 -1
  224. package/payload/platform/plugins/telegram/mcp/dist/tools/reach.d.ts +22 -0
  225. package/payload/platform/plugins/telegram/mcp/dist/tools/reach.d.ts.map +1 -0
  226. package/payload/platform/plugins/telegram/mcp/dist/tools/reach.js +67 -0
  227. package/payload/platform/plugins/telegram/mcp/dist/tools/reach.js.map +1 -0
  228. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts +21 -2
  229. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts.map +1 -1
  230. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js +47 -2
  231. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js.map +1 -1
  232. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.d.ts.map +1 -1
  233. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.js +12 -0
  234. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.js.map +1 -1
  235. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.d.ts +4 -1
  236. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.d.ts.map +1 -1
  237. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js +73 -6
  238. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js.map +1 -1
  239. package/payload/platform/plugins/telegram/skills/build/SKILL.md +217 -11
  240. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +87 -6
  241. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +12 -0
  242. package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts +36 -5
  243. package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.d.ts.map +1 -1
  244. package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.js +103 -10
  245. package/payload/platform/services/claude-session-manager/dist/account-dir-schema-reconcile.js.map +1 -1
  246. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  247. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
  248. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  249. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  250. package/payload/platform/services/claude-session-manager/dist/http-server.js +42 -4
  251. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  252. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  253. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +19 -5
  254. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  255. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +9 -0
  256. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  257. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +5 -1
  258. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  259. package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
  260. package/payload/platform/services/telegram-channel/dist/instructions.js +13 -0
  261. package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
  262. package/payload/platform/services/telegram-channel/dist/notification.d.ts +40 -0
  263. package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
  264. package/payload/platform/services/telegram-channel/dist/notification.js +41 -4
  265. package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
  266. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +52 -0
  267. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  268. package/payload/platform/services/whatsapp-channel/dist/notification.js +64 -1
  269. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  270. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  271. package/payload/platform/services/whatsapp-channel/dist/server.js +14 -2
  272. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  273. package/payload/platform/templates/account-schema/SCHEMA.md +17 -10
  274. package/payload/platform/templates/agents/admin/IDENTITY.md +5 -0
  275. package/payload/platform/templates/specialists/agents/data-manager.md +2 -2
  276. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  277. package/payload/server/{chunk-BFRB2U75.js → chunk-CV6AEMKH.js} +1 -0
  278. package/payload/server/{manager-CTVTF4YB.js → manager-FQSQSSJ3.js} +1 -1
  279. package/payload/server/public/activity.html +6 -6
  280. package/payload/server/public/agents.html +5 -5
  281. package/payload/server/public/assets/{AdminLoginScreens-B1lu4-_F.js → AdminLoginScreens-BLsDYWVi.js} +1 -1
  282. package/payload/server/public/assets/AdminLoginScreens-BLsDYWVi.js.br +0 -0
  283. package/payload/server/public/assets/AdminLoginScreens-BLsDYWVi.js.gz +0 -0
  284. package/payload/server/public/assets/{AdminShell-BMslfZxN.js → AdminShell-BZS8jzFA.js} +1 -1
  285. package/payload/server/public/assets/AdminShell-BZS8jzFA.js.br +0 -0
  286. package/payload/server/public/assets/AdminShell-BZS8jzFA.js.gz +0 -0
  287. package/payload/server/public/assets/{activity-kQ3w70LJ.js → activity-DOjvoLdd.js} +1 -1
  288. package/payload/server/public/assets/activity-DOjvoLdd.js.br +0 -0
  289. package/payload/server/public/assets/activity-DOjvoLdd.js.gz +0 -0
  290. package/payload/server/public/assets/{admin-CkASgYA7.js → admin-JrSNg29g.js} +1 -1
  291. package/payload/server/public/assets/admin-JrSNg29g.js.br +0 -0
  292. package/payload/server/public/assets/admin-JrSNg29g.js.gz +0 -0
  293. package/payload/server/public/assets/{agents-Cn_bZgnD.js → agents--9WMJVLC.js} +1 -1
  294. package/payload/server/public/assets/agents--9WMJVLC.js.br +0 -0
  295. package/payload/server/public/assets/agents--9WMJVLC.js.gz +0 -0
  296. package/payload/server/public/assets/{browser-BE-GDk5-.js → browser-DiiMmTrM.js} +1 -1
  297. package/payload/server/public/assets/browser-DiiMmTrM.js.br +0 -0
  298. package/payload/server/public/assets/browser-DiiMmTrM.js.gz +0 -0
  299. package/payload/server/public/assets/{calendar-Di7BEHHN.js → calendar-CazmCzgO.js} +1 -1
  300. package/payload/server/public/assets/calendar-CazmCzgO.js.br +0 -0
  301. package/payload/server/public/assets/calendar-CazmCzgO.js.gz +0 -0
  302. package/payload/server/public/assets/chat-CB0TcyXX.js +1 -0
  303. package/payload/server/public/assets/chat-CB0TcyXX.js.br +0 -0
  304. package/payload/server/public/assets/chat-CB0TcyXX.js.gz +0 -0
  305. package/payload/server/public/assets/chevron-left-0tVo23Dh.js +1 -0
  306. package/payload/server/public/assets/chevron-left-0tVo23Dh.js.br +0 -0
  307. package/payload/server/public/assets/clock-D2cZ0sge.js +1 -0
  308. package/payload/server/public/assets/clock-D2cZ0sge.js.br +0 -0
  309. package/payload/server/public/assets/clock-D2cZ0sge.js.gz +0 -0
  310. package/payload/server/public/assets/{copy-nkxspu2J.js → copy-C87QIN_o.js} +1 -1
  311. package/payload/server/public/assets/copy-C87QIN_o.js.br +0 -0
  312. package/payload/server/public/assets/copy-C87QIN_o.js.gz +0 -0
  313. package/payload/server/public/assets/data-CK7AMxPt.js +1 -0
  314. package/payload/server/public/assets/data-CK7AMxPt.js.br +0 -0
  315. package/payload/server/public/assets/data-CK7AMxPt.js.gz +0 -0
  316. package/payload/server/public/assets/{field-2rIXxGMt.js → field-C3kQgGWE.js} +1 -1
  317. package/payload/server/public/assets/field-C3kQgGWE.js.br +0 -0
  318. package/payload/server/public/assets/field-C3kQgGWE.js.gz +0 -0
  319. package/payload/server/public/assets/{file-text-CdSqrscg.js → file-text-rWowl9RN.js} +1 -1
  320. package/payload/server/public/assets/file-text-rWowl9RN.js.br +0 -0
  321. package/payload/server/public/assets/file-text-rWowl9RN.js.gz +0 -0
  322. package/payload/server/public/assets/{graph-BfBHHXaC.js → graph-CVJKz1Uo.js} +1 -1
  323. package/payload/server/public/assets/graph-CVJKz1Uo.js.br +0 -0
  324. package/payload/server/public/assets/graph-CVJKz1Uo.js.gz +0 -0
  325. package/payload/server/public/assets/{graph-labels-CHW2aBke.js → graph-labels-kneGnsHB.js} +1 -1
  326. package/payload/server/public/assets/graph-labels-kneGnsHB.js.br +0 -0
  327. package/payload/server/public/assets/graph-labels-kneGnsHB.js.gz +0 -0
  328. package/payload/server/public/assets/{jsx-runtime-D43jgaWP.css → jsx-runtime-rMaiYjNu.css} +1 -1
  329. package/payload/server/public/assets/jsx-runtime-rMaiYjNu.css.br +0 -0
  330. package/payload/server/public/assets/{jsx-runtime-D43jgaWP.css.gz → jsx-runtime-rMaiYjNu.css.gz} +0 -0
  331. package/payload/server/public/assets/{operator-DRn9LITC.js → operator-BGvB4hu4.js} +1 -1
  332. package/payload/server/public/assets/operator-BGvB4hu4.js.br +0 -0
  333. package/payload/server/public/assets/operator-BGvB4hu4.js.gz +0 -0
  334. package/payload/server/public/assets/{page-D_9mPS6W.js → page-DBQLOasI.js} +1 -1
  335. package/payload/server/public/assets/page-DBQLOasI.js.br +0 -0
  336. package/payload/server/public/assets/page-DBQLOasI.js.gz +0 -0
  337. package/payload/server/public/assets/{page-BwqQsoU8.js → page-DyVAu7tm.js} +1 -1
  338. package/payload/server/public/assets/page-DyVAu7tm.js.br +0 -0
  339. package/payload/server/public/assets/page-DyVAu7tm.js.gz +0 -0
  340. package/payload/server/public/assets/play-DgP7vl0r.js +1 -0
  341. package/payload/server/public/assets/play-DgP7vl0r.js.br +0 -0
  342. package/payload/server/public/assets/play-DgP7vl0r.js.gz +0 -0
  343. package/payload/server/public/assets/{public-CrjZYpdW.js → public-BvUQR3hd.js} +1 -1
  344. package/payload/server/public/assets/public-BvUQR3hd.js.br +0 -0
  345. package/payload/server/public/assets/public-BvUQR3hd.js.gz +0 -0
  346. package/payload/server/public/assets/{rotate-ccw-J9f-GWjm.js → rotate-ccw-Dnn7gbPh.js} +1 -1
  347. package/payload/server/public/assets/rotate-ccw-Dnn7gbPh.js.br +0 -0
  348. package/payload/server/public/assets/rotate-ccw-Dnn7gbPh.js.gz +0 -0
  349. package/payload/server/public/assets/{routines-C1AB-3FR.js → routines-N8NmxPOZ.js} +1 -1
  350. package/payload/server/public/assets/routines-N8NmxPOZ.js.br +0 -0
  351. package/payload/server/public/assets/routines-N8NmxPOZ.js.gz +0 -0
  352. package/payload/server/public/assets/{skills-C4EfNKEx.js → skills-B2CRgO-U.js} +1 -1
  353. package/payload/server/public/assets/skills-B2CRgO-U.js.br +0 -0
  354. package/payload/server/public/assets/skills-B2CRgO-U.js.gz +0 -0
  355. package/payload/server/public/assets/{tasks-DszD3aZl.js → tasks-8QLGtlSj.js} +1 -1
  356. package/payload/server/public/assets/tasks-8QLGtlSj.js.br +0 -0
  357. package/payload/server/public/assets/tasks-8QLGtlSj.js.gz +0 -0
  358. package/payload/server/public/assets/{triangle-alert-B5WAyAkC.js → triangle-alert-el772yUQ.js} +1 -1
  359. package/payload/server/public/assets/triangle-alert-el772yUQ.js.br +0 -0
  360. package/payload/server/public/assets/triangle-alert-el772yUQ.js.gz +0 -0
  361. package/payload/server/public/assets/{useCopyFeedback-B2nuNNJw.js → useCopyFeedback-DfNAu8hQ.js} +1 -1
  362. package/payload/server/public/assets/useCopyFeedback-DfNAu8hQ.js.br +0 -0
  363. package/payload/server/public/assets/useCopyFeedback-DfNAu8hQ.js.gz +0 -0
  364. package/payload/server/public/assets/{useMediaQuery-DUPJPHQt.js → useMediaQuery-B469O83-.js} +1 -1
  365. package/payload/server/public/assets/useMediaQuery-B469O83-.js.br +0 -0
  366. package/payload/server/public/assets/useMediaQuery-B469O83-.js.gz +0 -0
  367. package/payload/server/public/assets/useVoiceRecorder-Bb-51cJv.js +2 -0
  368. package/payload/server/public/assets/useVoiceRecorder-Bb-51cJv.js.br +0 -0
  369. package/payload/server/public/assets/useVoiceRecorder-Bb-51cJv.js.gz +0 -0
  370. package/payload/server/public/assets/{wrench-DZJZm17j.js → wrench-Ck4phkdB.js} +1 -1
  371. package/payload/server/public/assets/wrench-Ck4phkdB.js.br +0 -0
  372. package/payload/server/public/assets/wrench-Ck4phkdB.js.gz +0 -0
  373. package/payload/server/public/browser.html +5 -5
  374. package/payload/server/public/calendar.html +8 -8
  375. package/payload/server/public/chat.html +14 -14
  376. package/payload/server/public/data.html +12 -12
  377. package/payload/server/public/field.html +3 -3
  378. package/payload/server/public/graph.html +10 -10
  379. package/payload/server/public/index.html +14 -14
  380. package/payload/server/public/operator.html +16 -16
  381. package/payload/server/public/public.html +14 -14
  382. package/payload/server/public/routines.html +8 -8
  383. package/payload/server/public/skills.html +6 -6
  384. package/payload/server/public/tasks.html +7 -7
  385. package/payload/server/server.js +3777 -1258
  386. package/payload/server/public/assets/AdminLoginScreens-B1lu4-_F.js.br +0 -0
  387. package/payload/server/public/assets/AdminLoginScreens-B1lu4-_F.js.gz +0 -0
  388. package/payload/server/public/assets/AdminShell-BMslfZxN.js.br +0 -0
  389. package/payload/server/public/assets/AdminShell-BMslfZxN.js.gz +0 -0
  390. package/payload/server/public/assets/activity-kQ3w70LJ.js.br +0 -0
  391. package/payload/server/public/assets/activity-kQ3w70LJ.js.gz +0 -0
  392. package/payload/server/public/assets/admin-CkASgYA7.js.br +0 -0
  393. package/payload/server/public/assets/admin-CkASgYA7.js.gz +0 -0
  394. package/payload/server/public/assets/agents-Cn_bZgnD.js.br +0 -0
  395. package/payload/server/public/assets/agents-Cn_bZgnD.js.gz +0 -0
  396. package/payload/server/public/assets/browser-BE-GDk5-.js.br +0 -0
  397. package/payload/server/public/assets/browser-BE-GDk5-.js.gz +0 -0
  398. package/payload/server/public/assets/calendar-Di7BEHHN.js.br +0 -0
  399. package/payload/server/public/assets/calendar-Di7BEHHN.js.gz +0 -0
  400. package/payload/server/public/assets/chat-CKyMT5Ai.js +0 -1
  401. package/payload/server/public/assets/chat-CKyMT5Ai.js.br +0 -1
  402. package/payload/server/public/assets/chat-CKyMT5Ai.js.gz +0 -0
  403. package/payload/server/public/assets/chevron-left-Id9VAZAz.js +0 -1
  404. package/payload/server/public/assets/chevron-left-Id9VAZAz.js.br +0 -0
  405. package/payload/server/public/assets/clock-DKpWWJbJ.js +0 -1
  406. package/payload/server/public/assets/clock-DKpWWJbJ.js.br +0 -0
  407. package/payload/server/public/assets/copy-nkxspu2J.js.br +0 -0
  408. package/payload/server/public/assets/copy-nkxspu2J.js.gz +0 -0
  409. package/payload/server/public/assets/data-1c33cAHp.js +0 -1
  410. package/payload/server/public/assets/data-1c33cAHp.js.br +0 -2
  411. package/payload/server/public/assets/data-1c33cAHp.js.gz +0 -0
  412. package/payload/server/public/assets/field-2rIXxGMt.js.br +0 -0
  413. package/payload/server/public/assets/field-2rIXxGMt.js.gz +0 -0
  414. package/payload/server/public/assets/file-text-CdSqrscg.js.br +0 -0
  415. package/payload/server/public/assets/file-text-CdSqrscg.js.gz +0 -0
  416. package/payload/server/public/assets/graph-BfBHHXaC.js.br +0 -0
  417. package/payload/server/public/assets/graph-BfBHHXaC.js.gz +0 -0
  418. package/payload/server/public/assets/graph-labels-CHW2aBke.js.br +0 -0
  419. package/payload/server/public/assets/graph-labels-CHW2aBke.js.gz +0 -0
  420. package/payload/server/public/assets/jsx-runtime-D43jgaWP.css.br +0 -0
  421. package/payload/server/public/assets/operator-DRn9LITC.js.br +0 -0
  422. package/payload/server/public/assets/operator-DRn9LITC.js.gz +0 -0
  423. package/payload/server/public/assets/page-BwqQsoU8.js.br +0 -0
  424. package/payload/server/public/assets/page-BwqQsoU8.js.gz +0 -0
  425. package/payload/server/public/assets/page-D_9mPS6W.js.br +0 -0
  426. package/payload/server/public/assets/page-D_9mPS6W.js.gz +0 -0
  427. package/payload/server/public/assets/play-7LTxCuLX.js +0 -1
  428. package/payload/server/public/assets/play-7LTxCuLX.js.br +0 -0
  429. package/payload/server/public/assets/play-7LTxCuLX.js.gz +0 -0
  430. package/payload/server/public/assets/public-CrjZYpdW.js.br +0 -0
  431. package/payload/server/public/assets/public-CrjZYpdW.js.gz +0 -0
  432. package/payload/server/public/assets/rotate-ccw-J9f-GWjm.js.br +0 -0
  433. package/payload/server/public/assets/rotate-ccw-J9f-GWjm.js.gz +0 -0
  434. package/payload/server/public/assets/routines-C1AB-3FR.js.br +0 -0
  435. package/payload/server/public/assets/routines-C1AB-3FR.js.gz +0 -0
  436. package/payload/server/public/assets/skills-C4EfNKEx.js.br +0 -0
  437. package/payload/server/public/assets/skills-C4EfNKEx.js.gz +0 -0
  438. package/payload/server/public/assets/tasks-DszD3aZl.js.br +0 -0
  439. package/payload/server/public/assets/tasks-DszD3aZl.js.gz +0 -0
  440. package/payload/server/public/assets/triangle-alert-B5WAyAkC.js.br +0 -4
  441. package/payload/server/public/assets/triangle-alert-B5WAyAkC.js.gz +0 -0
  442. package/payload/server/public/assets/useCopyFeedback-B2nuNNJw.js.br +0 -0
  443. package/payload/server/public/assets/useCopyFeedback-B2nuNNJw.js.gz +0 -0
  444. package/payload/server/public/assets/useMediaQuery-DUPJPHQt.js.br +0 -0
  445. package/payload/server/public/assets/useMediaQuery-DUPJPHQt.js.gz +0 -0
  446. package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js +0 -2
  447. package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js.br +0 -0
  448. package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js.gz +0 -0
  449. package/payload/server/public/assets/wrench-DZJZm17j.js.br +0 -0
  450. package/payload/server/public/assets/wrench-DZJZm17j.js.gz +0 -0
  451. /package/payload/server/public/assets/{jsx-runtime-Cjug_Cyb.js → jsx-runtime-BmNepPEn.js} +0 -0
  452. /package/payload/server/public/assets/{jsx-runtime-Cjug_Cyb.js.br → jsx-runtime-BmNepPEn.js.br} +0 -0
  453. /package/payload/server/public/assets/{jsx-runtime-Cjug_Cyb.js.gz → jsx-runtime-BmNepPEn.js.gz} +0 -0
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isStorableChannelKey = isStorableChannelKey;
4
+ exports.isBusinessChannelKey = isBusinessChannelKey;
5
+ exports.channelKeyToFileStem = channelKeyToFileStem;
6
+ exports.fileStemToChannelKey = fileStemToChannelKey;
7
+ exports.collectTelegramReach = collectTelegramReach;
8
+ /**
9
+ * Task 2625 — which Telegram chats a registered bot can already message.
10
+ *
11
+ * Telegram does not let a bot open a conversation: the person must message it
12
+ * first (core.telegram.org/bots). So "can I reach X" is answerable only from
13
+ * what has already arrived, and the record of that is the message store the
14
+ * webhook writes. Before this module nothing enumerated it, and the agent
15
+ * refused a send that one telegram-card call would have made.
16
+ *
17
+ * Shared rather than duplicated plugin-side, unlike the live-location and card
18
+ * stores: BOTH callers need this same walk — the MCP tool answers one account on
19
+ * demand, the hourly census counts every account — so duplicating it would mean
20
+ * writing the walk twice and holding it together with a boundary test. The
21
+ * filename rule lives here too, and `ui/app/lib/telegram/message-store.ts`
22
+ * re-exports it, so the store that writes a filename and the walk that reads one
23
+ * cannot disagree.
24
+ *
25
+ * Path-free by construction: the caller passes `storeDir`. The plugin derives it
26
+ * from PLATFORM_ROOT and the server from the brand config dir, and neither
27
+ * derivation belongs in a library that must not know what a brand is.
28
+ */
29
+ const node_fs_1 = require("node:fs");
30
+ const node_path_1 = require("node:path");
31
+ /**
32
+ * Is this a channel key that can safely become a path segment?
33
+ *
34
+ * Both halves of an admin key are Telegram numeric ids (a bot id is positive; a
35
+ * chat or sender id is an integer and is negative for groups), so requiring
36
+ * exactly that is both the truthful shape check and a complete traversal guard:
37
+ * no `.`, `/` or `\` can survive it.
38
+ *
39
+ * Task 2615 — the business shape `<botId>:biz:<senderId>` joins the guard rather
40
+ * than bypassing it. Both alternatives are anchored and admit only digits, an
41
+ * optional leading minus and the literal `biz`, so neither can carry a `.`, `/`
42
+ * or `\` either.
43
+ */
44
+ function isStorableChannelKey(channelKey) {
45
+ return /^-?\d+:-?\d+$/.test(channelKey) || /^-?\d+:biz:-?\d+$/.test(channelKey);
46
+ }
47
+ /** Task 2615 — is this the three-part business shape?
48
+ *
49
+ * Its own predicate rather than a `.includes(':biz:')` at each caller: a
50
+ * business conversation is reached through the business-connection send route
51
+ * and its 24-hour window, not by addressing a chat id, so anything that answers
52
+ * "can we message this person now" has to be able to tell the two apart. */
53
+ function isBusinessChannelKey(channelKey) {
54
+ return /^-?\d+:biz:-?\d+$/.test(channelKey);
55
+ }
56
+ /** The filename stem for a channel key.
57
+ *
58
+ * Throws on a key that is neither two numeric ids nor the business shape.
59
+ * Refusing loudly is correct here: every caller reaches this with a key it has
60
+ * already validated, so an unstorable key means a caller skipped its guard, and
61
+ * silently sanitising it would build a path nobody asked for. */
62
+ function channelKeyToFileStem(channelKey) {
63
+ if (!isStorableChannelKey(channelKey)) {
64
+ throw new Error(`telegram-message-store: refusing unstorable channelKey ${JSON.stringify(channelKey)}`);
65
+ }
66
+ // Task 2615 — every colon, not only the first: a business key has two.
67
+ return channelKey.replaceAll(":", "_");
68
+ }
69
+ /** The inverse of `channelKeyToFileStem`.
70
+ *
71
+ * Task 2615 — a stem whose second segment is exactly `biz` is a three-part
72
+ * business key. Otherwise only the FIRST `_` is a separator, because both halves
73
+ * of an admin key are numeric Telegram ids and nothing later in that stem is
74
+ * one. */
75
+ function fileStemToChannelKey(stem) {
76
+ const i = stem.indexOf("_");
77
+ if (i <= 0)
78
+ return stem;
79
+ const rest = stem.slice(i + 1);
80
+ if (rest.startsWith("biz_")) {
81
+ return `${stem.slice(0, i)}:biz:${rest.slice("biz_".length)}`;
82
+ }
83
+ return `${stem.slice(0, i)}:${rest}`;
84
+ }
85
+ function parseLines(raw) {
86
+ const out = [];
87
+ for (const line of raw.split("\n")) {
88
+ if (!line.trim())
89
+ continue;
90
+ try {
91
+ out.push(JSON.parse(line));
92
+ }
93
+ catch {
94
+ // A partial write from a crash mid-append is skipped, never fatal: one
95
+ // corrupt line must not hide every other chat in the account.
96
+ }
97
+ }
98
+ return out;
99
+ }
100
+ /** Every conversation file's newest inbound PRIVATE row, keyed
101
+ * `<botId>:<senderId>`, plus the message rows read getting there. */
102
+ function scanStore(storeDir) {
103
+ const newest = new Map();
104
+ let storeRows = 0;
105
+ if (!storeDir || !(0, node_fs_1.existsSync)(storeDir))
106
+ return { newest, storeRows };
107
+ let entries;
108
+ try {
109
+ entries = (0, node_fs_1.readdirSync)(storeDir);
110
+ }
111
+ catch {
112
+ return { newest, storeRows };
113
+ }
114
+ for (const entry of entries) {
115
+ if (!entry.endsWith(".jsonl"))
116
+ continue;
117
+ const stem = entry.slice(0, -".jsonl".length);
118
+ const channelKey = fileStemToChannelKey(stem);
119
+ if (!isStorableChannelKey(channelKey))
120
+ continue;
121
+ // Task 2615's business conversations are skipped entirely, rows included.
122
+ // A business chat is NOT reached by addressing a chat id: it needs the
123
+ // business-connection send route and its own 24-hour window, which Task 2625
124
+ // put out of scope. Listing one here would report it as sendable with
125
+ // telegram-card, which is the same wrong answer in the opposite direction to
126
+ // the refusal this tool exists to prevent.
127
+ if (isBusinessChannelKey(channelKey))
128
+ continue;
129
+ const botId = channelKey.slice(0, channelKey.indexOf(":"));
130
+ let raw;
131
+ try {
132
+ raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(storeDir, entry), "utf8");
133
+ }
134
+ catch {
135
+ continue;
136
+ }
137
+ for (const row of parseLines(raw)) {
138
+ // An update row is a patch, not a message: counting it would inflate
139
+ // storeRows and it carries no sender at all.
140
+ if (row.kind === "update")
141
+ continue;
142
+ storeRows += 1;
143
+ if (row.origin !== "inbound")
144
+ continue;
145
+ const chatId = typeof row.chatId === "string" ? row.chatId : null;
146
+ const senderId = typeof row.senderId === "string" ? row.senderId : null;
147
+ const dateSent = typeof row.dateSent === "string" ? row.dateSent : null;
148
+ if (chatId === null || senderId === null || dateSent === null)
149
+ continue;
150
+ // Private chats only. A DM chat id equals the sender id; a group's differs
151
+ // (telegram-gateway.ts:66-68). A group is not a route to a person.
152
+ if (chatId !== senderId)
153
+ continue;
154
+ const key = `${botId}:${senderId}`;
155
+ const prev = newest.get(key);
156
+ if (prev !== undefined && prev.dateSent.localeCompare(dateSent) >= 0)
157
+ continue;
158
+ newest.set(key, {
159
+ chatId,
160
+ senderId,
161
+ senderName: typeof row.senderName === "string" ? row.senderName : null,
162
+ dateSent,
163
+ });
164
+ }
165
+ }
166
+ return { newest, storeRows };
167
+ }
168
+ /** Reachability for one account: every registered bot, the private chats that
169
+ * have messaged it, and the allowlisted people who have not. */
170
+ function collectTelegramReach(input) {
171
+ const { newest, storeRows } = scanStore(input.storeDir);
172
+ const bots = input.bots.map((bot) => {
173
+ const adminUsers = bot.adminUsers ?? [];
174
+ const adminSet = new Set(adminUsers.map((u) => String(u)));
175
+ const chats = [];
176
+ const seen = new Set();
177
+ for (const [key, row] of newest) {
178
+ if (key.slice(0, key.indexOf(":")) !== bot.id)
179
+ continue;
180
+ seen.add(row.senderId);
181
+ chats.push({
182
+ chatId: row.chatId,
183
+ senderId: row.senderId,
184
+ displayName: row.senderName,
185
+ lastInbound: row.dateSent,
186
+ admin: adminSet.has(row.senderId),
187
+ reachable: true,
188
+ });
189
+ }
190
+ chats.sort((a, b) => (b.lastInbound ?? "").localeCompare(a.lastInbound ?? ""));
191
+ for (const user of adminUsers) {
192
+ const senderId = String(user);
193
+ if (seen.has(senderId))
194
+ continue;
195
+ // Listed, never messaged. Reported rather than omitted, because "we are
196
+ // allowed to talk to them" and "they have opened the chat" are different
197
+ // facts and only the second one makes a send possible.
198
+ chats.push({
199
+ chatId: null,
200
+ senderId,
201
+ displayName: null,
202
+ lastInbound: null,
203
+ admin: true,
204
+ reachable: false,
205
+ });
206
+ }
207
+ return { botId: bot.id, role: bot.role, adminUsers, chats };
208
+ });
209
+ return { bots, storeRows };
210
+ }
211
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import {
6
+ collectTelegramReach,
7
+ isStorableChannelKey,
8
+ isBusinessChannelKey,
9
+ channelKeyToFileStem,
10
+ fileStemToChannelKey,
11
+ } from "../index.js";
12
+
13
+ const BOT = "8801383568";
14
+ const KIT = "8860040117";
15
+ const NEO = "1311221864";
16
+ const GROUP = "-1002222222222";
17
+
18
+ let storeDir: string;
19
+
20
+ /** One inbound message row, in the shape message-store.ts writes. */
21
+ const inbound = (over: Record<string, unknown> = {}) => ({
22
+ messageId: `telegram:acct:${BOT}:${KIT}:in:1`,
23
+ sessionId: "s",
24
+ dateSent: "2026-08-09T07:46:31.000Z",
25
+ body: "hello",
26
+ fromMe: false,
27
+ senderId: KIT,
28
+ senderName: "Kit Smalley",
29
+ chatId: KIT,
30
+ channelKey: `${BOT}:${KIT}`,
31
+ scope: "admin",
32
+ origin: "inbound",
33
+ createdAt: "2026-08-09T07:46:31.000Z",
34
+ ...over,
35
+ });
36
+
37
+ function writeConversation(channelKey: string, rows: unknown[]): void {
38
+ const file = join(storeDir, `${channelKeyToFileStem(channelKey)}.jsonl`);
39
+ writeFileSync(file, rows.map((r) => JSON.stringify(r)).join("\n") + "\n", "utf8");
40
+ }
41
+
42
+ beforeEach(() => {
43
+ storeDir = mkdtempSync(join(tmpdir(), "tg-reach-"));
44
+ });
45
+
46
+ afterEach(() => {
47
+ rmSync(storeDir, { recursive: true, force: true });
48
+ });
49
+
50
+ describe("the key helpers", () => {
51
+ it("accepts two numeric ids and rejects a traversal", () => {
52
+ expect(isStorableChannelKey(`${BOT}:${KIT}`)).toBe(true);
53
+ expect(isStorableChannelKey(`${BOT}:${GROUP}`)).toBe(true);
54
+ expect(isStorableChannelKey("../../../../etc/passwd:x")).toBe(false);
55
+ });
56
+
57
+ it("round-trips a key through its filename stem", () => {
58
+ expect(fileStemToChannelKey(channelKeyToFileStem(`${BOT}:${KIT}`))).toBe(`${BOT}:${KIT}`);
59
+ });
60
+
61
+ // Task 2615's three-part business shape. Round-tripping it is what keeps its
62
+ // conversations readable at all; telling it apart is what keeps them out of
63
+ // the reachable list.
64
+ it("round-trips a business key and recognises it as one", () => {
65
+ const biz = `${BOT}:biz:${KIT}`;
66
+ expect(isStorableChannelKey(biz)).toBe(true);
67
+ expect(channelKeyToFileStem(biz)).toBe(`${BOT}_biz_${KIT}`);
68
+ expect(fileStemToChannelKey(`${BOT}_biz_${KIT}`)).toBe(biz);
69
+ expect(isBusinessChannelKey(biz)).toBe(true);
70
+ expect(isBusinessChannelKey(`${BOT}:${KIT}`)).toBe(false);
71
+ });
72
+
73
+ it("refuses to build a stem from an unstorable key", () => {
74
+ expect(() => channelKeyToFileStem("a/b:c")).toThrow(/refusing unstorable channelKey/);
75
+ });
76
+ });
77
+
78
+ describe("collectTelegramReach", () => {
79
+ it("reports one entry per registered bot", () => {
80
+ const out = collectTelegramReach({
81
+ storeDir,
82
+ bots: [
83
+ { id: BOT, role: "admin", adminUsers: [] },
84
+ { id: "7777777777", role: "public" },
85
+ ],
86
+ });
87
+ expect(out.bots.map((b) => b.botId)).toEqual([BOT, "7777777777"]);
88
+ });
89
+
90
+ it("returns an empty chat list for a bot with no inbound, not an error", () => {
91
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
92
+ expect(out.bots[0].chats).toEqual([]);
93
+ expect(out.storeRows).toBe(0);
94
+ });
95
+
96
+ it("lists a chat that has messaged, with the newest inbound name and time", () => {
97
+ writeConversation(`${BOT}:${KIT}`, [
98
+ inbound(),
99
+ inbound({
100
+ messageId: "m2",
101
+ dateSent: "2026-08-09T09:00:00.000Z",
102
+ senderName: "Kit S",
103
+ }),
104
+ ]);
105
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
106
+ expect(out.bots[0].chats).toEqual([
107
+ {
108
+ chatId: KIT,
109
+ senderId: KIT,
110
+ displayName: "Kit S",
111
+ lastInbound: "2026-08-09T09:00:00.000Z",
112
+ admin: false,
113
+ reachable: true,
114
+ },
115
+ ]);
116
+ expect(out.storeRows).toBe(2);
117
+ });
118
+
119
+ it("marks a chat that is also an adminUsers entry", () => {
120
+ writeConversation(`${BOT}:${KIT}`, [inbound()]);
121
+ const out = collectTelegramReach({
122
+ storeDir,
123
+ bots: [{ id: BOT, role: "admin", adminUsers: [Number(KIT)] }],
124
+ });
125
+ expect(out.bots[0].chats[0].admin).toBe(true);
126
+ });
127
+
128
+ it("lists an adminUsers entry that has never messaged as not reachable", () => {
129
+ const out = collectTelegramReach({
130
+ storeDir,
131
+ bots: [{ id: BOT, role: "admin", adminUsers: [Number(KIT)] }],
132
+ });
133
+ expect(out.bots[0].chats).toEqual([
134
+ {
135
+ chatId: null,
136
+ senderId: KIT,
137
+ displayName: null,
138
+ lastInbound: null,
139
+ admin: true,
140
+ reachable: false,
141
+ },
142
+ ]);
143
+ });
144
+
145
+ it("excludes a group: its chatId differs from its senderId", () => {
146
+ writeConversation(`${BOT}:${KIT}`, [inbound({ chatId: GROUP })]);
147
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
148
+ expect(out.bots[0].chats).toEqual([]);
149
+ expect(out.storeRows).toBe(1);
150
+ });
151
+
152
+ it("does not make a chat reachable on agent or operator rows alone", () => {
153
+ writeConversation(`${BOT}:${KIT}`, [
154
+ inbound({ origin: "agent" }),
155
+ inbound({ messageId: "m2", origin: "operator-manual" }),
156
+ ]);
157
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
158
+ expect(out.bots[0].chats).toEqual([]);
159
+ expect(out.storeRows).toBe(2);
160
+ });
161
+
162
+ it("never counts an update row as a message and never makes it a chat", () => {
163
+ writeConversation(`${BOT}:${KIT}`, [
164
+ { kind: "update", targetMessageId: "m1", body: "x", createdAt: "2026-08-09T07:47:00.000Z" },
165
+ ]);
166
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
167
+ expect(out.storeRows).toBe(0);
168
+ expect(out.bots[0].chats).toEqual([]);
169
+ });
170
+
171
+ it("counts rows belonging to an unregistered bot, so a mis-scoped bot list is visible", () => {
172
+ writeConversation(`9999999999:${KIT}`, [inbound({ channelKey: `9999999999:${KIT}` })]);
173
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
174
+ expect(out.bots[0].chats).toEqual([]);
175
+ expect(out.storeRows).toBe(1);
176
+ });
177
+
178
+ // A business chat is reached through the business-connection route and its
179
+ // 24-hour window, never by addressing a chat id, so reporting one here would
180
+ // be the same wrong answer as the refusal this tool exists to prevent, only in
181
+ // the opposite direction. Its rows are not counted either: they were never
182
+ // walked.
183
+ it("skips a business conversation entirely, rows included", () => {
184
+ writeConversation(`${BOT}:biz:${KIT}`, [inbound({ channelKey: `${BOT}:biz:${KIT}` })]);
185
+ const out = collectTelegramReach({ storeDir, bots: [{ id: BOT, role: "admin" }] });
186
+ expect(out.bots[0].chats).toEqual([]);
187
+ expect(out.storeRows).toBe(0);
188
+ });
189
+
190
+ it("reads an absent store directory as no rows rather than throwing", () => {
191
+ const out = collectTelegramReach({
192
+ storeDir: join(storeDir, "nope"),
193
+ bots: [{ id: BOT, role: "admin" }],
194
+ });
195
+ expect(out.storeRows).toBe(0);
196
+ expect(out.bots[0].chats).toEqual([]);
197
+ });
198
+
199
+ it("orders reachable chats newest first, then the never-messaged admins", () => {
200
+ writeConversation(`${BOT}:${KIT}`, [inbound()]);
201
+ writeConversation(`${BOT}:${NEO}`, [
202
+ inbound({
203
+ senderId: NEO,
204
+ chatId: NEO,
205
+ channelKey: `${BOT}:${NEO}`,
206
+ senderName: "Neo",
207
+ dateSent: "2026-08-09T08:08:12.000Z",
208
+ }),
209
+ ]);
210
+ const out = collectTelegramReach({
211
+ storeDir,
212
+ bots: [{ id: BOT, role: "admin", adminUsers: [Number(KIT), 5555555555] }],
213
+ });
214
+ expect(out.bots[0].chats.map((c) => c.senderId)).toEqual([NEO, KIT, "5555555555"]);
215
+ });
216
+ });