@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
@@ -17,10 +17,11 @@ and this skill says how to call it.
17
17
 
18
18
  ## What you have
19
19
 
20
- Ten named tools for the common paths, and one passthrough for everything else.
20
+ Eleven named tools for the common paths, and one passthrough for everything else.
21
21
 
22
22
  | Tool | Use it for |
23
23
  |---|---|
24
+ | `mcp__telegram__telegram-reach` | Which chats each registered bot can message now, and which allowlisted admins have never messaged it |
24
25
  | `mcp__telegram__telegram-card` | Posting a card, or editing the one your key already names |
25
26
  | `mcp__telegram__telegram-ask` | Polls, checklists, locations, venues, contacts, dice |
26
27
  | `mcp__telegram__telegram-media-send` | Sending a photo, file, video, audio or album, and editing media or captions |
@@ -36,7 +37,20 @@ Ten named tools for the common paths, and one passthrough for everything else.
36
37
  `telegram-api` takes `botId` (never a token), `method`, `params`, and optionally `files` and
37
38
  `timeoutMs`. Field names inside `params` are Telegram's own snake_case.
38
39
 
39
- ## The five methods it will not call
40
+ ## Who you can send to
41
+
42
+ Telegram does not let a bot open a conversation. Somebody who has messaged one of this account's
43
+ bots can be messaged back at any time with `telegram-card` and their chat id; somebody who never has
44
+ must write to the bot first, and no tool here can shortcut that.
45
+
46
+ `telegram-reach` is what tells the two apart. It takes no parameters and lists, per registered bot,
47
+ every private chat that has messaged it — chat id, name, and when they last wrote — plus any admin
48
+ user allowlisted on that bot who has never messaged. Being on the allowlist is not the same fact as
49
+ having opened the chat, and only the second one makes a send possible.
50
+
51
+ Read it before telling anybody a Telegram send is impossible.
52
+
53
+ ## The seven methods it will not call
40
54
 
41
55
  Each refusal names the tool that owns the capability instead.
42
56
 
@@ -45,6 +59,41 @@ Each refusal names the tool that owns the capability instead.
45
59
  | `setWebhook`, `deleteWebhook` | Webhook state is registered on the one path the maxy edge admits, stamped with the bot id. A raw call silently repoints or stops every inbound message | `telegram-webhook-register` |
46
60
  | `getUpdates` | Telegram's two ways of receiving updates are mutually exclusive, and this one does not work while a webhook is set | The webhook already delivers inbound |
47
61
  | `logOut`, `close` | Both move the bot off the cloud Bot API server | Nothing. Do not do this |
62
+ | `getManagedBotToken`, `replaceManagedBotToken` | The result IS a live bot token. Relaying it puts a credential in a tool result, and therefore in the transcript | `telegram-bot-provision`, which persists tokens and returns only bot ids |
63
+
64
+ `getManagedBotAccessSettings` and `setManagedBotAccessSettings` are NOT refused: they return no
65
+ credential, so refusing them would remove a capability while protecting nothing. Prefer
66
+ `telegram-bot-provision action=access` anyway, which logs the change.
67
+
68
+ ## Creating a bot without BotFather
69
+
70
+ `telegram-bot-provision` has four actions.
71
+
72
+ | Action | What it does |
73
+ |---|---|
74
+ | `offer` | Sends a one-tap button into a private chat. The person taps it, names the bot, and this install receives it, stores its token, restricts it to its owner and registers its webhook |
75
+ | `rotate` | Revokes a managed bot's token, saves the replacement, and re-registers the webhook at the URL it was already on |
76
+ | `access` | Reads the access settings when `isAccessRestricted` is omitted; writes them when it is given. Up to ten `addedUserIds` besides the owner |
77
+ | `list` | This account's bots by id and role. Never a token |
78
+
79
+ ```
80
+ telegram-bot-provision botId=<managing-bot> action=offer chatId=<private-chat>
81
+ suggestedName="Front Desk" suggestedUsername="frontdesk_bot"
82
+ ```
83
+
84
+ Three things to know before using it:
85
+
86
+ - The managing bot must have management of other bots enabled **once**, in the @BotFather Mini App.
87
+ No API call turns it on. `offer` checks `getMe().can_manage_bots` and refuses with the Mini App
88
+ named, so a button that would do nothing is never sent.
89
+ - The button is a REPLY keyboard and Telegram makes it **private chats only**. A group or channel
90
+ id will not work.
91
+ - A provisioned bot lands as `role:'unbound'` and answers nobody until an agent is bound to it. It
92
+ is restricted to its owner on Telegram's side at the same time.
93
+
94
+ Telegram sends no `request_id` back and no event discriminator, so a creation and a token change
95
+ are told apart only by whether the account already holds the bot id, and the log correlates on
96
+ `newBotId` rather than on the request id.
48
97
 
49
98
  ## Five things people actually build
50
99
 
@@ -166,6 +215,21 @@ form needs forum topic mode enabled on the bot: `sendMessage`'s `message_thread_
166
215
  working "for forum supergroups and private chats of bots with forum topic mode enabled only", so
167
216
  without it the topic exists and nothing can be sent into it.
168
217
 
218
+ **A message from a topic is answered in that topic, and you do not arrange it.** The route reads the
219
+ topic off the inbound and threads it through the reply, so your turn's final text lands where the
220
+ question was asked. You only pass `messageThreadId` yourself when you are sending into a topic
221
+ nobody just wrote in.
222
+
223
+ **A checklist cannot go into a topic.** `sendChecklist` is the one send method with no
224
+ `message_thread_id` in its table. `telegram-ask` refuses that pair before the network call rather
225
+ than dropping the field and letting the checklist land in the group's General thread, which used to
226
+ read as the call having worked. Send it without `messageThreadId`, or use a poll or a plain message
227
+ for the topic itself.
228
+
229
+ **Only a real topic counts.** Telegram also stamps `message_thread_id` on an ordinary reply in a
230
+ supergroup, so the route keys on `is_topic_message` instead. A plain reply is answered in the
231
+ conversation, not pulled into a thread.
232
+
169
233
  ### 8. Asking a question, or sending a place
170
234
 
171
235
  `telegram-ask` covers the structured sends. A poll takes its answers as plain strings:
@@ -188,9 +252,40 @@ telegram-ask botId=<id> chatId=<chat> kind=editLiveLocation messageId=<id> latit
188
252
  longitude=-0.13
189
253
  ```
190
254
 
191
- `venue`, `contact` and `dice` are one call each. The two checklist kinds need
192
- `businessConnectionId`: Telegram sends a checklist only on behalf of a connected business account,
193
- and refuses without it.
255
+ `venue`, `contact` and `dice` are one call each.
256
+
257
+ **The two checklist kinds need a connected business account, and you do not have to find its
258
+ identifier yourself.** `business_connection_id` is required on `sendChecklist` and
259
+ `editMessageChecklist` and there is no variant without it, so a bot can never send a checklist as
260
+ itself. Telegram announces the identifier once, on a `business_connection` update, when the operator
261
+ connects the bot under Telegram, Settings, Business, Chatbots. This install captures it and stores it
262
+ per bot, so `telegram-ask kind=checklist` with no `businessConnectionId` sends on the stored
263
+ connection. Pass one explicitly only to override that. With nothing stored the tool refuses and names
264
+ the operator step, which means the answer is to ask the operator to connect the bot, not to hunt for
265
+ a parameter.
266
+
267
+ **A customer messaging the connected business account reaches you in their own conversation, not the
268
+ operator's.** Once the operator connects the bot under Telegram, Settings, Business, Chatbots, every
269
+ message in that account's private chats arrives here as a turn of its own. Four things follow.
270
+
271
+ The turn is a **stranger's**, so it runs as the entry's public agent and carries none of the
272
+ operator's standing rules, whatever role the bot itself holds. The two conversations never share a
273
+ session even when the same person is in both.
274
+
275
+ Every reply **quotes the connection**, and you do not supply it: `telegram-card` and the turn's own
276
+ reply fill it in from the stored connection. Telegram routes the message as the business account
277
+ rather than as the bot, and there is no variant without it.
278
+
279
+ The **24-hour window is a hard limit**. `BusinessBotRights.can_reply` grants the right to answer only
280
+ "in the private chats that had incoming messages in the last 24 hours". A send past that is refused
281
+ here before it is attempted, and the refusal names the window. Nothing is emitted when a window
282
+ closes, so a customer you leave unanswered simply becomes unreachable with no error anywhere. Answer
283
+ while you can.
284
+
285
+ An edit from the customer **changes the message you already have** rather than arriving as a new one.
286
+ It still raises a turn, because a customer who rewrites their question has asked something new; what
287
+ it does not do is leave you two messages to reconcile. A deletion marks the message deleted rather
288
+ than removing it, so what was withdrawn stays readable, and it raises no turn at all.
194
289
 
195
290
  **A business connection and Telegram Premium are two separate gates, and they govern different
196
291
  things.** Telegram states them apart, so do not treat one as the other. Bot API 9.1 (3 July 2025)
@@ -199,8 +294,20 @@ business account" — that gate is the business connection, and it is the one `b
199
294
  carries. Bot API 9.4 (9 February 2026) allowed "custom emoji in messages directly sent by the bot to
200
295
  private, group and supergroup chats if the owner of the bot has a Telegram Premium subscription" —
201
296
  that gate is Premium, it is on the bot's OWNER rather than on a connection, and it governs custom
202
- emoji, not checklists. Whether Telegram Business itself requires Premium is not stated in Telegram's
203
- documentation, so do not tell an operator that it does or that it does not.
297
+ emoji, not checklists.
298
+
299
+ On Premium and Business, `core.telegram.org/api/business` says two things and you need both. "All
300
+ Telegram Business features are available for free to Premium subscribers." And: "Additionally,
301
+ connected bots are also available to non-Premium users." A checklist rides on a connected bot, so do
302
+ not tell an operator that a checklist requires Premium. If Telegram nevertheless answers
303
+ `PREMIUM_ACCOUNT_REQUIRED` on a `sendChecklist` that carried a valid `business_connection_id`, that is
304
+ a finding worth reporting rather than a settled fact.
305
+
306
+ **A Mini App button and a checklist cannot share one message.** Telegram's `InlineKeyboardButton`
307
+ table says a `web_app` button is "Available only in private chats between a user and the bot. Not
308
+ supported for messages sent on behalf of a business account." A checklist is sent on behalf of a
309
+ business account, so send the Mini App button as its own ordinary message. This install's Mini App is
310
+ `/field?bot=<botId>` on the install's own origin, not the public site.
204
311
 
205
312
  ### 9. Charging for something
206
313
 
@@ -221,10 +328,19 @@ keyboard to be a Pay button, and leaving the keyboard off gets that button for f
221
328
  `payload` is your own reference. It is never shown to the payer and it comes back on the
222
329
  successful-payment update, which is how a payment is matched to a job.
223
330
 
224
- Set `isFlexible` and Telegram sends a shipping query mid-checkout; answer it with
225
- `action=answerShipping`, and answer the pre-checkout query that follows within ten seconds with
226
- `action=answerPreCheckout`. `ok=false` on either needs `errorMessage`, which Telegram shows the
227
- payer verbatim. `balance`, `transactions`, `refund` and `editSubscription` are the Stars controls.
331
+ **You do not answer the pre-checkout query.** Telegram cancels the transaction if no answer lands
332
+ within ten seconds, and a turn cannot start and finish in ten seconds, so the inbound route answers
333
+ it itself: `ok=true` for a sender with access, `ok=false` for one without. You then get a turn saying
334
+ `[pre-checkout approved: …]`, and once the payer confirms, a second one saying
335
+ `[payment received: …]` with your own `payload` on it. `action=answerPreCheckout` stays on the tool
336
+ for a surface that answers out of band; calling it for a query the route has already answered gets a
337
+ Telegram error about a stale id.
338
+
339
+ Set `isFlexible` and Telegram sends a shipping query mid-checkout. That one **is** yours: the route
340
+ raises a turn saying `[shipping query: …]` with the `queryId`, because only you know the options.
341
+ Answer it with `action=answerShipping`. `ok=false` needs `errorMessage`, which Telegram shows the
342
+ payer verbatim. `balance`, `transactions`, `refund` and `editSubscription` are the Stars controls; a
343
+ subscription that is cancelled, re-enabled or fails to charge arrives as its own turn.
228
344
 
229
345
  ### Ephemeral messages
230
346
 
@@ -235,6 +351,96 @@ other send methods. The resulting message has `message_id: 0` and carries its id
235
351
  address. Send one through `telegram-api`; no named tool covers it, because nothing on this install
236
352
  sends group messages visible to a single user.
237
353
 
354
+ ## What arrives from Telegram
355
+
356
+ Telegram defines twenty-six update classes. This install registers twenty-two and handles seventeen
357
+ of them.
358
+
359
+ | Class | Registered | What happens |
360
+ |---|---|---|
361
+ | `message`, `edited_message` | yes | a turn, with media, transcription, location and the quoted original when the sender replied |
362
+ | `callback_query` | yes | answered, stored, and a turn unless it is a dispatch button |
363
+ | `poll_answer` | yes | a turn per voter |
364
+ | `poll` | yes | a turn on close only, naming the question and the counts |
365
+ | `message_reaction` | yes | a turn naming the emoji and the message reacted to |
366
+ | `pre_checkout_query` | yes | answered by the route inside ten seconds, then a turn |
367
+ | `shipping_query` | yes | a turn; you answer it with `telegram-invoice action=answerShipping` |
368
+ | `subscription` | yes | a turn naming the state (`canceled`, `active`, `failed`) |
369
+ | `my_chat_member` | yes | logged only, no turn: in a DM this is a block or an unblock |
370
+ | `business_connection` | yes | recorded so `business_connection_id` can be supplied |
371
+ | `business_message` | yes | a turn, in the customer's own session |
372
+ | `edited_business_message` | yes | a turn, and it patches the message rather than adding one |
373
+ | `deleted_business_messages` | yes | marks the stored rows deleted, no turn |
374
+ | `chat_member` | yes | logged only, no turn: another member joined, left or was removed |
375
+ | `chat_join_request` | yes | logged only, no turn |
376
+ | `message_reaction_count` | yes | logged against the message, no turn: the anonymous tally, as against `message_reaction` which names the reactor |
377
+ | `chat_boost`, `removed_chat_boost` | yes | logged only, no turn |
378
+ | `channel_post`, `edited_channel_post` | yes | a turn, attributed to the channel, when the channel is allowlisted |
379
+ | everything else | no | does not arrive |
380
+
381
+ None of `chat_member`, `chat_join_request`, `message_reaction_count` or the two boost classes raises
382
+ a turn, and none takes an access decision: they are things that happened, with nobody addressing the
383
+ bot, so there is nobody to admit or refuse.
384
+
385
+ **A channel post has no author.** Telegram documents `Message.from` as "may be empty for messages
386
+ sent to channels", so the turn names the channel by its title and there is no person in it. Do not
387
+ address a channel post as if somebody wrote it.
388
+
389
+ **A reaction may never arrive in a DM.** Telegram documents `message_reaction` as requiring the bot
390
+ to be an administrator in the chat, and a private chat has no administrator. The class is registered
391
+ and the handler exists; if nothing ever arrives from a DM, reactions are group-only here.
392
+
393
+ ### The `allowed_updates` trap
394
+
395
+ Naming **any** class in `allowed_updates` replaces Telegram's default set. Telegram's default is
396
+ every class except `chat_member`, `message_reaction` and `message_reaction_count` — so a class that
397
+ works today and is missing from the list stops arriving, with no error in any log.
398
+
399
+ Those same three are the ones outside the default, so a bot registered before they were added
400
+ receives none of them until it re-registers. That is not a failure anything reports: the bot simply
401
+ never sees a reaction or a membership change.
402
+
403
+ The list lives in exactly one place, `TELEGRAM_ALLOWED_UPDATES` in
404
+ `platform/lib/telegram-managed-bot/` (re-exported from
405
+ `plugins/telegram/mcp/src/lib/telegram.ts`). Add a class there and nowhere else, and re-register the
406
+ webhook: `allowed_updates` is set at registration, so an existing bot keeps the list it was
407
+ registered with. `telegram-webhook-register` prints
408
+ `op=webhook-allowed … match=yes|no` against what `getWebhookInfo` reports back; `match=no` means
409
+ Telegram registered something narrower than was asked for.
410
+
411
+ The registration test asserts the whole array, not that a particular name is in it, because the
412
+ failure it guards against is a name silently dropped.
413
+
414
+ ## Sending to a channel or a group
415
+
416
+ Every send whose chat id you choose is checked before it reaches Telegram. A chat id beginning
417
+ `-100` is a channel or a supergroup — Telegram gives the two the same id shape and nothing local can
418
+ tell them apart — and it is refused unless the operator listed it in that bot's `allowChannels` or
419
+ `allowGroups`. The refusal names the id and both fields, and nothing is sent.
420
+
421
+ This is a refusal, not a retry. A channel post reaches every subscriber and cannot be unsent, so the
422
+ check happens before the network call rather than after Telegram's answer. If you are refused, say
423
+ so plainly and name the id; do not try another tool, and do not reach for `telegram-api` to route
424
+ around it, because the same check applies there on `params.chat_id`.
425
+
426
+ Both lists live on public bot entries only. An admin, specialist or unbound bot reaches no channel
427
+ and no group, in either direction.
428
+
429
+ A private chat id (positive) and a basic group id (negative, no `-100`) are unaffected.
430
+
431
+ ## Answering a comment on a channel post
432
+
433
+ Telegram builds a comment thread by auto-forwarding each channel post into the channel's linked
434
+ discussion group. That forwarded copy is the thread root, and it is not a message anybody sent you:
435
+ it raises no turn, because the post itself already reached you through the channel.
436
+
437
+ A comment arrives as an ordinary group message whose turn carries the root's message id. Answer by
438
+ replying beneath that root, not at the bottom of the group, or the answer reads to everyone in the
439
+ thread as no answer at all.
440
+
441
+ A commenter who posted anonymously has no personal identity. The turn names the group they commented
442
+ as, which is the only identity Telegram supplies.
443
+
238
444
  ## Reading the method list
239
445
 
240
446
  `references/methods.md` carries all 185 names grouped as Telegram documents them: Getting updates,
@@ -18,12 +18,30 @@ A finished Telegram setup has all of these, and the skill is not done until each
18
18
  - The bot is stored as one entry in `account.json`'s `telegram.bots` array (under the brand install, never `~/.claude/`). The `telegram-webhook-register` tool writes it there and logs `[telegram-setup] op=token-write dir=… brand=…`.
19
19
  - The webhook is registered against a URL whose path is `/api/telegram/` (the only path the maxy edge admits). The register tool refuses any other path and logs `op=webhook-register path=… botId=… account=… admitted=false` when it does.
20
20
  - The registered URL carries `bot=<botId>`, the bot's own Telegram id. The register tool derives it from the token and appends it, so you never type it. The receiver requires it and rejects `reason=unknown-bot`; the bot id is what determines the account, so no `account=` is carried.
21
- - The bot's `role` is stated, not inferred: `admin` or `public`. It selects the spawn path, so it is a privilege decision.
22
- - Access policy is set **on that entry**: an admin bot carries the operator's numeric Telegram user IDs (`adminUsers`); a public bot carries a DM policy (and an allowlist when the policy is `allowlist`). Nothing is shared with the account's other bots.
23
- - A public bot names the `agent` it answers as, and that agent is active. An admin bot names none: it reads `agents/admin` by construction.
21
+ - The bot's `role` is stated, not inferred: `admin`, `public` or `specialist`. It selects the spawn path, so it is a privilege decision. (A bot that arrived through the one-tap path lands as `unbound`, which answers nobody; giving it a role is what finishes it.)
22
+ - Access policy is set **on that entry**: an admin bot carries the operator's numeric Telegram user IDs (`adminUsers`); a public bot carries a DM policy (and an allowlist when the policy is `allowlist`); a specialist bot carries `allowFrom` and nothing else, because there is no open policy for that role. Nothing is shared with the account's other bots.
23
+ - A public bot names the `agent` it answers as, and that agent is active. A specialist bot names the `specialist` card it runs as, and the account has that card. An admin bot names neither: it reads `agents/admin` by construction.
24
+ - If the bot is to work in a **group**, it is a public bot (never an admin or specialist bot), its group privacy mode is on in BotFather before registration, and every group it answers in is listed by chat id on that entry (`groupPolicy: 'allowlist'`, `allowGroups`). An admin bot cannot be used in a group at all.
25
+ - If the bot is to work in a **channel**, it is a public bot for the same reason, it is a channel administrator with post rights, and every channel it reads or posts to is listed by chat id on that entry (`channelPolicy: 'allowlist'`, `allowChannels`). The list gates both directions: a channel not on it is neither read nor posted to. An admin bot cannot be used in a channel at all, and it can no longer post to any group or channel either, in either direction.
24
26
 
25
27
  An account may hold any number of bots. Registering, re-pointing or removing one never disturbs another, in any account.
26
28
 
29
+ ## Two ways in, and the first one is preferred
30
+
31
+ **The one-tap path.** If this account already has a working admin bot, a new bot needs no BotFather
32
+ visit and no token typed anywhere. Call `telegram-bot-provision action=offer` with that admin bot's
33
+ id and the operator's private chat id. They tap the button, name the bot, and this install receives
34
+ it, stores its token, restricts it to its owner and registers its webhook by itself. What arrives is
35
+ a `role:'unbound'` entry that answers nobody; binding it to an agent is the only step left.
36
+
37
+ That path needs the managing bot to have management of other bots enabled **once**, in the
38
+ @BotFather Mini App. No API call turns it on. `offer` checks first and refuses with the Mini App
39
+ named rather than sending a button that would do nothing.
40
+
41
+ **The BotFather path**, below, is still the way in for the first bot on an install, and for a bot
42
+ the operator already owns. Everything after Step 1 applies to it alone: a provisioned bot has
43
+ already had Steps 1, 3, 4 and 5 done for it.
44
+
27
45
  ## Flow
28
46
 
29
47
  Read `references/setup-guide.md` (cited throughout this flow) with the `plugin-read` tool (`file="references/setup-guide.md"`), which resolves it at the plugin root. A plain `Read` against this skill's base directory misses, because the file lives one level up at the plugin root, not under the skill.
@@ -32,12 +50,17 @@ Read `references/setup-guide.md` (cited throughout this flow) with the `plugin-r
32
50
 
33
51
  Follow `references/setup-guide.md` "Creating a Bot": the operator creates the bot via @BotFather and gives you the token (e.g. `123456:ABC-DEF…`). Confirm you have it before continuing.
34
52
 
53
+ Skip this step entirely when the account already has a working admin bot: use `telegram-bot-provision action=offer` instead, and no token is ever handled by anyone.
54
+
35
55
  ### Step 2 — Decide the role, and for a public bot its agent
36
56
 
37
57
  Ask which role this bot serves (see `references/setup-guide.md` "Admin Bot vs Public Bot"). The role is stated by the operator, never worked out from anything else: it decides which spawn path the bot's messages take.
38
58
 
39
59
  - **Admin bot** — only the numeric Telegram user IDs the operator names for THIS bot may message it; everything else is denied. Collect those IDs (`references/setup-guide.md` "Finding Your Telegram User ID"). It answers as the admin agent.
40
60
  - **Public bot** — customer-facing; choose a DM policy (`open`, `allowlist`, or `disabled`), for `allowlist` the allowed numeric IDs, and **which of this account's agents answers on it**. Call `account-manage` to list the account's agents and let the operator pick one. The agent must be active; the register tool refuses an inactive or unknown slug.
61
+ - **Specialist bot** — a bot bound to one of the account's own specialist cards, so messaging it runs that specialist with its own prompt and its own tools instead of the admin seat. Collect two things: **which card** (the file name under the account's `specialists/agents/`, without `.md` — that is the name the spawn resolves, not the card's title) and **who may message it** (numeric IDs). Both are required: there is no open policy for this role, because the session carries the card's own tool surface rather than the public zero-tool ringfence.
62
+
63
+ If the operator wants this bot in a **group**, say plainly that groups are a public-bot feature. An admin bot added to a group answers nobody: it would otherwise put the operator's own agent, with the operator's own standing rules and tools, into a room other people read, and every member's messages into its context. There is no setting that changes this.
41
64
 
42
65
  The account may already hold other bots. This one is added alongside them and shares nothing with them.
43
66
 
@@ -54,15 +77,62 @@ The register tool aborts on any other path, so do not invent `/channels/telegram
54
77
  Call `telegram-webhook-register` with:
55
78
  - `botToken` — the BotFather token
56
79
  - `webhookUrl` — the URL from Step 3
57
- - `role` — `admin` or `public`
80
+ - `role` — `admin`, `public` or `specialist`
58
81
  - admin bot: `adminUsers` — the numeric IDs from Step 2
59
82
  - public bot: `agent` — the slug from Step 2, plus `dmPolicy` and, for `allowlist`, `allowFrom`
83
+ - specialist bot: `specialist` — the card file name from Step 2, plus `allowFrom` (both required)
84
+
85
+ On success the tool has, in this order: verified the token, derived the bot id, set the webhook with a generated secret (written to `~/.<brand>/telegram-secrets/<botId>`), probed Telegram and confirmed no delivery error since the registration, and only then persisted the entry into `account.json`'s `telegram.bots` array. It logs `op=webhook-register admitted=true` + `op=webhook-verify reachable=true` + `op=token-write`. It replaces only the entry with this bot's id, so the account's other bots are untouched. If it returns an error, read it back to the operator verbatim — the common ones are a wrong path (`admitted=false`), a webhook Telegram cannot reach (`op=webhook-verify reachable=false`), a public bot with no or an inactive `agent` (`op=token-write-rejected reason=no-agent|agent-inactive`), a specialist bot with no card, an unknown card or an empty allowlist (`op=token-write-rejected reason=no-specialist|specialist-unknown|no-allowlist`), or a token write blocked outside the brand install.
86
+
87
+ ### Step 4a — Groups, when the bot is to work in one
88
+
89
+ Only for a public bot, and only if the operator asked for it. Skip this step entirely otherwise.
90
+
91
+ The outcome is that an allowlisted group can address the bot and gets an answer in that group, and that the bot reads nothing else said in the room.
92
+
93
+ Three things have to be true, and the register tool has already checked the first:
94
+
95
+ - **Group privacy mode is ON in BotFather.** With it off the bot receives every message anyone types in every group it joins. `telegram-webhook-register` refuses such a bot outright and logs `[telegram-webhook] op=group-preflight … canReadAllGroupMessages=true verdict=refused`, naming the BotFather step. With it on, Telegram delivers only commands, @mentions and replies to the bot's own messages, which is why no further "was I being addressed" rule exists anywhere in the code.
96
+ - **The bot is in the group.** A group admin adds it. The install cannot do this and does not try.
97
+ - **The group's chat id is on the entry.** Set `groupPolicy: 'allowlist'` and put the numeric chat id in `allowGroups`. A supergroup id is negative and long, e.g. `-1001234567890`. Until the id is listed, the bot answers nobody in that room and logs `op=group-refused … reason=not-in-allowGroups`.
98
+
99
+ The chat is what is admitted, not its members: once a group is allowlisted, anyone in it can address the bot, including people on no `allowFrom` list. Say that to the operator in those words before they allowlist a room. `dmPolicy` and `allowFrom` govern one-to-one chats only and are never consulted for a group.
100
+
101
+ A group is one conversation, not one per member: everyone in the room shares a single thread and a single session, and each turn names who spoke.
102
+
103
+ ## Setting a bot up in a channel
104
+
105
+ The outcome is that a post in an allowlisted channel reaches the agent, that the agent can post to
106
+ that channel and no other, and that comments on a post can be attributed and answered.
107
+
108
+ Three things have to be true:
109
+
110
+ - **The bot is a channel administrator, with post rights.** A channel admin adds it and grants
111
+ "Post Messages". The install cannot do this and does not try. Without the post right the bot still
112
+ reads posts but every send fails, which from the agent's side is indistinguishable from a channel
113
+ nobody reads.
114
+ - **The channel's chat id is on the entry.** Set `channelPolicy: 'allowlist'` and put the numeric
115
+ chat id in `allowChannels`. A channel id is negative and long, e.g. `-1001234567890`. Until the id
116
+ is listed, no post from that channel reaches the agent (`op=channel-refused …
117
+ reason=not-in-allowChannels`) and no send to it leaves the install.
118
+ - **For comments, the channel has a linked discussion group,** and that group is allowlisted too
119
+ (`groupPolicy`, `allowGroups`). Telegram builds comment threads by auto-forwarding each post into
120
+ the linked group; without the link there is nothing to comment on and nothing to answer in.
121
+
122
+ The list gates **both directions**. That is the difference from a group, and it is deliberate: a
123
+ channel post reaches every subscriber and cannot be unsent, so a send to a channel outside
124
+ `allowChannels` is refused before it reaches Telegram, and the refusal names both list fields.
125
+
126
+ Say this to the operator in these words before they allowlist a channel: the agent will be able to
127
+ post to it, and a post cannot be taken back.
60
128
 
61
- On success the tool has, in this order: verified the token, derived the bot id, set the webhook with a generated secret (written to `~/.<brand>/telegram-secrets/<botId>`), probed Telegram and confirmed no delivery error since the registration, and only then persisted the entry into `account.json`'s `telegram.bots` array. It logs `op=webhook-register admitted=true` + `op=webhook-verify reachable=true` + `op=token-write`. It replaces only the entry with this bot's id, so the account's other bots are untouched. If it returns an error, read it back to the operator verbatim — the common ones are a wrong path (`admitted=false`), a webhook Telegram cannot reach (`op=webhook-verify reachable=false`), a public bot with no or an inactive `agent` (`op=token-write-rejected reason=no-agent|agent-inactive`), or a token write blocked outside the brand install.
129
+ A channel post has no author. Telegram sends no sender for it, so the turn names the channel by its
130
+ title. A comment does have an author, unless the person commented anonymously, in which case the
131
+ turn names the group they commented as.
62
132
 
63
133
  ### Step 5 — Confirm
64
134
 
65
- Tell the operator the bot is connected, which role it has, and that messaging the bot now reaches the agent and a reply returns. For a public bot, name the agent that will respond. If the account holds other bots, say that this one is separate from them: its own people, its own agent, its own conversations.
135
+ Tell the operator the bot is connected, which role it has, and that messaging the bot now reaches the agent and a reply returns. For a public bot, name the agent that will respond; for a specialist bot, name the card and say the conversation stays the same one across days. If the account holds other bots, say that this one is separate from them: its own people, its own agent, its own conversations.
66
136
 
67
137
  ## Failure modes (state these loudly, do not paper over)
68
138
 
@@ -76,6 +146,17 @@ Tell the operator the bot is connected, which role it has, and that messaging th
76
146
  - **One bot id claimed by two accounts** — inbound is refused `[telegram-inbound] op=reject reason=duplicate-bot-id`, and the standing `[telegram-audit] op=duplicate-bot-id` names it every tick. Two accounts hold the same token. Remove it from the one that should not have it; nothing picks between them.
77
147
  - **Chat id claimed by two bots** — a scheduled dispatch logs `[schedule-inject] op=telegram-destination-ambiguous … dispatched=no`. Two bots, in one account or two, list the same numeric ID in their `adminUsers`. Remove it from the one that should not have it; the dispatch refuses rather than guessing which bot the person should hear from.
78
148
  - **A secret file with no bot, or a bot with no secret file** — `[telegram-audit] op=secret-orphan botId=… side=file|entry`. Neither shows up any other way. `side=entry` means that bot cannot receive anything until it re-registers; `side=file` is left-over state from a bot that has been removed.
149
+ - **Group privacy mode off at registration** — register returns an error naming BotFather's Group Privacy setting and logs `op=group-preflight … verdict=refused`. Nothing was registered and nothing written. Turn privacy on, then register again.
150
+ - **The bot cannot be added to groups** — the same refusal, naming BotFather's "Allow Groups?" setting instead.
151
+ - **Admin bot in a group** — `[telegram-inbound] op=group-refused … reason=admin-entry-no-groups`, and no turn runs. This is not a misconfiguration to fix; the admin persona never enters a group. Use a public bot for the room.
152
+ - **Group not allowlisted** — `op=group-refused … reason=not-in-allowGroups` (the id is missing from `allowGroups`) or `reason=group-policy-disabled` (the entry has no `groupPolicy: 'allowlist'` at all). Both are silent to everyone in the room, so check the log rather than assuming the bot is broken.
153
+ - **Privacy mode turned off AFTER registration** — nothing fails and no update says so; the bot simply starts reading every message in the room. The hourly `[telegram-audit] op=group-census … privacyOff=<n>` is the only thing that reports it. `privacyOff>0` needs the BotFather setting turned back on.
154
+ - **Bot removed from a group** — every later send fails and no inbound arrives again. `op=chat-member-group … status=kicked` catches it live; if the install was down when it happened, the hourly `op=group-census … absent=<n>` is what surfaces it. Read `bots=` and `groups=` on that line before trusting `absent=0`: zero absent out of zero groups is an install with no groups, not a healthy one.
155
+ - **Admin or specialist bot in a channel** — `[telegram-inbound] op=channel-refused … reason=admin-entry-no-channels` (or `specialist-entry-no-channels`, or `unbound-entry-no-channels`), and no turn runs. Not a misconfiguration to fix; those personas never enter a channel. Use a public bot.
156
+ - **Channel not allowlisted** — `op=channel-refused … reason=not-in-allowChannels` (the id is missing from `allowChannels`) or `reason=channel-policy-disabled` (the entry has no `channelPolicy: 'allowlist'` at all). Both are silent to every subscriber, so read the log rather than assuming the bot is broken. The same two states also refuse every send, logged as `[telegram-outbound] op=channel-send … allowed=no reason=not-in-allowChannels`.
157
+ - **Agent says it cannot post to a channel or group** — the id is on neither `allowChannels` nor `allowGroups`. Both lists exist on public entries only, so an admin, specialist or unbound bot can never post to any channel or group. The refusal names the id and both fields.
158
+ - **Bot loses its post rights, or is demoted in a channel** — every later send fails one at a time and nothing announces it. The hourly `[telegram-audit] op=channel-census … admin=<n> notAdmin=<n> noPostRight=<n>` is the only thing that reports it. `noPostRight>0` means the bot is still an administrator but cannot post; `notAdmin>0` means it is no longer an administrator at all. Read `bots=` and `channels=` before trusting either zero: zero out of zero channels is an install with no channels, not a healthy one.
159
+ - **Comments arrive but answers land in the wrong place** — the reply must sit beneath the auto-forwarded root post, whose id the turn carries. `op=channel-comment-root … rootMessageId=<id>` is the record of that id; a thread with no root line is a thread whose comments point nowhere, which means the discussion group is not linked or not allowlisted.
79
160
 
80
161
  ## Language
81
162
 
@@ -12,6 +12,18 @@ The agent has **no tool to initiate a WhatsApp message to an arbitrary number.**
12
12
 
13
13
  What the agent **can** still do: reply within an existing chat. **The `reply` and `reply-document` tools are retired**; the agent no longer chooses to deliver. Its answer is the text its turn ends with, read from the session record and sent by the gateway, split into separate messages on any line that is exactly `[[next]]`. A scheduled turn delivers the same way, so a scheduled turn with nothing to report must end with no text at all. Files go through `SendUserFile`, caught by a read-only JSONL follower on the session and funnelled through `sendWhatsAppDocument`, the one send core that owns path validation, the 100 MB ceiling, the canonical log, and per-file reconciliation. Delivery stays reply-only by construction: the follower runs only for an admin session and its recipient is fixed when the session spawns, so there is no recipient the agent can name. (The removed `whatsapp-send-document` route tool and the bridge path `SendUserFile` → `file-delivery-bridge.ts` → `POST /api/whatsapp/send-document` are the legacy webchat/email bridge surface, not the native WhatsApp channel.) Replying within your chats is what WhatsApp permits; starting new chats from a linked device is what it penalises.
14
14
 
15
+ The operator-facing half of this rule now also lives in the admin identity, under its `## Channel reality` section. This page loads only with the WhatsApp skill, and on 2026-08-09 an admin turn that had not loaded it filled the gap from model priors and offered a cold send three times. The identity states which channels can start a conversation and with whom; this page stays the authority on why WhatsApp cannot. A change to either belongs in both.
16
+
17
+ ## The channel-suggestion clause
18
+
19
+ The platform arm of this door's turn wrapper — `REFRAME_INSTRUCTION` in `platform/services/whatsapp-channel/src/notification.ts`, the body of a turn the operator authored from their own handset or the scheduler — ends with a clause telling the agent that when the turn wanted something this door cannot do (a button, an in-place card, a poll or checklist, a map pin, a photo or album, an invoice, a reply in a group, an edit to a message already sent, or a message to someone not already registered) it names the missing thing, says Telegram has it, and offers to set it up. It is conditioned on the turn: when this door served the request, the agent never raises another door, which is what stops it becoming a nag without needing a per-sender counter.
20
+
21
+ It exists because Telegram's own wrapper gained a paragraph naming its surfaces and no counterpart was possible here, so on the weaker door the agent answered in prose and never said a better door existed.
22
+
23
+ **WhatsApp-only, and it offers no counterweight.** A public visitor's turn takes the account arm and never reads this constant. The two twins' tests assert the clause's absence, so copying it across fails there. Three counterweights were drafted and each was struck on evidence: there is no outbound reach on this door at all and the paired number is a dedicated line no contact already holds; Telegram runs the same whisper wrapper, so the voice-note transcript is not this door's alone; and both doors gate inbound on the same `dmPolicy`. A clause that invents an advantage here is the defect it exists to close, and its test asserts all three are absent.
24
+
25
+ **How to see it.** The `[reframe] op=applied` line carries `arm=<platform|account|webchat>` and `suggestClause=<bool>`, both read back off the composed body rather than off the branch the composer meant to take. `arm=platform suggestClause=false` means the constant shipped without the clause; `arm=account suggestClause=true`, or any `suggestClause=true` on a webchat line, is a leak. Whether it ever converts anyone has no event of its own, so the hourly `[channel-suggest-census]` counts the state instead: `accountsWaOnly` flat over weeks while `waOperatorTurns` climbs is the signal. It is a proxy and never proof of causation — an operator who reads the clause and decides against Telegram is a correct outcome that moves the number not at all.
26
+
15
27
  ## Per-account observe socket (account manager)
16
28
 
17
29
  Each sub-account can pair its own WhatsApp number as a linked device, separate from the house socket. This is intended for an account manager's phone: the agent reads that WhatsApp, but the phone's inbound is never treated as instructions to the agent.
@@ -43,15 +43,46 @@ export interface ReconcileDeps {
43
43
  * account has settings reports hooks-missing=0 and reads as fenced.
44
44
  *
45
45
  * The matcher is compared for equality, which is the shape
46
- * provision-account-dir.sh writes for all five. A settings file that reaches the
47
- * same effect another way — a matcher-less catch-all entry, or a regex
48
- * alternation — reads as missing here. That is intended: what this audits is
49
- * whether the account carries the provisioned fence, and drift from the template
50
- * is worth a line even when it happens to be equivalent.
46
+ * provision-account-dir.sh writes for the five tool rows. A settings file that
47
+ * reaches the same effect another way — a matcher-less catch-all entry, or a
48
+ * regex alternation — reads as missing here. That is intended: what this audits
49
+ * is whether the account carries the provisioned fence, and drift from the
50
+ * template is worth a line even when it happens to be equivalent.
51
+ *
52
+ * A row with a null matcher inverts that test to "no matcher key at all", which
53
+ * is the shape account-settings.json writes for every UserPromptSubmit hook. The
54
+ * rule is the same in both directions: match the template exactly.
51
55
  */
52
56
  export declare function hookRegistration(accountDir: string): {
53
57
  missing: string[];
54
58
  } | null;
59
+ /**
60
+ * Per-account count of the entity folders and their child folders.
61
+ *
62
+ * The archive exception widened the guard's depth rule, and a rule that is too
63
+ * wide produces NO event: a successful write emits nothing, so an entity folder
64
+ * quietly growing a second subtree on some route is invisible. `stray` above zero
65
+ * is that signature.
66
+ *
67
+ * `entities` rides the same line because `stray=0` alone cannot tell a clean
68
+ * account from a walker that read nothing: `entities=0` on an account that holds
69
+ * entity folders is the not-measuring reading, and the two are indistinguishable
70
+ * without the denominator.
71
+ *
72
+ * Directories only; files are not counted. Dot-prefixed entries are skipped at
73
+ * both levels, because SCHEMA.md's name rule exempts them at every level and the
74
+ * write guard skips them too: counting one as a stray would raise a standing
75
+ * alarm about an entry the rules permit.
76
+ *
77
+ * A bucket that does not exist, or a child that cannot be stat'd, contributes
78
+ * nothing rather than throwing: the caller already swallows per-account errors,
79
+ * and a partial count is worth more than a dropped line.
80
+ */
81
+ export declare function entitySubdirs(accountDir: string): {
82
+ entities: number;
83
+ archive: number;
84
+ stray: number;
85
+ };
55
86
  /** One reconcile pass over every account under the accounts root: one op=strays
56
87
  * line naming the unaccounted-for entries of each account that has any, then the
57
88
  * single summary line. An account is any child dir with an account.json (the
@@ -1 +1 @@
1
- {"version":3,"file":"account-dir-schema-reconcile.d.ts","sourceRoot":"","sources":["../src/account-dir-schema-reconcile.ts"],"names":[],"mappings":"AA8EA,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD;;;;;0CAKsC;IACtC,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;+DAE+D;AAC/D,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,eAAe,EAClB,WAAW,SAAI,EACf,aAAa,SAAI,EACjB,UAAU,SAAI,EACd,YAAY,SAAI,EAChB,cAAc,SAAI,GACjB,MAAM,CAIR;AAED;;8EAE8E;AAC9E,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAcpE;AA+ED;;;8EAG8E;AAC9E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAoCpE;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AAqED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CA6BjF;AAED;;;;;;;;;;;;;iCAaiC;AACjC,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CA6EtD;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;CACb;AAED;oDACoD;AACpD,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,aAAa,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3C,yBAAyB,CAiB3B"}
1
+ {"version":3,"file":"account-dir-schema-reconcile.d.ts","sourceRoot":"","sources":["../src/account-dir-schema-reconcile.ts"],"names":[],"mappings":"AA8EA,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD;;;;;0CAKsC;IACtC,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;+DAE+D;AAC/D,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,eAAe,EAClB,WAAW,SAAI,EACf,aAAa,SAAI,EACjB,UAAU,SAAI,EACd,YAAY,SAAI,EAChB,cAAc,SAAI,GACjB,MAAM,CAIR;AAED;;8EAE8E;AAC9E,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAcpE;AA+ED;;;8EAG8E;AAC9E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAoCpE;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AA8ED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAgCjF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAuCtG;AAED;;;;;;;;;;;;;iCAaiC;AACjC,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAsFtD;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;CACb;AAED;oDACoD;AACpD,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,aAAa,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3C,yBAAyB,CAiB3B"}