@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,75 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { mkdtempSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { cardRatioFromLogs, tallyCardRatio } from "../lib/card-ratio.js";
6
+ const CARD = (n) => `[telegram-tools] op=card callId=abcd outcome=sent buttons=${n}`;
7
+ const TURN = (role) => `[telegram:inbound] op=delivered key=12345678 role=${role} source=user payloadBytes=12`;
8
+ describe("tallyCardRatio", () => {
9
+ it("counts a card with buttons and not one without", () => {
10
+ expect(tallyCardRatio([CARD(2), CARD(0), CARD(1)])).toEqual({ cardsWithButtons: 2, turns: 0 });
11
+ });
12
+ it("counts admin-door turns and not public ones", () => {
13
+ expect(tallyCardRatio([TURN("admin"), TURN("public"), TURN("admin")])).toEqual({
14
+ cardsWithButtons: 0,
15
+ turns: 2,
16
+ });
17
+ });
18
+ // The two failure modes the task names, read off one line.
19
+ it("reads as the clause not taking when there are turns and no buttoned cards", () => {
20
+ expect(tallyCardRatio([TURN("admin"), TURN("admin"), CARD(0)])).toEqual({
21
+ cardsWithButtons: 0,
22
+ turns: 2,
23
+ });
24
+ });
25
+ it("reads as over-firing when buttoned cards approach turns", () => {
26
+ expect(tallyCardRatio([TURN("admin"), CARD(3), TURN("admin"), CARD(2)])).toEqual({
27
+ cardsWithButtons: 2,
28
+ turns: 2,
29
+ });
30
+ });
31
+ // A zero numerator over a zero denominator is what a dead counter prints and
32
+ // must not be reported as health. The census line carries both, so the operator
33
+ // can tell them apart; the tally's job is only to not invent one.
34
+ it("returns zeros for no lines at all", () => {
35
+ expect(tallyCardRatio([])).toEqual({ cardsWithButtons: 0, turns: 0 });
36
+ });
37
+ it("ignores an op=card line from a build with no buttons field", () => {
38
+ expect(tallyCardRatio(["[telegram-tools] op=card callId=abcd outcome=sent"])).toEqual({
39
+ cardsWithButtons: 0,
40
+ turns: 0,
41
+ });
42
+ });
43
+ it("does not count the op=call or op=result lines of the same card", () => {
44
+ expect(tallyCardRatio([
45
+ "[telegram-tools] op=call tool=telegram-card method=sendMessage callId=abcd botId=111",
46
+ `[telegram-tools] op=result callId=abcd tool=telegram-card method=sendMessage ok=true errorCode=- description=""`,
47
+ CARD(2),
48
+ ])).toEqual({ cardsWithButtons: 1, turns: 0 });
49
+ });
50
+ });
51
+ describe("cardRatioFromLogs", () => {
52
+ it("sums both counts across every mcp-*.log in the directory", () => {
53
+ const dir = mkdtempSync(join(tmpdir(), "logs-"));
54
+ writeFileSync(join(dir, "mcp-admin-a.log"), [CARD(2), CARD(0)].join("\n"), "utf-8");
55
+ writeFileSync(join(dir, "mcp-telegram-channel-a.log"), [TURN("admin"), TURN("admin")].join("\n"), "utf-8");
56
+ expect(cardRatioFromLogs(dir)).toEqual({ cardsWithButtons: 1, turns: 2 });
57
+ });
58
+ it("skips a file that is not an mcp-*.log", () => {
59
+ const dir = mkdtempSync(join(tmpdir(), "logs-"));
60
+ writeFileSync(join(dir, "server.log"), [CARD(2), TURN("admin")].join("\n"), "utf-8");
61
+ expect(cardRatioFromLogs(dir)).toEqual({ cardsWithButtons: 0, turns: 0 });
62
+ });
63
+ it("skips a rotated .gz rather than reading it as text", () => {
64
+ const dir = mkdtempSync(join(tmpdir(), "logs-"));
65
+ writeFileSync(join(dir, "mcp-admin-a.log.gz"), CARD(2), "utf-8");
66
+ expect(cardRatioFromLogs(dir)).toEqual({ cardsWithButtons: 0, turns: 0 });
67
+ });
68
+ it("reports zeros without throwing when LOG_DIR is absent", () => {
69
+ expect(cardRatioFromLogs(undefined)).toEqual({ cardsWithButtons: 0, turns: 0 });
70
+ });
71
+ it("reports zeros without throwing when LOG_DIR does not exist", () => {
72
+ expect(cardRatioFromLogs("/no/such/directory")).toEqual({ cardsWithButtons: 0, turns: 0 });
73
+ });
74
+ });
75
+ //# sourceMappingURL=card-ratio.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-ratio.test.js","sourceRoot":"","sources":["../../src/__tests__/card-ratio.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=card-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/card-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ import { describe, expect, it, beforeEach } from "vitest";
2
+ import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, statSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { CARD_TTL_MS, cardCensusLine, cardKey, readCardId, writeCardId, } from "../lib/card-store.js";
6
+ import { resolveAccountDir } from "../lib/account-write.js";
7
+ /** A brand install: <root>/platform is PLATFORM_ROOT, <root>/data/accounts/<id>
8
+ * is where account state lives. Mirrors account-token.ts:15. */
9
+ function brandInstall(accountId) {
10
+ const root = mkdtempSync(join(tmpdir(), "brand-"));
11
+ mkdirSync(join(root, "platform"), { recursive: true });
12
+ mkdirSync(join(root, "data", "accounts", accountId), { recursive: true });
13
+ return join(root, "platform");
14
+ }
15
+ const ACC = "acc-1";
16
+ let platformRoot;
17
+ beforeEach(() => {
18
+ platformRoot = brandInstall(ACC);
19
+ });
20
+ describe("cardKey", () => {
21
+ it("is scoped by bot and chat, so the same key in two chats is two cards", () => {
22
+ expect(cardKey("111", 222, "job")).toBe("111:222:job");
23
+ expect(cardKey("111", 333, "job")).not.toBe(cardKey("111", 222, "job"));
24
+ });
25
+ });
26
+ describe("resolveAccountDir", () => {
27
+ it("resolves an account directory under the brand install", () => {
28
+ const out = resolveAccountDir(platformRoot, ACC);
29
+ expect(out).toEqual({ ok: true, dir: join(platformRoot, "..", "data", "accounts", ACC) });
30
+ });
31
+ it("refuses an accountId that traverses out of the brand install", () => {
32
+ const out = resolveAccountDir(platformRoot, "../../../../../../etc");
33
+ expect(out).toEqual({ ok: false, error: "non-brand-path" });
34
+ });
35
+ });
36
+ describe("readCardId / writeCardId", () => {
37
+ it("returns null when nothing was ever stored", () => {
38
+ expect(readCardId(platformRoot, ACC, cardKey("111", 222, "job"))).toBeNull();
39
+ });
40
+ it("round-trips a message id", () => {
41
+ const k = cardKey("111", 222, "job");
42
+ writeCardId(platformRoot, ACC, k, 4102);
43
+ expect(readCardId(platformRoot, ACC, k)).toBe(4102);
44
+ });
45
+ it("leaves another key's entry byte-identical on write", () => {
46
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "a"), 1);
47
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "b"), 2);
48
+ expect(readCardId(platformRoot, ACC, cardKey("111", 222, "a"))).toBe(1);
49
+ expect(readCardId(platformRoot, ACC, cardKey("111", 222, "b"))).toBe(2);
50
+ });
51
+ it("overwrites the same key rather than accumulating", () => {
52
+ const k = cardKey("111", 222, "job");
53
+ writeCardId(platformRoot, ACC, k, 1);
54
+ writeCardId(platformRoot, ACC, k, 2);
55
+ expect(readCardId(platformRoot, ACC, k)).toBe(2);
56
+ });
57
+ it("returns null on unparseable state rather than throwing", () => {
58
+ const path = join(platformRoot, "..", "data", "accounts", ACC, "telegram-cards.json");
59
+ writeFileSync(path, "{ not json", "utf-8");
60
+ expect(readCardId(platformRoot, ACC, cardKey("111", 222, "job"))).toBeNull();
61
+ });
62
+ it("writes nothing when the account dir escapes the brand install", () => {
63
+ writeCardId(platformRoot, "../../../../../../tmp", cardKey("111", 222, "job"), 1);
64
+ expect(existsSync(join(tmpdir(), "telegram-cards.json"))).toBe(false);
65
+ });
66
+ it("stores state beside account.json, not inside it", () => {
67
+ const dir = join(platformRoot, "..", "data", "accounts", ACC);
68
+ writeFileSync(join(dir, "account.json"), JSON.stringify({ telegram: { bots: [] } }), "utf-8");
69
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "job"), 7);
70
+ expect(JSON.parse(readFileSync(join(dir, "account.json"), "utf-8"))).toEqual({
71
+ telegram: { bots: [] },
72
+ });
73
+ expect(existsSync(join(dir, "telegram-cards.json"))).toBe(true);
74
+ });
75
+ });
76
+ describe("expiry", () => {
77
+ const K = cardKey("111", 222, "job");
78
+ it("reads back an id written at the same instant", () => {
79
+ writeCardId(platformRoot, ACC, K, 4102, 1_000_000);
80
+ expect(readCardId(platformRoot, ACC, K, 1_000_000)).toBe(4102);
81
+ });
82
+ it("still reads one millisecond before the window closes", () => {
83
+ writeCardId(platformRoot, ACC, K, 4102, 1_000_000);
84
+ expect(readCardId(platformRoot, ACC, K, 1_000_000 + CARD_TTL_MS - 1)).toBe(4102);
85
+ });
86
+ it("reads null once the entry is exactly CARD_TTL_MS old", () => {
87
+ writeCardId(platformRoot, ACC, K, 4102, 1_000_000);
88
+ expect(readCardId(platformRoot, ACC, K, 1_000_000 + CARD_TTL_MS)).toBeNull();
89
+ });
90
+ it("drops stale entries and keeps fresh ones in the same rewrite", () => {
91
+ const old = cardKey("111", 222, "old");
92
+ const fresh = cardKey("111", 222, "fresh");
93
+ const added = cardKey("111", 222, "new");
94
+ // `old` is written at 0 and `fresh` at CARD_TTL_MS. The third write also
95
+ // lands at CARD_TTL_MS, so `old` is exactly CARD_TTL_MS stale (the boundary
96
+ // the previous test pins as expired) and `fresh` is zero milliseconds old.
97
+ writeCardId(platformRoot, ACC, old, 1, 0);
98
+ writeCardId(platformRoot, ACC, fresh, 2, CARD_TTL_MS);
99
+ writeCardId(platformRoot, ACC, added, 3, CARD_TTL_MS);
100
+ const path = join(platformRoot, "..", "data", "accounts", ACC, "telegram-cards.json");
101
+ const kept = JSON.parse(readFileSync(path, "utf-8"));
102
+ expect(Object.keys(kept).sort()).toEqual([added, fresh].sort());
103
+ expect(readCardId(platformRoot, ACC, old, CARD_TTL_MS)).toBeNull();
104
+ expect(readCardId(platformRoot, ACC, fresh, CARD_TTL_MS)).toBe(2);
105
+ });
106
+ it("reads a pre-2588-shape bare number as absent", () => {
107
+ const path = join(platformRoot, "..", "data", "accounts", ACC, "telegram-cards.json");
108
+ writeFileSync(path, JSON.stringify({ [K]: 4102 }), "utf-8");
109
+ expect(readCardId(platformRoot, ACC, K, 1_000_000)).toBeNull();
110
+ });
111
+ });
112
+ describe("cardCensusLine", () => {
113
+ it("reports zeros when no card has ever been written", () => {
114
+ expect(cardCensusLine(platformRoot, ACC)).toBe("[telegram-card-census] keys=0 bytes=0 cardsWithButtons=0 turns=0");
115
+ });
116
+ it("reports zeros without throwing when ACCOUNT_ID is absent", () => {
117
+ expect(cardCensusLine(platformRoot, undefined)).toBe("[telegram-card-census] keys=0 bytes=0 cardsWithButtons=0 turns=0");
118
+ });
119
+ it("reports zeros without throwing when the accountId escapes the brand install", () => {
120
+ expect(cardCensusLine(platformRoot, "../../../../../../etc")).toBe("[telegram-card-census] keys=0 bytes=0 cardsWithButtons=0 turns=0");
121
+ });
122
+ it("counts the entries it reads back from disk, with the file's byte size", () => {
123
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "a"), 1, 1_000);
124
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "b"), 2, 1_000);
125
+ const path = join(platformRoot, "..", "data", "accounts", ACC, "telegram-cards.json");
126
+ const bytes = statSync(path).size;
127
+ expect(cardCensusLine(platformRoot, ACC)).toBe(`[telegram-card-census] keys=2 bytes=${bytes} cardsWithButtons=0 turns=0`);
128
+ });
129
+ // Task 2604 — the ratio rides this line, so a caller that passes a LOG_DIR gets
130
+ // both counts from it. `turns` is present so the operator can tell a healthy
131
+ // quiet window from a counter that stopped.
132
+ it("carries the button-and-turn ratio when given a log directory", () => {
133
+ const dir = mkdtempSync(join(tmpdir(), "logs-"));
134
+ writeFileSync(join(dir, "mcp-admin-a.log"), "[telegram-tools] op=card callId=abcd outcome=sent buttons=2", "utf-8");
135
+ writeFileSync(join(dir, "mcp-telegram-channel-a.log"), "[telegram:inbound] op=delivered key=12345678 role=admin source=user payloadBytes=12", "utf-8");
136
+ expect(cardCensusLine(platformRoot, ACC, dir)).toBe("[telegram-card-census] keys=0 bytes=0 cardsWithButtons=1 turns=1");
137
+ });
138
+ it("rises on a write and falls when a write compacts stale entries", () => {
139
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "a"), 1, 0);
140
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "b"), 2, 0);
141
+ expect(cardCensusLine(platformRoot, ACC)).toContain("keys=2");
142
+ // A write CARD_TTL_MS later: both earlier entries age out, one new one lands.
143
+ writeCardId(platformRoot, ACC, cardKey("111", 222, "c"), 3, CARD_TTL_MS);
144
+ expect(cardCensusLine(platformRoot, ACC)).toContain("keys=1");
145
+ });
146
+ it("does not count an unparseable file as entries", () => {
147
+ const path = join(platformRoot, "..", "data", "accounts", ACC, "telegram-cards.json");
148
+ writeFileSync(path, "{ not json", "utf-8");
149
+ expect(cardCensusLine(platformRoot, ACC)).toContain("keys=0");
150
+ });
151
+ });
152
+ //# sourceMappingURL=card-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-store.test.js","sourceRoot":"","sources":["../../src/__tests__/card-store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=card-tool.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-tool.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/card-tool.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,231 @@
1
+ import { describe, expect, it, beforeEach } from "vitest";
2
+ import { mkdtempSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { telegramCard } from "../tools/card.js";
6
+ import { cardKey, readCardId } from "../lib/card-store.js";
7
+ const ACC = "acc-1";
8
+ const BOT = "111";
9
+ let platformRoot;
10
+ let lines;
11
+ function install() {
12
+ const root = mkdtempSync(join(tmpdir(), "brand-"));
13
+ mkdirSync(join(root, "platform"), { recursive: true });
14
+ const dir = join(root, "data", "accounts", ACC);
15
+ mkdirSync(dir, { recursive: true });
16
+ writeFileSync(join(dir, "account.json"), JSON.stringify({ telegram: { bots: [{ id: BOT, role: "admin", token: `${BOT}:SECRET` }] } }), "utf-8");
17
+ return join(root, "platform");
18
+ }
19
+ /** Records every (method, body) pair and replies from a queue. */
20
+ function recorder(replies) {
21
+ const calls = [];
22
+ let i = 0;
23
+ const fetchImpl = (async (url, init) => {
24
+ calls.push({
25
+ method: String(url).split("/").pop() ?? "",
26
+ body: JSON.parse(String(init.body)),
27
+ });
28
+ return new Response(JSON.stringify(replies[i++] ?? { ok: true, result: {} }));
29
+ });
30
+ return { calls, fetchImpl };
31
+ }
32
+ const sent = (id) => ({ ok: true, result: { message_id: id } });
33
+ const notModified = {
34
+ ok: false,
35
+ error_code: 400,
36
+ description: "Bad Request: message is not modified",
37
+ };
38
+ beforeEach(() => {
39
+ platformRoot = install();
40
+ lines = [];
41
+ });
42
+ function deps(fetchImpl) {
43
+ return {
44
+ platformRoot,
45
+ accountId: ACC,
46
+ callId: "abcd1234",
47
+ log: (l) => lines.push(l),
48
+ fetchImpl,
49
+ };
50
+ }
51
+ describe("telegramCard", () => {
52
+ it("posts a new card when no key is given", async () => {
53
+ const { calls, fetchImpl } = recorder([sent(500)]);
54
+ const out = await telegramCard({ botId: BOT, chatId: 222, text: "Job 4102" }, deps(fetchImpl));
55
+ expect(out.outcome).toBe("sent");
56
+ expect(out.isError).toBe(false);
57
+ expect(calls[0]?.method).toBe("sendMessage");
58
+ expect(calls[0]?.body).toMatchObject({ chat_id: 222, text: "Job 4102" });
59
+ });
60
+ it("posts on the first keyed call and edits on the second", async () => {
61
+ const first = recorder([sent(500)]);
62
+ await telegramCard({ botId: BOT, chatId: 222, key: "j4102", text: "one" }, deps(first.fetchImpl));
63
+ const second = recorder([sent(500)]);
64
+ const out = await telegramCard({ botId: BOT, chatId: 222, key: "j4102", text: "two" }, deps(second.fetchImpl));
65
+ expect(out.outcome).toBe("edited");
66
+ expect(second.calls[0]?.method).toBe("editMessageText");
67
+ expect(second.calls[0]?.body).toMatchObject({ chat_id: 222, message_id: 500, text: "two" });
68
+ });
69
+ it("treats 'message is not modified' as a no-op, not an error", async () => {
70
+ const first = recorder([sent(500)]);
71
+ await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "same" }, deps(first.fetchImpl));
72
+ const second = recorder([notModified]);
73
+ const out = await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "same" }, deps(second.fetchImpl));
74
+ expect(out.outcome).toBe("unchanged");
75
+ expect(out.isError).toBe(false);
76
+ expect(out.ok).toBe(true);
77
+ expect(lines.join("\n")).toContain("op=card callId=abcd1234 outcome=unchanged");
78
+ });
79
+ it("relays any other Telegram refusal unaltered", async () => {
80
+ const { fetchImpl } = recorder([
81
+ { ok: false, error_code: 403, description: "Forbidden: bot was blocked by the user" },
82
+ ]);
83
+ const out = await telegramCard({ botId: BOT, chatId: 222, text: "hi" }, deps(fetchImpl));
84
+ expect(out.isError).toBe(true);
85
+ expect(out.text).toContain("Forbidden: bot was blocked by the user");
86
+ expect(out.text).toContain("403");
87
+ });
88
+ it("maps buttons to the Bot API inline keyboard shape", async () => {
89
+ const { calls, fetchImpl } = recorder([sent(1)]);
90
+ await telegramCard({
91
+ botId: BOT,
92
+ chatId: 222,
93
+ text: "pick",
94
+ buttons: [
95
+ [
96
+ { text: "Accept", callbackData: "j:ok" },
97
+ { text: "Sheet", webAppUrl: "https://x/y" },
98
+ ],
99
+ ],
100
+ }, deps(fetchImpl));
101
+ expect(calls[0]?.body.reply_markup).toEqual({
102
+ inline_keyboard: [
103
+ [
104
+ { text: "Accept", callback_data: "j:ok" },
105
+ { text: "Sheet", web_app: { url: "https://x/y" } },
106
+ ],
107
+ ],
108
+ });
109
+ });
110
+ it("answers the callback query AFTER the send, so a stale id cannot block the card", async () => {
111
+ const { calls, fetchImpl } = recorder([sent(1), { ok: true, result: true }]);
112
+ await telegramCard({ botId: BOT, chatId: 222, text: "hi", callbackQueryId: "q1", alert: true }, deps(fetchImpl));
113
+ expect(calls.map((c) => c.method)).toEqual(["sendMessage", "answerCallbackQuery"]);
114
+ expect(calls[1]?.body).toMatchObject({ callback_query_id: "q1", show_alert: true });
115
+ });
116
+ it("reports a failed callback answer while still naming what the send achieved", async () => {
117
+ const { fetchImpl } = recorder([
118
+ sent(1),
119
+ { ok: false, error_code: 400, description: "Bad Request: query is too old" },
120
+ ]);
121
+ const out = await telegramCard({ botId: BOT, chatId: 222, text: "hi", callbackQueryId: "q1" }, deps(fetchImpl));
122
+ expect(out.isError).toBe(true);
123
+ expect(out.outcome).toBe("sent");
124
+ expect(out.text).toContain("query is too old");
125
+ });
126
+ it("refuses with the registered bot list when the botId is unknown", async () => {
127
+ const { calls, fetchImpl } = recorder([]);
128
+ const out = await telegramCard({ botId: "999", chatId: 222, text: "hi" }, deps(fetchImpl));
129
+ expect(out.isError).toBe(true);
130
+ expect(out.text).toContain("111");
131
+ expect(calls.length).toBe(0);
132
+ expect(lines.join("\n")).toContain("op=no-bot");
133
+ });
134
+ it("refuses without ACCOUNT_ID and makes no network call", async () => {
135
+ const { calls, fetchImpl } = recorder([]);
136
+ const out = await telegramCard({ botId: BOT, chatId: 222, text: "hi" }, { platformRoot, accountId: undefined, callId: "c", log: (l) => lines.push(l), fetchImpl });
137
+ expect(out.isError).toBe(true);
138
+ expect(calls.length).toBe(0);
139
+ expect(lines.join("\n")).toContain("op=no-account");
140
+ });
141
+ it("emits a call/result pair sharing one callId", async () => {
142
+ const { fetchImpl } = recorder([sent(1)]);
143
+ await telegramCard({ botId: BOT, chatId: 222, text: "hi" }, deps(fetchImpl));
144
+ expect(lines.join("\n")).toContain("op=call tool=telegram-card method=sendMessage callId=abcd1234");
145
+ expect(lines.join("\n")).toContain("op=result callId=abcd1234 tool=telegram-card method=sendMessage ok=true");
146
+ });
147
+ it("never puts the token in a log line", async () => {
148
+ const { fetchImpl } = recorder([sent(1)]);
149
+ await telegramCard({ botId: BOT, chatId: 222, text: "hi" }, deps(fetchImpl));
150
+ expect(lines.join("\n")).not.toContain("SECRET");
151
+ });
152
+ });
153
+ const editNotFound = {
154
+ ok: false,
155
+ error_code: 400,
156
+ description: "Bad Request: message to edit not found",
157
+ };
158
+ describe("telegramCard key lifecycle", () => {
159
+ const storeFile = () => join(platformRoot, "..", "data", "accounts", ACC, "telegram-cards.json");
160
+ it("relays 'message to edit not found' as an error and keeps the stored key", async () => {
161
+ const first = recorder([sent(500)]);
162
+ await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "one" }, deps(first.fetchImpl));
163
+ const second = recorder([editNotFound]);
164
+ const out = await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "two" }, deps(second.fetchImpl));
165
+ expect(out.isError).toBe(true);
166
+ expect(out.outcome).toBe("none");
167
+ expect(out.text).toContain("message to edit not found");
168
+ // Deliberately still stored. Dropping it here would post a fresh message on
169
+ // every call in the failure mode where Telegram refuses a live message
170
+ // (tdlib/telegram-bot-api#400), turning one visible error into chat spam.
171
+ expect(readCardId(platformRoot, ACC, cardKey(BOT, 222, "j"))).toBe(500);
172
+ });
173
+ it("refreshes the stored timestamp on a successful edit", async () => {
174
+ const first = recorder([sent(500)]);
175
+ await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "one" }, deps(first.fetchImpl));
176
+ const created = JSON.parse(readFileSync(storeFile(), "utf-8"))[cardKey(BOT, 222, "j")]?.at;
177
+ // Both calls run inside one millisecond on a fast machine, so comparing the
178
+ // two timestamps directly can read equal whether or not the refresh is in.
179
+ // Age the entry by hand instead: the refresh must move `at` forward from a
180
+ // value that is demonstrably in the past.
181
+ writeFileSync(storeFile(), JSON.stringify({ [cardKey(BOT, 222, "j")]: { id: 500, at: created - 60_000 } }), "utf-8");
182
+ const second = recorder([sent(500)]);
183
+ await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "two" }, deps(second.fetchImpl));
184
+ const after = JSON.parse(readFileSync(storeFile(), "utf-8"))[cardKey(BOT, 222, "j")]?.at;
185
+ expect(after).toBeGreaterThan(created - 60_000);
186
+ expect(readCardId(platformRoot, ACC, cardKey(BOT, 222, "j"))).toBe(500);
187
+ });
188
+ it("does not refresh the timestamp when Telegram says the message is not modified", async () => {
189
+ const first = recorder([sent(500)]);
190
+ await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "same" }, deps(first.fetchImpl));
191
+ const before = readFileSync(storeFile(), "utf-8");
192
+ const second = recorder([notModified]);
193
+ await telegramCard({ botId: BOT, chatId: 222, key: "j", text: "same" }, deps(second.fetchImpl));
194
+ expect(readFileSync(storeFile(), "utf-8")).toBe(before);
195
+ });
196
+ // Task 2604 — the census counts cards that carried buttons against turns on
197
+ // the door. Neither the op=call nor the op=card line recorded whether a card
198
+ // had any, so the numerator had no source. Counted flattened across rows,
199
+ // because two buttons in one row and two across two rows are the same two
200
+ // choices offered to the person.
201
+ it("records the button count on the op=card line", async () => {
202
+ const { fetchImpl } = recorder([sent(500)]);
203
+ await telegramCard({
204
+ botId: BOT,
205
+ chatId: 222,
206
+ text: "pick",
207
+ buttons: [[{ text: "Yes", callbackData: "y" }, { text: "No", callbackData: "n" }]],
208
+ }, deps(fetchImpl));
209
+ expect(lines).toContain("[telegram-tools] op=card callId=abcd1234 outcome=sent buttons=2");
210
+ });
211
+ it("records buttons=0 when the card carried none", async () => {
212
+ const { fetchImpl } = recorder([sent(500)]);
213
+ await telegramCard({ botId: BOT, chatId: 222, text: "just text" }, deps(fetchImpl));
214
+ expect(lines).toContain("[telegram-tools] op=card callId=abcd1234 outcome=sent buttons=0");
215
+ });
216
+ it("counts buttons flattened across rows", async () => {
217
+ const { fetchImpl } = recorder([sent(500)]);
218
+ await telegramCard({
219
+ botId: BOT,
220
+ chatId: 222,
221
+ text: "pick",
222
+ buttons: [
223
+ [{ text: "A", callbackData: "a" }],
224
+ [{ text: "B", callbackData: "b" }],
225
+ [{ text: "C", callbackData: "c" }],
226
+ ],
227
+ }, deps(fetchImpl));
228
+ expect(lines).toContain("[telegram-tools] op=card callId=abcd1234 outcome=sent buttons=3");
229
+ });
230
+ });
231
+ //# sourceMappingURL=card-tool.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-tool.test.js","sourceRoot":"","sources":["../../src/__tests__/card-tool.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=invoice-tool.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-tool.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/invoice-tool.test.ts"],"names":[],"mappings":""}