@rubytech/create-maxy-code 0.1.579 → 0.1.581

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 (325) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/telegram-media/dist/index.d.ts +45 -0
  3. package/payload/platform/lib/telegram-media/dist/index.d.ts.map +1 -0
  4. package/payload/platform/lib/telegram-media/dist/index.js +89 -0
  5. package/payload/platform/lib/telegram-media/dist/index.js.map +1 -0
  6. package/payload/platform/lib/telegram-media/src/__tests__/telegram-media.test.ts +104 -0
  7. package/payload/platform/lib/telegram-media/src/index.ts +102 -0
  8. package/payload/platform/lib/telegram-media/tsconfig.json +9 -0
  9. package/payload/platform/lib/telegram-media/vitest.config.ts +9 -0
  10. package/payload/platform/package.json +2 -2
  11. package/payload/platform/plugins/admin/PLUGIN.md +2 -2
  12. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +22 -0
  13. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +34 -0
  14. package/payload/platform/plugins/admin/hooks/__tests__/quote-path-write-gate.test.sh +25 -0
  15. package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +11 -4
  16. package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +2 -2
  17. package/payload/platform/plugins/admin/hooks/quote-path-write-gate.sh +6 -3
  18. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +13 -1
  19. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +16 -0
  20. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-schema-shape.test.ts +23 -0
  21. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-visit-status-write.test.ts +175 -3
  22. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-visits-scope.test.ts +101 -0
  23. package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +35 -1
  24. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visit-status.ts +73 -8
  25. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visits.ts +59 -8
  26. package/payload/platform/plugins/docs/references/telegram-guide.md +12 -0
  27. package/payload/platform/plugins/telegram/.claude-plugin/plugin.json +1 -1
  28. package/payload/platform/plugins/telegram/PLUGIN.md +27 -3
  29. package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-census.test.js +99 -1
  30. package/payload/platform/plugins/telegram/mcp/dist/__tests__/api-census.test.js.map +1 -1
  31. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.d.ts +2 -0
  32. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.d.ts.map +1 -0
  33. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js +226 -0
  34. package/payload/platform/plugins/telegram/mcp/dist/__tests__/ask-tool.test.js.map +1 -0
  35. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-ratio.test.d.ts +2 -0
  36. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-ratio.test.d.ts.map +1 -0
  37. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-ratio.test.js +75 -0
  38. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-ratio.test.js.map +1 -0
  39. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-store.test.d.ts +2 -0
  40. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-store.test.d.ts.map +1 -0
  41. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-store.test.js +152 -0
  42. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-store.test.js.map +1 -0
  43. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.d.ts +2 -0
  44. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.d.ts.map +1 -0
  45. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js +231 -0
  46. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js.map +1 -0
  47. package/payload/platform/plugins/telegram/mcp/dist/__tests__/invoice-tool.test.d.ts +2 -0
  48. package/payload/platform/plugins/telegram/mcp/dist/__tests__/invoice-tool.test.d.ts.map +1 -0
  49. package/payload/platform/plugins/telegram/mcp/dist/__tests__/invoice-tool.test.js +196 -0
  50. package/payload/platform/plugins/telegram/mcp/dist/__tests__/invoice-tool.test.js.map +1 -0
  51. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-store.test.d.ts +2 -0
  52. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-store.test.d.ts.map +1 -0
  53. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-store.test.js +93 -0
  54. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-store.test.js.map +1 -0
  55. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-tool.test.d.ts +2 -0
  56. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-tool.test.d.ts.map +1 -0
  57. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-tool.test.js +76 -0
  58. package/payload/platform/plugins/telegram/mcp/dist/__tests__/live-location-tool.test.js.map +1 -0
  59. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-fetch-tool.test.d.ts +2 -0
  60. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-fetch-tool.test.d.ts.map +1 -0
  61. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-fetch-tool.test.js +95 -0
  62. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-fetch-tool.test.js.map +1 -0
  63. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-send-tool.test.d.ts +2 -0
  64. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-send-tool.test.d.ts.map +1 -0
  65. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-send-tool.test.js +293 -0
  66. package/payload/platform/plugins/telegram/mcp/dist/__tests__/media-send-tool.test.js.map +1 -0
  67. package/payload/platform/plugins/telegram/mcp/dist/__tests__/schemas.test.d.ts +2 -0
  68. package/payload/platform/plugins/telegram/mcp/dist/__tests__/schemas.test.d.ts.map +1 -0
  69. package/payload/platform/plugins/telegram/mcp/dist/__tests__/schemas.test.js +130 -0
  70. package/payload/platform/plugins/telegram/mcp/dist/__tests__/schemas.test.js.map +1 -0
  71. package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.d.ts +2 -0
  72. package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.d.ts.map +1 -0
  73. package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.js +119 -0
  74. package/payload/platform/plugins/telegram/mcp/dist/__tests__/thread-tool.test.js.map +1 -0
  75. package/payload/platform/plugins/telegram/mcp/dist/index.js +89 -66
  76. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  77. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +15 -0
  78. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -1
  79. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +27 -10
  80. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -1
  81. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.d.ts +38 -0
  82. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.d.ts.map +1 -1
  83. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.js +106 -0
  84. package/payload/platform/plugins/telegram/mcp/dist/lib/api-census.js.map +1 -1
  85. package/payload/platform/plugins/telegram/mcp/dist/lib/card-ratio.d.ts +15 -0
  86. package/payload/platform/plugins/telegram/mcp/dist/lib/card-ratio.d.ts.map +1 -0
  87. package/payload/platform/plugins/telegram/mcp/dist/lib/card-ratio.js +78 -0
  88. package/payload/platform/plugins/telegram/mcp/dist/lib/card-ratio.js.map +1 -0
  89. package/payload/platform/plugins/telegram/mcp/dist/lib/card-store.d.ts +60 -0
  90. package/payload/platform/plugins/telegram/mcp/dist/lib/card-store.d.ts.map +1 -0
  91. package/payload/platform/plugins/telegram/mcp/dist/lib/card-store.js +141 -0
  92. package/payload/platform/plugins/telegram/mcp/dist/lib/card-store.js.map +1 -0
  93. package/payload/platform/plugins/telegram/mcp/dist/lib/live-location-store.d.ts +44 -0
  94. package/payload/platform/plugins/telegram/mcp/dist/lib/live-location-store.d.ts.map +1 -0
  95. package/payload/platform/plugins/telegram/mcp/dist/lib/live-location-store.js +88 -0
  96. package/payload/platform/plugins/telegram/mcp/dist/lib/live-location-store.js.map +1 -0
  97. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.d.ts +73 -0
  98. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.d.ts.map +1 -0
  99. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.js +270 -0
  100. package/payload/platform/plugins/telegram/mcp/dist/tools/ask.js.map +1 -0
  101. package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts +34 -0
  102. package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts.map +1 -0
  103. package/payload/platform/plugins/telegram/mcp/dist/tools/card.js +140 -0
  104. package/payload/platform/plugins/telegram/mcp/dist/tools/card.js.map +1 -0
  105. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.d.ts +70 -0
  106. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.d.ts.map +1 -0
  107. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.js +232 -0
  108. package/payload/platform/plugins/telegram/mcp/dist/tools/invoice.js.map +1 -0
  109. package/payload/platform/plugins/telegram/mcp/dist/tools/live-location.d.ts +23 -0
  110. package/payload/platform/plugins/telegram/mcp/dist/tools/live-location.d.ts.map +1 -0
  111. package/payload/platform/plugins/telegram/mcp/dist/tools/live-location.js +43 -0
  112. package/payload/platform/plugins/telegram/mcp/dist/tools/live-location.js.map +1 -0
  113. package/payload/platform/plugins/telegram/mcp/dist/tools/media-fetch.d.ts +42 -0
  114. package/payload/platform/plugins/telegram/mcp/dist/tools/media-fetch.d.ts.map +1 -0
  115. package/payload/platform/plugins/telegram/mcp/dist/tools/media-fetch.js +92 -0
  116. package/payload/platform/plugins/telegram/mcp/dist/tools/media-fetch.js.map +1 -0
  117. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.d.ts +76 -0
  118. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.d.ts.map +1 -0
  119. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.js +288 -0
  120. package/payload/platform/plugins/telegram/mcp/dist/tools/media-send.js.map +1 -0
  121. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts +250 -0
  122. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.d.ts.map +1 -0
  123. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js +400 -0
  124. package/payload/platform/plugins/telegram/mcp/dist/tools/schemas.js.map +1 -0
  125. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.d.ts +38 -0
  126. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.d.ts.map +1 -0
  127. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.js +120 -0
  128. package/payload/platform/plugins/telegram/mcp/dist/tools/thread.js.map +1 -0
  129. package/payload/platform/plugins/telegram/mcp/vitest.config.ts +14 -0
  130. package/payload/platform/plugins/telegram/skills/build/SKILL.md +171 -21
  131. package/payload/platform/scripts/__tests__/hook-matcher-dispatch.test.sh +163 -0
  132. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  133. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +7 -1
  134. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  135. package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
  136. package/payload/platform/services/telegram-channel/dist/instructions.js +15 -1
  137. package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
  138. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  139. package/payload/server/{adminuser-self-heal-Y4U3UNKF.js → adminuser-self-heal-ZHFNDKJK.js} +2 -10
  140. package/payload/server/{chunk-637C2FGE.js → chunk-BFRB2U75.js} +3278 -3381
  141. package/payload/server/{chunk-6DQCFP2E.js → chunk-BTXRBXMU.js} +3785 -4090
  142. package/payload/server/{chunk-KVR2FT6O.js → chunk-HYQNUVGO.js} +1 -12
  143. package/payload/server/{chunk-PGGGWUBM.js → chunk-SKYZG6OT.js} +224 -372
  144. package/payload/server/{manager-R3XH3BNM.js → manager-CTVTF4YB.js} +3 -3
  145. package/payload/server/maxy-edge.js +4 -27
  146. package/payload/server/public/activity.html +6 -6
  147. package/payload/server/public/agents.html +5 -5
  148. package/payload/server/public/assets/{AdminLoginScreens-Bus-Y-rG.js → AdminLoginScreens-B1lu4-_F.js} +1 -1
  149. package/payload/server/public/assets/AdminLoginScreens-B1lu4-_F.js.br +0 -0
  150. package/payload/server/public/assets/AdminLoginScreens-B1lu4-_F.js.gz +0 -0
  151. package/payload/server/public/assets/{AdminShell-Bsm7q3CW.js → AdminShell-BMslfZxN.js} +1 -1
  152. package/payload/server/public/assets/AdminShell-BMslfZxN.js.br +0 -0
  153. package/payload/server/public/assets/AdminShell-BMslfZxN.js.gz +0 -0
  154. package/payload/server/public/assets/{activity-BWqrCyYM.js → activity-kQ3w70LJ.js} +1 -1
  155. package/payload/server/public/assets/activity-kQ3w70LJ.js.br +0 -0
  156. package/payload/server/public/assets/activity-kQ3w70LJ.js.gz +0 -0
  157. package/payload/server/public/assets/{admin-zly7Y6EZ.js → admin-CkASgYA7.js} +1 -1
  158. package/payload/server/public/assets/admin-CkASgYA7.js.br +0 -0
  159. package/payload/server/public/assets/admin-CkASgYA7.js.gz +0 -0
  160. package/payload/server/public/assets/{agents-BsxGD1V1.js → agents-Cn_bZgnD.js} +1 -1
  161. package/payload/server/public/assets/agents-Cn_bZgnD.js.br +0 -0
  162. package/payload/server/public/assets/agents-Cn_bZgnD.js.gz +0 -0
  163. package/payload/server/public/assets/{browser-CRLxTaw2.js → browser-BE-GDk5-.js} +1 -1
  164. package/payload/server/public/assets/browser-BE-GDk5-.js.br +0 -0
  165. package/payload/server/public/assets/browser-BE-GDk5-.js.gz +0 -0
  166. package/payload/server/public/assets/{calendar-Bmp6qI_P.js → calendar-Di7BEHHN.js} +1 -1
  167. package/payload/server/public/assets/calendar-Di7BEHHN.js.br +0 -0
  168. package/payload/server/public/assets/calendar-Di7BEHHN.js.gz +0 -0
  169. package/payload/server/public/assets/chat-CKyMT5Ai.js +1 -0
  170. package/payload/server/public/assets/chat-CKyMT5Ai.js.br +1 -0
  171. package/payload/server/public/assets/chat-CKyMT5Ai.js.gz +0 -0
  172. package/payload/server/public/assets/chevron-left-Id9VAZAz.js +1 -0
  173. package/payload/server/public/assets/chevron-left-Id9VAZAz.js.br +0 -0
  174. package/payload/server/public/assets/clock-DKpWWJbJ.js +1 -0
  175. package/payload/server/public/assets/clock-DKpWWJbJ.js.br +0 -0
  176. package/payload/server/public/assets/{copy-Bcjpxqzn.js → copy-nkxspu2J.js} +1 -1
  177. package/payload/server/public/assets/copy-nkxspu2J.js.br +0 -0
  178. package/payload/server/public/assets/copy-nkxspu2J.js.gz +0 -0
  179. package/payload/server/public/assets/data-1c33cAHp.js +1 -0
  180. package/payload/server/public/assets/data-1c33cAHp.js.br +2 -0
  181. package/payload/server/public/assets/data-1c33cAHp.js.gz +0 -0
  182. package/payload/server/public/assets/{field-ChKB2l_d.js → field-2rIXxGMt.js} +1 -1
  183. package/payload/server/public/assets/field-2rIXxGMt.js.br +0 -0
  184. package/payload/server/public/assets/field-2rIXxGMt.js.gz +0 -0
  185. package/payload/server/public/assets/{file-text-COZcf7mU.js → file-text-CdSqrscg.js} +1 -1
  186. package/payload/server/public/assets/file-text-CdSqrscg.js.br +0 -0
  187. package/payload/server/public/assets/file-text-CdSqrscg.js.gz +0 -0
  188. package/payload/server/public/assets/{graph-nnV47iqM.js → graph-BfBHHXaC.js} +1 -1
  189. package/payload/server/public/assets/graph-BfBHHXaC.js.br +0 -0
  190. package/payload/server/public/assets/graph-BfBHHXaC.js.gz +0 -0
  191. package/payload/server/public/assets/{graph-labels-x-1MT-3c.js → graph-labels-CHW2aBke.js} +1 -1
  192. package/payload/server/public/assets/graph-labels-CHW2aBke.js.br +0 -0
  193. package/payload/server/public/assets/graph-labels-CHW2aBke.js.gz +0 -0
  194. package/payload/server/public/assets/jsx-runtime-D43jgaWP.css +1 -0
  195. package/payload/server/public/assets/jsx-runtime-D43jgaWP.css.br +0 -0
  196. package/payload/server/public/assets/jsx-runtime-D43jgaWP.css.gz +0 -0
  197. package/payload/server/public/assets/{operator-BAO0-mjU.js → operator-DRn9LITC.js} +1 -1
  198. package/payload/server/public/assets/operator-DRn9LITC.js.br +0 -0
  199. package/payload/server/public/assets/operator-DRn9LITC.js.gz +0 -0
  200. package/payload/server/public/assets/page-BwqQsoU8.js +1 -0
  201. package/payload/server/public/assets/page-BwqQsoU8.js.br +0 -0
  202. package/payload/server/public/assets/page-BwqQsoU8.js.gz +0 -0
  203. package/payload/server/public/assets/{page-B-F08pod.js → page-D_9mPS6W.js} +1 -1
  204. package/payload/server/public/assets/page-D_9mPS6W.js.br +0 -0
  205. package/payload/server/public/assets/page-D_9mPS6W.js.gz +0 -0
  206. package/payload/server/public/assets/play-7LTxCuLX.js +1 -0
  207. package/payload/server/public/assets/play-7LTxCuLX.js.br +0 -0
  208. package/payload/server/public/assets/play-7LTxCuLX.js.gz +0 -0
  209. package/payload/server/public/assets/{public-_HJsUohA.js → public-CrjZYpdW.js} +1 -1
  210. package/payload/server/public/assets/public-CrjZYpdW.js.br +0 -0
  211. package/payload/server/public/assets/public-CrjZYpdW.js.gz +0 -0
  212. package/payload/server/public/assets/{rotate-ccw-DJeAnYLQ.js → rotate-ccw-J9f-GWjm.js} +1 -1
  213. package/payload/server/public/assets/rotate-ccw-J9f-GWjm.js.br +0 -0
  214. package/payload/server/public/assets/rotate-ccw-J9f-GWjm.js.gz +0 -0
  215. package/payload/server/public/assets/{routines-CoIVXRCB.js → routines-C1AB-3FR.js} +1 -1
  216. package/payload/server/public/assets/routines-C1AB-3FR.js.br +0 -0
  217. package/payload/server/public/assets/routines-C1AB-3FR.js.gz +0 -0
  218. package/payload/server/public/assets/{skills-BjHt5lDG.js → skills-C4EfNKEx.js} +1 -1
  219. package/payload/server/public/assets/skills-C4EfNKEx.js.br +0 -0
  220. package/payload/server/public/assets/skills-C4EfNKEx.js.gz +0 -0
  221. package/payload/server/public/assets/{tasks-iUFfeA9_.js → tasks-DszD3aZl.js} +1 -1
  222. package/payload/server/public/assets/tasks-DszD3aZl.js.br +0 -0
  223. package/payload/server/public/assets/tasks-DszD3aZl.js.gz +0 -0
  224. package/payload/server/public/assets/{triangle-alert-Dwa986Gg.js → triangle-alert-B5WAyAkC.js} +1 -1
  225. package/payload/server/public/assets/triangle-alert-B5WAyAkC.js.br +4 -0
  226. package/payload/server/public/assets/triangle-alert-B5WAyAkC.js.gz +0 -0
  227. package/payload/server/public/assets/{useCopyFeedback-B1Jp6CsE.js → useCopyFeedback-B2nuNNJw.js} +1 -1
  228. package/payload/server/public/assets/useCopyFeedback-B2nuNNJw.js.br +0 -0
  229. package/payload/server/public/assets/useCopyFeedback-B2nuNNJw.js.gz +0 -0
  230. package/payload/server/public/assets/{useMediaQuery-CVZYjRf6.js → useMediaQuery-DUPJPHQt.js} +1 -1
  231. package/payload/server/public/assets/useMediaQuery-DUPJPHQt.js.br +0 -0
  232. package/payload/server/public/assets/useMediaQuery-DUPJPHQt.js.gz +0 -0
  233. package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js +2 -0
  234. package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js.br +0 -0
  235. package/payload/server/public/assets/useVoiceRecorder-CCK60d2i.js.gz +0 -0
  236. package/payload/server/public/assets/{wrench-BD7xwbV1.js → wrench-DZJZm17j.js} +1 -1
  237. package/payload/server/public/assets/wrench-DZJZm17j.js.br +0 -0
  238. package/payload/server/public/assets/wrench-DZJZm17j.js.gz +0 -0
  239. package/payload/server/public/browser.html +5 -5
  240. package/payload/server/public/calendar.html +8 -8
  241. package/payload/server/public/chat.html +14 -14
  242. package/payload/server/public/data.html +12 -12
  243. package/payload/server/public/field.html +3 -3
  244. package/payload/server/public/graph.html +10 -10
  245. package/payload/server/public/index.html +14 -14
  246. package/payload/server/public/operator.html +15 -15
  247. package/payload/server/public/public.html +14 -14
  248. package/payload/server/public/routines.html +8 -8
  249. package/payload/server/public/skills.html +6 -6
  250. package/payload/server/public/tasks.html +7 -7
  251. package/payload/server/server.js +10561 -10491
  252. package/payload/server/{src-IJCLNFYU.js → src-MM64CYYZ.js} +1 -1
  253. package/payload/server/{userprofile-reconcile-PUA657YX.js → userprofile-reconcile-TL4JKBPG.js} +1 -8
  254. package/payload/server/public/assets/AdminLoginScreens-Bus-Y-rG.js.br +0 -0
  255. package/payload/server/public/assets/AdminLoginScreens-Bus-Y-rG.js.gz +0 -0
  256. package/payload/server/public/assets/AdminShell-Bsm7q3CW.js.br +0 -0
  257. package/payload/server/public/assets/AdminShell-Bsm7q3CW.js.gz +0 -0
  258. package/payload/server/public/assets/activity-BWqrCyYM.js.br +0 -0
  259. package/payload/server/public/assets/activity-BWqrCyYM.js.gz +0 -0
  260. package/payload/server/public/assets/admin-zly7Y6EZ.js.br +0 -0
  261. package/payload/server/public/assets/admin-zly7Y6EZ.js.gz +0 -0
  262. package/payload/server/public/assets/agents-BsxGD1V1.js.br +0 -0
  263. package/payload/server/public/assets/agents-BsxGD1V1.js.gz +0 -0
  264. package/payload/server/public/assets/browser-CRLxTaw2.js.br +0 -0
  265. package/payload/server/public/assets/browser-CRLxTaw2.js.gz +0 -0
  266. package/payload/server/public/assets/calendar-Bmp6qI_P.js.br +0 -0
  267. package/payload/server/public/assets/calendar-Bmp6qI_P.js.gz +0 -0
  268. package/payload/server/public/assets/chat-ChObDKHy.js +0 -1
  269. package/payload/server/public/assets/chat-ChObDKHy.js.br +0 -0
  270. package/payload/server/public/assets/chat-ChObDKHy.js.gz +0 -0
  271. package/payload/server/public/assets/chevron-left-D2l4jMcd.js +0 -1
  272. package/payload/server/public/assets/chevron-left-D2l4jMcd.js.br +0 -0
  273. package/payload/server/public/assets/clock-CMdfsroW.js +0 -1
  274. package/payload/server/public/assets/clock-CMdfsroW.js.br +0 -0
  275. package/payload/server/public/assets/clock-CMdfsroW.js.gz +0 -0
  276. package/payload/server/public/assets/copy-Bcjpxqzn.js.br +0 -0
  277. package/payload/server/public/assets/copy-Bcjpxqzn.js.gz +0 -0
  278. package/payload/server/public/assets/data-CFB5Lgw-.js +0 -1
  279. package/payload/server/public/assets/data-CFB5Lgw-.js.br +0 -0
  280. package/payload/server/public/assets/data-CFB5Lgw-.js.gz +0 -0
  281. package/payload/server/public/assets/field-ChKB2l_d.js.br +0 -0
  282. package/payload/server/public/assets/field-ChKB2l_d.js.gz +0 -0
  283. package/payload/server/public/assets/file-text-COZcf7mU.js.br +0 -0
  284. package/payload/server/public/assets/file-text-COZcf7mU.js.gz +0 -0
  285. package/payload/server/public/assets/graph-labels-x-1MT-3c.js.br +0 -0
  286. package/payload/server/public/assets/graph-labels-x-1MT-3c.js.gz +0 -0
  287. package/payload/server/public/assets/graph-nnV47iqM.js.br +0 -0
  288. package/payload/server/public/assets/graph-nnV47iqM.js.gz +0 -0
  289. package/payload/server/public/assets/jsx-runtime-CeNZasfC.css +0 -1
  290. package/payload/server/public/assets/jsx-runtime-CeNZasfC.css.br +0 -0
  291. package/payload/server/public/assets/jsx-runtime-CeNZasfC.css.gz +0 -0
  292. package/payload/server/public/assets/operator-BAO0-mjU.js.br +0 -0
  293. package/payload/server/public/assets/operator-BAO0-mjU.js.gz +0 -0
  294. package/payload/server/public/assets/page-B-F08pod.js.br +0 -0
  295. package/payload/server/public/assets/page-B-F08pod.js.gz +0 -0
  296. package/payload/server/public/assets/page-BMOCy2aD.js +0 -1
  297. package/payload/server/public/assets/page-BMOCy2aD.js.br +0 -0
  298. package/payload/server/public/assets/page-BMOCy2aD.js.gz +0 -0
  299. package/payload/server/public/assets/play-DFtlk8Zs.js +0 -1
  300. package/payload/server/public/assets/play-DFtlk8Zs.js.br +0 -0
  301. package/payload/server/public/assets/play-DFtlk8Zs.js.gz +0 -0
  302. package/payload/server/public/assets/public-_HJsUohA.js.br +0 -0
  303. package/payload/server/public/assets/public-_HJsUohA.js.gz +0 -0
  304. package/payload/server/public/assets/rotate-ccw-DJeAnYLQ.js.br +0 -0
  305. package/payload/server/public/assets/rotate-ccw-DJeAnYLQ.js.gz +0 -0
  306. package/payload/server/public/assets/routines-CoIVXRCB.js.br +0 -0
  307. package/payload/server/public/assets/routines-CoIVXRCB.js.gz +0 -0
  308. package/payload/server/public/assets/skills-BjHt5lDG.js.br +0 -0
  309. package/payload/server/public/assets/skills-BjHt5lDG.js.gz +0 -0
  310. package/payload/server/public/assets/tasks-iUFfeA9_.js.br +0 -0
  311. package/payload/server/public/assets/tasks-iUFfeA9_.js.gz +0 -0
  312. package/payload/server/public/assets/triangle-alert-Dwa986Gg.js.br +0 -0
  313. package/payload/server/public/assets/triangle-alert-Dwa986Gg.js.gz +0 -0
  314. package/payload/server/public/assets/useCopyFeedback-B1Jp6CsE.js.br +0 -0
  315. package/payload/server/public/assets/useCopyFeedback-B1Jp6CsE.js.gz +0 -0
  316. package/payload/server/public/assets/useMediaQuery-CVZYjRf6.js.br +0 -0
  317. package/payload/server/public/assets/useMediaQuery-CVZYjRf6.js.gz +0 -0
  318. package/payload/server/public/assets/useVoiceRecorder-D5b4r4z0.js +0 -2
  319. package/payload/server/public/assets/useVoiceRecorder-D5b4r4z0.js.br +0 -0
  320. package/payload/server/public/assets/useVoiceRecorder-D5b4r4z0.js.gz +0 -0
  321. package/payload/server/public/assets/wrench-BD7xwbV1.js.br +0 -0
  322. package/payload/server/public/assets/wrench-BD7xwbV1.js.gz +0 -0
  323. /package/payload/server/public/assets/{jsx-runtime-CjJ246F7.js → jsx-runtime-Cjug_Cyb.js} +0 -0
  324. /package/payload/server/public/assets/{jsx-runtime-CjJ246F7.js.br → jsx-runtime-Cjug_Cyb.js.br} +0 -0
  325. /package/payload/server/public/assets/{jsx-runtime-CjJ246F7.js.gz → jsx-runtime-Cjug_Cyb.js.gz} +0 -0
@@ -0,0 +1,78 @@
1
+ import { readdirSync, readFileSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { MAX_BYTES_PER_FILE } from "./api-census.js";
4
+ /** The numerator: one card that carried at least one button. Task 2604 added the
5
+ * `buttons=` field; a line from an older build has none, matches nothing here and
6
+ * is counted as neither, which is right — it cannot say whether it had buttons.
7
+ *
8
+ * EVERY outcome counts, `none` included. card.ts logs `op=card` unconditionally
9
+ * after its outcome branch, so a card Telegram refused is in this count. That is
10
+ * deliberate: this census measures whether the AGENT reached for the affordance,
11
+ * which is what the instruction clause governs, and a 400 from Telegram is not
12
+ * the agent declining to offer buttons. It does mean the numerator is offers
13
+ * made, not keyboards seen — read `[telegram-tools] op=result … ok=false` beside
14
+ * it if that distinction matters for a given question. */
15
+ const CARD_LINE = /^\[telegram-tools\] op=card .*\bbuttons=(\d+)/;
16
+ /** The denominator: one composed turn on the ADMIN Telegram door. The channel
17
+ * service writes this per turn (telegram-channel/src/server.ts), to its own
18
+ * stderr, which lands in mcp-telegram-channel-<sessionId>.log — an mcp-*.log, so
19
+ * the same walk finds it. `[telegram:reframe] op=compose` is per-turn too but is
20
+ * emitted by the GATEWAY into server.log, which rotates on size and is skipped by
21
+ * MAX_BYTES_PER_FILE, so it would report a permanent zero denominator.
22
+ *
23
+ * role=admin only: the clause this census measures lives in
24
+ * ADMIN_REFRAME_INSTRUCTION and a public visitor's turn never carries it. */
25
+ const TURN_LINE = /^\[telegram:inbound\] op=delivered .*\brole=admin\b/;
26
+ /** Pure, so the arithmetic is testable without a log directory. */
27
+ export function tallyCardRatio(lines) {
28
+ let cardsWithButtons = 0;
29
+ let turns = 0;
30
+ for (const line of lines) {
31
+ const card = CARD_LINE.exec(line);
32
+ if (card) {
33
+ if (Number(card[1]) > 0)
34
+ cardsWithButtons += 1;
35
+ continue;
36
+ }
37
+ if (TURN_LINE.test(line))
38
+ turns += 1;
39
+ }
40
+ return { cardsWithButtons, turns };
41
+ }
42
+ /** Both counts from one walk of LOG_DIR over mcp-*.log — the filter and size
43
+ * guard passthroughCensusLine already uses. Rotated `.gz` files are skipped:
44
+ * read as text they yield binary noise, not lines.
45
+ *
46
+ * Never throws. A boot throw empties the plugin registry (CLAUDE.md), so any
47
+ * failure reports zeros, and `turns` on the census line is what lets the
48
+ * operator tell those zeros from a healthy quiet window. */
49
+ export function cardRatioFromLogs(logDir) {
50
+ let cardsWithButtons = 0;
51
+ let turns = 0;
52
+ try {
53
+ if (logDir) {
54
+ for (const name of readdirSync(logDir)) {
55
+ if (!name.startsWith("mcp-") || !name.endsWith(".log"))
56
+ continue;
57
+ const path = join(logDir, name);
58
+ let text;
59
+ try {
60
+ if (statSync(path).size > MAX_BYTES_PER_FILE)
61
+ continue;
62
+ text = readFileSync(path, "utf-8");
63
+ }
64
+ catch {
65
+ continue;
66
+ }
67
+ const t = tallyCardRatio(text.split("\n"));
68
+ cardsWithButtons += t.cardsWithButtons;
69
+ turns += t.turns;
70
+ }
71
+ }
72
+ }
73
+ catch {
74
+ // Zeros, deliberately. See the doc comment.
75
+ }
76
+ return { cardsWithButtons, turns };
77
+ }
78
+ //# sourceMappingURL=card-ratio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-ratio.js","sourceRoot":"","sources":["../../src/lib/card-ratio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;2DAU2D;AAC3D,MAAM,SAAS,GAAG,+CAA+C,CAAC;AAElE;;;;;;;;8EAQ8E;AAC9E,MAAM,SAAS,GAAG,qDAAqD,CAAC;AAOxE,mEAAmE;AACnE,MAAM,UAAU,cAAc,CAAC,KAAuB;IACpD,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAAE,gBAAgB,IAAI,CAAC,CAAC;YAC/C,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;6DAM6D;AAC7D,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC;QACH,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,SAAS;gBACjE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAChC,IAAI,IAAY,CAAC;gBACjB,IAAI,CAAC;oBACH,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,kBAAkB;wBAAE,SAAS;oBACvD,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;gBACD,MAAM,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC3C,gBAAgB,IAAI,CAAC,CAAC,gBAAgB,CAAC;gBACvC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,60 @@
1
+ /** Scoped by bot AND chat, not by the caller's key alone: the same "job-4102"
2
+ * key in two chats is two cards, and collapsing them would edit a stranger's
3
+ * message. */
4
+ export declare function cardKey(botId: string, chatId: string | number, key: string): string;
5
+ /** A card untouched for this long stops being edited in place: the next keyed
6
+ * call posts fresh. Operator decision 2026-08-08 (Task 2595). No Telegram-imposed
7
+ * edit window is claimed here — none was confirmed. This is our own ceiling, and
8
+ * it is what bounds the file: without it every key ever used is kept for ever. */
9
+ export declare const CARD_TTL_MS: number;
10
+ /** The stored message id for this key, or null. Null once the entry has gone
11
+ * CARD_TTL_MS untouched: the caller then posts fresh, which is how a key whose
12
+ * message is gone recovers without matching on Telegram's error prose. */
13
+ export declare function readCardId(platformRoot: string, accountId: string, k: string, now?: number): number | null;
14
+ /** Record the message id this key now names, and drop every entry that has gone
15
+ * CARD_TTL_MS untouched. Compaction rides the write because the write already
16
+ * rewrites the whole file; a separate prune pass would be a second thing to
17
+ * schedule. Every surviving key keeps its own id and timestamp, the same promise
18
+ * persistTelegramBot makes for bot entries. */
19
+ export declare function writeCardId(platformRoot: string, accountId: string, k: string, messageId: number, now?: number): void;
20
+ export declare const CARD_CENSUS_TAG = "[telegram-card-census]";
21
+ /** The standing check for this store, emitted once at MCP boot.
22
+ *
23
+ * It answers what nothing else can: is telegram-cards.json growing? Every entry
24
+ * is one key that was used and kept, and until this line existed that growth was
25
+ * invisible — Task 2588 gave the media store a census and gave this one none.
26
+ *
27
+ * It reports the count it read back from disk, never that a prune ran. A prune
28
+ * that pruned nothing and a prune that worked print the same thing if the line
29
+ * reports the prune rather than the state.
30
+ *
31
+ * `keys` is every entry ON DISK, expired ones included. Compaction only rides a
32
+ * write, so an account that stops posting cards keeps its file at whatever size
33
+ * it reached while every entry in it reads as absent through readCardId. That is
34
+ * the right number for the question this line asks — is the file growing — but
35
+ * it is not a count of live cards. `keys=0` with `bytes>0` is the third state: a
36
+ * file that exists and parsed to nothing.
37
+ *
38
+ * `keys` rising across boots while jobs close is the leak. Never throws: a boot
39
+ * throw empties the plugin registry (CLAUDE.md), so any failure reports zeros.
40
+ *
41
+ * Task 2604 added `cardsWithButtons` and `turns`, which come from LOG_DIR rather
42
+ * than from this store: buttons are not stored here and an unkeyed one-off card
43
+ * has no entry at all, so neither is answerable from telegram-cards.json. The
44
+ * pair is the signal for the affordances clause in the Telegram turn
45
+ * instruction — not offering a button is a non-event and logs nothing of its
46
+ * own, so only a ratio can show the clause taking or over-firing. `turns` is on
47
+ * the line because `cardsWithButtons=0` alone cannot be told from a counter that
48
+ * is not running. No threshold is asserted here; the numbers are what the
49
+ * operator judges the wording against.
50
+ *
51
+ * THE TWO HALVES OF THIS LINE ARE SCOPED DIFFERENTLY, and reading them as one
52
+ * scope is the mistake to avoid. `keys` and `bytes` are ONE ACCOUNT's: they read
53
+ * telegram-cards.json under that account's own directory. `cardsWithButtons` and
54
+ * `turns` are INSTALL-WIDE: LOG_DIR is `~/.<brand>/logs/`, which every account in
55
+ * the brand shares, and no line in it carries an accountId to filter on. So on a
56
+ * multi-account install the ratio is the whole brand's and the store counts are
57
+ * one account's. Per-account attribution would need an accountId on the
58
+ * `op=card` and `op=delivered` lines, which neither carries today. */
59
+ export declare function cardCensusLine(platformRoot: string, accountId: string | undefined, logDir?: string): string;
60
+ //# sourceMappingURL=card-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-store.d.ts","sourceRoot":"","sources":["../../src/lib/card-store.ts"],"names":[],"mappings":"AASA;;eAEe;AACf,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnF;AAOD;;;mFAGmF;AACnF,eAAO,MAAM,WAAW,QAA0B,CAAC;AAwCnD;;2EAE2E;AAC3E,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,CAAC,EAAE,MAAM,EACT,GAAG,GAAE,MAAmB,GACvB,MAAM,GAAG,IAAI,CAMf;AAED;;;;gDAIgD;AAChD,wBAAgB,WAAW,CACzB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,CAAC,EAAE,MAAM,EACT,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAmB,GACvB,IAAI,CASN;AAED,eAAO,MAAM,eAAe,2BAA2B,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uEAqCuE;AACvE,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAgBR"}
@@ -0,0 +1,141 @@
1
+ import { join } from "node:path";
2
+ import { existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
3
+ import { resolveAccountDir } from "./account-write.js";
4
+ import { cardRatioFromLogs } from "./card-ratio.js";
5
+ /** Runtime state, so a file of its own rather than a key inside account.json,
6
+ * which holds configuration. Same directory, same brand containment. */
7
+ const FILE = "telegram-cards.json";
8
+ /** Scoped by bot AND chat, not by the caller's key alone: the same "job-4102"
9
+ * key in two chats is two cards, and collapsing them would edit a stranger's
10
+ * message. */
11
+ export function cardKey(botId, chatId, key) {
12
+ return `${botId}:${chatId}:${key}`;
13
+ }
14
+ function storePath(platformRoot, accountId) {
15
+ const resolved = resolveAccountDir(platformRoot, accountId);
16
+ return resolved.ok ? join(resolved.dir, FILE) : null;
17
+ }
18
+ /** A card untouched for this long stops being edited in place: the next keyed
19
+ * call posts fresh. Operator decision 2026-08-08 (Task 2595). No Telegram-imposed
20
+ * edit window is claimed here — none was confirmed. This is our own ceiling, and
21
+ * it is what bounds the file: without it every key ever used is kept for ever. */
22
+ export const CARD_TTL_MS = 7 * 24 * 60 * 60 * 1000;
23
+ function isEntry(v) {
24
+ if (!v || typeof v !== "object" || Array.isArray(v))
25
+ return false;
26
+ const e = v;
27
+ return (typeof e.id === "number" &&
28
+ Number.isFinite(e.id) &&
29
+ typeof e.at === "number" &&
30
+ Number.isFinite(e.at));
31
+ }
32
+ function readAll(path) {
33
+ if (!existsSync(path))
34
+ return {};
35
+ try {
36
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
37
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
38
+ return {};
39
+ const out = {};
40
+ for (const [k, v] of Object.entries(parsed)) {
41
+ if (isEntry(v))
42
+ out[k] = v;
43
+ }
44
+ return out;
45
+ }
46
+ catch {
47
+ // Unparseable state reads as "no card stored", which makes the next call
48
+ // post a fresh one. Throwing here would take the tool down over a file the
49
+ // caller never sees. A pre-2588-shape bare number fails isEntry and reads as
50
+ // absent for the same reason: it carries no timestamp, so its age is
51
+ // unknowable and it can never be aged out.
52
+ return {};
53
+ }
54
+ }
55
+ /** The stored message id for this key, or null. Null once the entry has gone
56
+ * CARD_TTL_MS untouched: the caller then posts fresh, which is how a key whose
57
+ * message is gone recovers without matching on Telegram's error prose. */
58
+ export function readCardId(platformRoot, accountId, k, now = Date.now()) {
59
+ const path = storePath(platformRoot, accountId);
60
+ if (!path)
61
+ return null;
62
+ const entry = readAll(path)[k];
63
+ if (!entry)
64
+ return null;
65
+ return now - entry.at >= CARD_TTL_MS ? null : entry.id;
66
+ }
67
+ /** Record the message id this key now names, and drop every entry that has gone
68
+ * CARD_TTL_MS untouched. Compaction rides the write because the write already
69
+ * rewrites the whole file; a separate prune pass would be a second thing to
70
+ * schedule. Every surviving key keeps its own id and timestamp, the same promise
71
+ * persistTelegramBot makes for bot entries. */
72
+ export function writeCardId(platformRoot, accountId, k, messageId, now = Date.now()) {
73
+ const path = storePath(platformRoot, accountId);
74
+ if (!path)
75
+ return;
76
+ const kept = {};
77
+ for (const [key, entry] of Object.entries(readAll(path))) {
78
+ if (now - entry.at < CARD_TTL_MS)
79
+ kept[key] = entry;
80
+ }
81
+ kept[k] = { id: messageId, at: now };
82
+ writeFileSync(path, JSON.stringify(kept, null, 2) + "\n", "utf-8");
83
+ }
84
+ export const CARD_CENSUS_TAG = "[telegram-card-census]";
85
+ /** The standing check for this store, emitted once at MCP boot.
86
+ *
87
+ * It answers what nothing else can: is telegram-cards.json growing? Every entry
88
+ * is one key that was used and kept, and until this line existed that growth was
89
+ * invisible — Task 2588 gave the media store a census and gave this one none.
90
+ *
91
+ * It reports the count it read back from disk, never that a prune ran. A prune
92
+ * that pruned nothing and a prune that worked print the same thing if the line
93
+ * reports the prune rather than the state.
94
+ *
95
+ * `keys` is every entry ON DISK, expired ones included. Compaction only rides a
96
+ * write, so an account that stops posting cards keeps its file at whatever size
97
+ * it reached while every entry in it reads as absent through readCardId. That is
98
+ * the right number for the question this line asks — is the file growing — but
99
+ * it is not a count of live cards. `keys=0` with `bytes>0` is the third state: a
100
+ * file that exists and parsed to nothing.
101
+ *
102
+ * `keys` rising across boots while jobs close is the leak. Never throws: a boot
103
+ * throw empties the plugin registry (CLAUDE.md), so any failure reports zeros.
104
+ *
105
+ * Task 2604 added `cardsWithButtons` and `turns`, which come from LOG_DIR rather
106
+ * than from this store: buttons are not stored here and an unkeyed one-off card
107
+ * has no entry at all, so neither is answerable from telegram-cards.json. The
108
+ * pair is the signal for the affordances clause in the Telegram turn
109
+ * instruction — not offering a button is a non-event and logs nothing of its
110
+ * own, so only a ratio can show the clause taking or over-firing. `turns` is on
111
+ * the line because `cardsWithButtons=0` alone cannot be told from a counter that
112
+ * is not running. No threshold is asserted here; the numbers are what the
113
+ * operator judges the wording against.
114
+ *
115
+ * THE TWO HALVES OF THIS LINE ARE SCOPED DIFFERENTLY, and reading them as one
116
+ * scope is the mistake to avoid. `keys` and `bytes` are ONE ACCOUNT's: they read
117
+ * telegram-cards.json under that account's own directory. `cardsWithButtons` and
118
+ * `turns` are INSTALL-WIDE: LOG_DIR is `~/.<brand>/logs/`, which every account in
119
+ * the brand shares, and no line in it carries an accountId to filter on. So on a
120
+ * multi-account install the ratio is the whole brand's and the store counts are
121
+ * one account's. Per-account attribution would need an accountId on the
122
+ * `op=card` and `op=delivered` lines, which neither carries today. */
123
+ export function cardCensusLine(platformRoot, accountId, logDir) {
124
+ let keys = 0;
125
+ let bytes = 0;
126
+ try {
127
+ if (accountId) {
128
+ const path = storePath(platformRoot, accountId);
129
+ if (path && existsSync(path)) {
130
+ keys = Object.keys(readAll(path)).length;
131
+ bytes = statSync(path).size;
132
+ }
133
+ }
134
+ }
135
+ catch {
136
+ // Zeros, deliberately. See the doc comment.
137
+ }
138
+ const ratio = cardRatioFromLogs(logDir);
139
+ return `${CARD_CENSUS_TAG} keys=${keys} bytes=${bytes} cardsWithButtons=${ratio.cardsWithButtons} turns=${ratio.turns}`;
140
+ }
141
+ //# sourceMappingURL=card-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-store.js","sourceRoot":"","sources":["../../src/lib/card-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /** Task 2602 — the read side of the live-location record.
2
+ *
3
+ * The platform writes it (`platform/ui/app/lib/telegram/live-location.ts`) on
4
+ * every location-carrying inbound; this reads it back for the agent. The shape,
5
+ * the file name and the expiry rule are duplicated across the boundary on
6
+ * purpose — the plugin cannot import from `platform/ui/app`, the same boundary
7
+ * that already duplicates the webhook secret path and the card store — and
8
+ * `ui/app/lib/telegram/__tests__/live-location-boundary.test.ts` asserts the two
9
+ * derivations agree.
10
+ *
11
+ * Runtime state, so its own file beside `telegram-cards.json` rather than a key
12
+ * in `account.json`, which holds configuration. Same brand containment: the
13
+ * path resolves through `resolveAccountDir`, so a traversal in the account id
14
+ * reads as no share rather than reaching outside the install.
15
+ */
16
+ export declare const LIVE_LOCATION_FILE = "telegram-live-location.json";
17
+ export interface LiveLocationRecord {
18
+ lat: number;
19
+ lon: number;
20
+ /** Telegram's own measurement time, in ms. Not when we heard about it. */
21
+ at: number;
22
+ botId: string;
23
+ /** The share's own `live_period`, in seconds. */
24
+ livePeriodS: number;
25
+ }
26
+ export declare function liveLocationKey(botId: string, senderId: string): string;
27
+ /** Item 5's rule: a record older than the share's own `live_period` reads as
28
+ * absent, so a stale fix is never answered as current. */
29
+ export declare function isExpired(rec: LiveLocationRecord, now: number): boolean;
30
+ /** The current position for one sender on one bot, or a named refusal.
31
+ *
32
+ * An expired record comes back as no record at all. Returning it and trusting
33
+ * every caller to check the outcome is exactly how a stale fix gets reported as
34
+ * where somebody is now. */
35
+ export declare function readLiveLocation(platformRoot: string, accountId: string, botId: string, senderId: string, now?: number): {
36
+ outcome: "current" | "expired" | "absent";
37
+ record: LiveLocationRecord | null;
38
+ ageMs: number | null;
39
+ };
40
+ /** Every `<botId>:<senderId>` still inside its period. The refusal lists these
41
+ * so a caller who guessed the wrong id can correct it without guessing again.
42
+ * Keys only: a refusal is not a place to hand back positions nobody asked for. */
43
+ export declare function currentLiveLocationKeys(platformRoot: string, accountId: string, now?: number): string[];
44
+ //# sourceMappingURL=live-location-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-location-store.d.ts","sourceRoot":"","sources":["../../src/lib/live-location-store.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,gCAAgC,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvE;AAkBD;2DAC2D;AAC3D,wBAAgB,SAAS,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvE;AAsBD;;;;6BAI6B;AAC7B,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAmB,GACvB;IACD,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1C,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAMA;AAED;;mFAEmF;AACnF,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAmB,GACvB,MAAM,EAAE,CAIV"}
@@ -0,0 +1,88 @@
1
+ import { join } from "node:path";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { resolveAccountDir } from "./account-write.js";
4
+ /** Task 2602 — the read side of the live-location record.
5
+ *
6
+ * The platform writes it (`platform/ui/app/lib/telegram/live-location.ts`) on
7
+ * every location-carrying inbound; this reads it back for the agent. The shape,
8
+ * the file name and the expiry rule are duplicated across the boundary on
9
+ * purpose — the plugin cannot import from `platform/ui/app`, the same boundary
10
+ * that already duplicates the webhook secret path and the card store — and
11
+ * `ui/app/lib/telegram/__tests__/live-location-boundary.test.ts` asserts the two
12
+ * derivations agree.
13
+ *
14
+ * Runtime state, so its own file beside `telegram-cards.json` rather than a key
15
+ * in `account.json`, which holds configuration. Same brand containment: the
16
+ * path resolves through `resolveAccountDir`, so a traversal in the account id
17
+ * reads as no share rather than reaching outside the install.
18
+ */
19
+ export const LIVE_LOCATION_FILE = "telegram-live-location.json";
20
+ export function liveLocationKey(botId, senderId) {
21
+ return `${botId}:${senderId}`;
22
+ }
23
+ function isRecord(v) {
24
+ if (!v || typeof v !== "object" || Array.isArray(v))
25
+ return false;
26
+ const r = v;
27
+ return (typeof r.lat === "number" &&
28
+ Number.isFinite(r.lat) &&
29
+ typeof r.lon === "number" &&
30
+ Number.isFinite(r.lon) &&
31
+ typeof r.at === "number" &&
32
+ Number.isFinite(r.at) &&
33
+ typeof r.botId === "string" &&
34
+ typeof r.livePeriodS === "number" &&
35
+ Number.isFinite(r.livePeriodS));
36
+ }
37
+ /** Item 5's rule: a record older than the share's own `live_period` reads as
38
+ * absent, so a stale fix is never answered as current. */
39
+ export function isExpired(rec, now) {
40
+ return now - rec.at >= rec.livePeriodS * 1000;
41
+ }
42
+ function readAll(platformRoot, accountId) {
43
+ const resolved = resolveAccountDir(platformRoot, accountId);
44
+ if (!resolved.ok)
45
+ return {};
46
+ const path = join(resolved.dir, LIVE_LOCATION_FILE);
47
+ if (!existsSync(path))
48
+ return {};
49
+ try {
50
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
51
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
52
+ return {};
53
+ const out = {};
54
+ for (const [k, v] of Object.entries(parsed)) {
55
+ if (isRecord(v))
56
+ out[k] = v;
57
+ }
58
+ return out;
59
+ }
60
+ catch {
61
+ // Unparseable state reads as "no share stored", so the tool refuses by name.
62
+ // Throwing here would take the tool down over a file the caller never sees.
63
+ return {};
64
+ }
65
+ }
66
+ /** The current position for one sender on one bot, or a named refusal.
67
+ *
68
+ * An expired record comes back as no record at all. Returning it and trusting
69
+ * every caller to check the outcome is exactly how a stale fix gets reported as
70
+ * where somebody is now. */
71
+ export function readLiveLocation(platformRoot, accountId, botId, senderId, now = Date.now()) {
72
+ const rec = readAll(platformRoot, accountId)[liveLocationKey(botId, senderId)];
73
+ if (!rec)
74
+ return { outcome: "absent", record: null, ageMs: null };
75
+ const ageMs = now - rec.at;
76
+ if (isExpired(rec, now))
77
+ return { outcome: "expired", record: null, ageMs };
78
+ return { outcome: "current", record: rec, ageMs };
79
+ }
80
+ /** Every `<botId>:<senderId>` still inside its period. The refusal lists these
81
+ * so a caller who guessed the wrong id can correct it without guessing again.
82
+ * Keys only: a refusal is not a place to hand back positions nobody asked for. */
83
+ export function currentLiveLocationKeys(platformRoot, accountId, now = Date.now()) {
84
+ return Object.entries(readAll(platformRoot, accountId))
85
+ .filter(([, rec]) => !isExpired(rec, now))
86
+ .map(([k]) => k);
87
+ }
88
+ //# sourceMappingURL=live-location-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-location-store.js","sourceRoot":"","sources":["../../src/lib/live-location-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { type InlineKeyboardButtonInput } from "../lib/telegram.js";
2
+ export type AskKind = "poll" | "checklist" | "location" | "venue" | "contact" | "dice" | "stopPoll" | "editChecklist" | "editLiveLocation" | "stopLiveLocation";
3
+ /** Kind to Bot API method. Verified against the live parameter tables on
4
+ * 2026-08-08. Exported so the census's owned-method map and this tool cannot
5
+ * disagree about which methods the tool owns. */
6
+ export declare const ASK_METHOD: Readonly<Record<AskKind, string>>;
7
+ export interface ChecklistInput {
8
+ title: string;
9
+ tasks: Array<{
10
+ id: number;
11
+ text: string;
12
+ }>;
13
+ othersCanAddTasks?: boolean;
14
+ othersCanMarkTasksAsDone?: boolean;
15
+ }
16
+ export interface AskParams {
17
+ botId: string;
18
+ chatId: string | number;
19
+ kind: AskKind;
20
+ question?: string;
21
+ options?: string[];
22
+ pollType?: "regular" | "quiz";
23
+ isAnonymous?: boolean;
24
+ allowsMultipleAnswers?: boolean;
25
+ correctOptionIds?: number[];
26
+ explanation?: string;
27
+ openPeriod?: number;
28
+ businessConnectionId?: string;
29
+ checklist?: ChecklistInput;
30
+ latitude?: number;
31
+ longitude?: number;
32
+ horizontalAccuracy?: number;
33
+ livePeriod?: number;
34
+ heading?: number;
35
+ proximityAlertRadius?: number;
36
+ title?: string;
37
+ address?: string;
38
+ phoneNumber?: string;
39
+ firstName?: string;
40
+ lastName?: string;
41
+ emoji?: string;
42
+ messageId?: number;
43
+ buttons?: InlineKeyboardButtonInput[][];
44
+ replyToMessageId?: number;
45
+ messageThreadId?: number;
46
+ disableNotification?: boolean;
47
+ protectContent?: boolean;
48
+ }
49
+ export interface AskDeps {
50
+ platformRoot: string;
51
+ accountId: string | undefined;
52
+ /** Per-invocation id threading one call's lines together. */
53
+ callId: string;
54
+ log: (line: string) => void;
55
+ fetchImpl?: typeof fetch;
56
+ }
57
+ export interface AskResult {
58
+ ok: boolean;
59
+ text: string;
60
+ isError: boolean;
61
+ }
62
+ /** Polls, checklists, locations, venues, contacts and dice, plus stopping a
63
+ * poll and editing or stopping a live location.
64
+ *
65
+ * Task 2594: these ten methods were reachable only through telegram-api, whose
66
+ * untyped params object gave the model no field names for any of them, so a
67
+ * malformed call was caught by Telegram's 400 and nothing earlier.
68
+ *
69
+ * Inline messages are not addressed. Telegram lets editMessageLiveLocation and
70
+ * stopMessageLiveLocation target an inline_message_id instead of a chat, but
71
+ * nothing on this install sends inline messages, so chatId stays required. */
72
+ export declare function telegramAsk(p: AskParams, deps: AskDeps): Promise<AskResult>;
73
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/tools/ask.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAKzF,MAAM,MAAM,OAAO,GACf,MAAM,GACN,WAAW,GACX,UAAU,GACV,OAAO,GACP,SAAS,GACT,MAAM,GACN,UAAU,GACV,eAAe,GACf,kBAAkB,GAClB,kBAAkB,CAAC;AAEvB;;kDAEkD;AAClD,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAWvD,CAAC;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,yBAAyB,EAAE,EAAE,CAAC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAwLD;;;;;;;;;+EAS+E;AAC/E,wBAAsB,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAiEjF"}