@rubytech/create-maxy-code 0.1.357 → 0.1.359

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 (260) hide show
  1. package/dist/__tests__/claude-ptys-slice.test.js +36 -1
  2. package/dist/__tests__/neo4j-pidfile-scrub.test.js +103 -0
  3. package/dist/index.js +42 -7
  4. package/dist/neo4j-pidfile-scrub.js +90 -0
  5. package/dist/port-resolution.js +18 -1
  6. package/package.json +1 -1
  7. package/payload/platform/package-lock.json +237 -0
  8. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js +79 -1
  9. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js.map +1 -1
  10. package/payload/platform/plugins/admin/mcp/dist/index.js +17 -3
  11. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  12. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts +16 -0
  13. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts.map +1 -1
  14. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js +52 -0
  15. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js.map +1 -1
  16. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +61 -1
  17. package/payload/platform/plugins/cloudflare/PLUGIN.md +7 -1
  18. package/payload/platform/plugins/cloudflare/bin/__tests__/cf-token.test.sh +195 -0
  19. package/payload/platform/plugins/cloudflare/bin/cf-token.sh +157 -0
  20. package/payload/platform/plugins/cloudflare/references/api.md +2 -0
  21. package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +14 -0
  22. package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +10 -1
  23. package/payload/platform/plugins/docs/PLUGIN.md +2 -0
  24. package/payload/platform/plugins/docs/references/admin-ui.md +2 -0
  25. package/payload/platform/plugins/docs/references/claudeai-connectors.md +45 -0
  26. package/payload/platform/plugins/docs/references/cloudflare.md +6 -0
  27. package/payload/platform/plugins/docs/references/troubleshooting.md +2 -0
  28. package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
  29. package/payload/platform/plugins/email/PLUGIN.md +7 -3
  30. package/payload/platform/plugins/email/mcp/dist/__tests__/body-extract.test.d.ts +2 -0
  31. package/payload/platform/plugins/email/mcp/dist/__tests__/body-extract.test.d.ts.map +1 -0
  32. package/payload/platform/plugins/email/mcp/dist/__tests__/body-extract.test.js +99 -0
  33. package/payload/platform/plugins/email/mcp/dist/__tests__/body-extract.test.js.map +1 -0
  34. package/payload/platform/plugins/email/mcp/dist/__tests__/compose-draft-id.test.d.ts +2 -0
  35. package/payload/platform/plugins/email/mcp/dist/__tests__/compose-draft-id.test.d.ts.map +1 -0
  36. package/payload/platform/plugins/email/mcp/dist/__tests__/compose-draft-id.test.js +32 -0
  37. package/payload/platform/plugins/email/mcp/dist/__tests__/compose-draft-id.test.js.map +1 -0
  38. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-edit.test.js +64 -6
  39. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-edit.test.js.map +1 -1
  40. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js +12 -0
  41. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js.map +1 -1
  42. package/payload/platform/plugins/email/mcp/dist/__tests__/email-status.test.d.ts +2 -0
  43. package/payload/platform/plugins/email/mcp/dist/__tests__/email-status.test.d.ts.map +1 -0
  44. package/payload/platform/plugins/email/mcp/dist/__tests__/email-status.test.js +58 -0
  45. package/payload/platform/plugins/email/mcp/dist/__tests__/email-status.test.js.map +1 -0
  46. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js +94 -9
  47. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js.map +1 -1
  48. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js +109 -1
  49. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js.map +1 -1
  50. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js +4 -0
  51. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js.map +1 -1
  52. package/payload/platform/plugins/email/mcp/dist/index.js +39 -2
  53. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  54. package/payload/platform/plugins/email/mcp/dist/lib/compose.d.ts +5 -0
  55. package/payload/platform/plugins/email/mcp/dist/lib/compose.d.ts.map +1 -1
  56. package/payload/platform/plugins/email/mcp/dist/lib/compose.js +8 -1
  57. package/payload/platform/plugins/email/mcp/dist/lib/compose.js.map +1 -1
  58. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +13 -0
  59. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
  60. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +35 -0
  61. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
  62. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +83 -30
  63. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
  64. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +327 -112
  65. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
  66. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts +19 -0
  67. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts.map +1 -1
  68. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js +33 -0
  69. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js.map +1 -1
  70. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +6 -0
  71. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -1
  72. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +4 -0
  73. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -1
  74. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.d.ts +8 -1
  75. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.d.ts.map +1 -1
  76. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.js +10 -6
  77. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.js.map +1 -1
  78. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts.map +1 -1
  79. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js +4 -2
  80. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js.map +1 -1
  81. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-body.d.ts +15 -0
  82. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-body.d.ts.map +1 -0
  83. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-body.js +29 -0
  84. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch-body.js.map +1 -0
  85. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
  86. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +11 -1
  87. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
  88. package/payload/platform/plugins/email/mcp/dist/tools/email-status.d.ts.map +1 -1
  89. package/payload/platform/plugins/email/mcp/dist/tools/email-status.js +24 -1
  90. package/payload/platform/plugins/email/mcp/dist/tools/email-status.js.map +1 -1
  91. package/payload/platform/plugins/email/mcp/package.json +2 -0
  92. package/payload/platform/plugins/email/references/email-reference.md +30 -3
  93. package/payload/platform/scripts/rss-sampler.sh +21 -0
  94. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  95. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  96. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  97. package/payload/platform/services/claude-session-manager/dist/connector-auth.d.ts +31 -0
  98. package/payload/platform/services/claude-session-manager/dist/connector-auth.d.ts.map +1 -0
  99. package/payload/platform/services/claude-session-manager/dist/connector-auth.js +49 -0
  100. package/payload/platform/services/claude-session-manager/dist/connector-auth.js.map +1 -0
  101. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +24 -0
  102. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  103. package/payload/platform/services/claude-session-manager/dist/http-server.js +214 -17
  104. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  105. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +13 -5
  106. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  107. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +46 -11
  108. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  109. package/payload/platform/services/webchat-channel/dist/instructions.d.ts +1 -0
  110. package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
  111. package/payload/platform/services/webchat-channel/dist/instructions.js +28 -0
  112. package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
  113. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  114. package/payload/platform/services/webchat-channel/dist/server.js +75 -5
  115. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  116. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  117. package/payload/server/public/assets/{AdminLoginScreens-BW1UgfoI.js → AdminLoginScreens-tHyAPNnQ.js} +1 -1
  118. package/payload/server/public/assets/AdminShell-Ce9izNVZ.js +1 -0
  119. package/payload/server/public/assets/{Checkbox-O1qvMk_u.js → Checkbox-Cq6SJJlX.js} +1 -1
  120. package/payload/server/public/assets/OperatorConversations-BERW_hUa.css +1 -0
  121. package/payload/server/public/assets/OperatorConversations-m2lz6Ss7.js +9 -0
  122. package/payload/server/public/assets/admin-D9iMgdbN.js +1 -0
  123. package/payload/server/public/assets/{arc-DpkSQNto.js → arc-Crkz45LN.js} +1 -1
  124. package/payload/server/public/assets/architecture-YZFGNWBL-Dma4Bgha.js +1 -0
  125. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Bw7Yq8O9.js → architectureDiagram-Q4EWVU46-C9JThHgP.js} +1 -1
  126. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BBtJQFSz.js → blockDiagram-DXYQGD6D-DpsV_HXT.js} +1 -1
  127. package/payload/server/public/assets/{browser-CySvj140.js → browser-CZWi0EAP.js} +1 -1
  128. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-JAMgxzOr.js → c4Diagram-AHTNJAMY-CTm_6aKi.js} +1 -1
  129. package/payload/server/public/assets/calendar-DUAh-_kx.js +1 -0
  130. package/payload/server/public/assets/channel-B_-5bau1.js +1 -0
  131. package/payload/server/public/assets/chat-DHuibPfc.js +1 -0
  132. package/payload/server/public/assets/{chunk-2KRD3SAO-eDugsc2L.js → chunk-2KRD3SAO-1KSJW1q6.js} +1 -1
  133. package/payload/server/public/assets/{chunk-336JU56O-BXfECwdC.js → chunk-336JU56O-C3t08Ip-.js} +2 -2
  134. package/payload/server/public/assets/chunk-426QAEUC-Dirxdwjh.js +1 -0
  135. package/payload/server/public/assets/{chunk-4BX2VUAB-CByVeKCY.js → chunk-4BX2VUAB-kl1ze33n.js} +1 -1
  136. package/payload/server/public/assets/{chunk-4TB4RGXK-CpY0DcUB.js → chunk-4TB4RGXK-DxpoDoHg.js} +1 -1
  137. package/payload/server/public/assets/{chunk-55IACEB6-C3YxgyIb.js → chunk-55IACEB6-WM9VJzha.js} +1 -1
  138. package/payload/server/public/assets/{chunk-5FUZZQ4R-Bc0d7j8A.js → chunk-5FUZZQ4R-CLH63ZH3.js} +1 -1
  139. package/payload/server/public/assets/{chunk-5PVQY5BW-CTUGMRIa.js → chunk-5PVQY5BW-DCTb8IAT.js} +1 -1
  140. package/payload/server/public/assets/{chunk-67CJDMHE-CbdPnpLd.js → chunk-67CJDMHE-BSYzyaoH.js} +1 -1
  141. package/payload/server/public/assets/{chunk-7N4EOEYR-Cjl2kevz.js → chunk-7N4EOEYR-CarJ7O2P.js} +1 -1
  142. package/payload/server/public/assets/{chunk-AA7GKIK3-BgozIh5p.js → chunk-AA7GKIK3-DTNLyBpH.js} +1 -1
  143. package/payload/server/public/assets/{chunk-BSJP7CBP-6Ufq45NW.js → chunk-BSJP7CBP-BFmHflHY.js} +1 -1
  144. package/payload/server/public/assets/{chunk-CIAEETIT-BhhYuMnA.js → chunk-CIAEETIT-BpjG0IzU.js} +1 -1
  145. package/payload/server/public/assets/{chunk-EDXVE4YY-BfaJ3yDD.js → chunk-EDXVE4YY-2fSowhlW.js} +1 -1
  146. package/payload/server/public/assets/{chunk-ENJZ2VHE-C7-hIGVC.js → chunk-ENJZ2VHE-ClcranGV.js} +1 -1
  147. package/payload/server/public/assets/{chunk-FMBD7UC4-BQvvyocF.js → chunk-FMBD7UC4-DLq4BItQ.js} +1 -1
  148. package/payload/server/public/assets/{chunk-FOC6F5B3-C6rBDOxH.js → chunk-FOC6F5B3-B9QI3Guz.js} +1 -1
  149. package/payload/server/public/assets/{chunk-ICPOFSXX-BjOJvkVa.js → chunk-ICPOFSXX-BAr-Mv1Z.js} +2 -2
  150. package/payload/server/public/assets/{chunk-K5T4RW27-kKowRHhn.js → chunk-K5T4RW27-8PvAHasY.js} +1 -1
  151. package/payload/server/public/assets/{chunk-KGLVRYIC-bAEV_5eH.js → chunk-KGLVRYIC--aGaDRH5.js} +1 -1
  152. package/payload/server/public/assets/{chunk-LIHQZDEY-BLvsQAfg.js → chunk-LIHQZDEY-BrWj7mw2.js} +1 -1
  153. package/payload/server/public/assets/{chunk-ORNJ4GCN-BzYZfPZ7.js → chunk-ORNJ4GCN-kYQmkMTi.js} +1 -1
  154. package/payload/server/public/assets/{chunk-OYMX7WX6-CL7WRw42.js → chunk-OYMX7WX6-CIsryCWH.js} +1 -1
  155. package/payload/server/public/assets/chunk-QZHKN3VN-Duipo1kI.js +1 -0
  156. package/payload/server/public/assets/{chunk-U2HBQHQK-BdcVGjau.js → chunk-U2HBQHQK-68X653e3.js} +1 -1
  157. package/payload/server/public/assets/{chunk-X2U36JSP-C0CL_Jin.js → chunk-X2U36JSP-v3v9soX3.js} +1 -1
  158. package/payload/server/public/assets/{chunk-XPW4576I-CsV7CUxH.js → chunk-XPW4576I-CW5DPpop.js} +1 -1
  159. package/payload/server/public/assets/{chunk-YZCP3GAM-Cj0_fLkR.js → chunk-YZCP3GAM-B1VP7Rl2.js} +1 -1
  160. package/payload/server/public/assets/{chunk-ZZ45TVLE-DLuquyoY.js → chunk-ZZ45TVLE-DiJrujNY.js} +1 -1
  161. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B3kX5SuB.js +1 -0
  162. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D761c7Lr.js +1 -0
  163. package/payload/server/public/assets/clone-BrhFv6Tb.js +1 -0
  164. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-BU3EOLXX.js → cose-bilkent-S5V4N54A-BscXxLMc.js} +1 -1
  165. package/payload/server/public/assets/{dagre-KV5264BT-CoCAYhFc.js → dagre-KV5264BT-DVgGlTQ1.js} +1 -1
  166. package/payload/server/public/assets/{dagre-BRq8C9NU.js → dagre-MBv6WlCS.js} +1 -1
  167. package/payload/server/public/assets/data-CoOcAR_2.js +1 -0
  168. package/payload/server/public/assets/{diagram-5BDNPKRD-DBy5GNaQ.js → diagram-5BDNPKRD-BmhCaO0a.js} +1 -1
  169. package/payload/server/public/assets/{diagram-G4DWMVQ6-l93MsBLv.js → diagram-G4DWMVQ6-ChU9L8vz.js} +1 -1
  170. package/payload/server/public/assets/{diagram-MMDJMWI5-BIfXkVlL.js → diagram-MMDJMWI5-Oy409Zc_.js} +1 -1
  171. package/payload/server/public/assets/{diagram-TYMM5635-BuTJLBny.js → diagram-TYMM5635-Cn1YByqk.js} +1 -1
  172. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BwPxWDbP.js → erDiagram-SMLLAGMA-e17yfLvr.js} +1 -1
  173. package/payload/server/public/assets/{flatten-DtM0XAMt.js → flatten-Cl1Bc3dR.js} +1 -1
  174. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BhPtHXMR.js → flowDiagram-DWJPFMVM-Dqt7sCVZ.js} +1 -1
  175. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BlXjprdD.js → ganttDiagram-T4ZO3ILL-B4IhwS2r.js} +1 -1
  176. package/payload/server/public/assets/gitGraph-7Q5UKJZL-BCQAqtLy.js +1 -0
  177. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BW36BDiu.js → gitGraphDiagram-UUTBAWPF-BDw-PKcI.js} +1 -1
  178. package/payload/server/public/assets/{graph-uFhGyOZR.js → graph-Dc_votDd.js} +3 -3
  179. package/payload/server/public/assets/{graph-labels-BNnhRQqM.js → graph-labels-jqagxwhW.js} +1 -1
  180. package/payload/server/public/assets/{graphlib-Bjg3Tq-k.js → graphlib-DPIYk_sg.js} +1 -1
  181. package/payload/server/public/assets/info-OMHHGYJF-qU7hK50T.js +1 -0
  182. package/payload/server/public/assets/infoDiagram-42DDH7IO-KGdcJeTs.js +2 -0
  183. package/payload/server/public/assets/{isEmpty-D__iH1WQ.js → isEmpty-D1pGOD1J.js} +1 -1
  184. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CmB-bA_O.js → ishikawaDiagram-UXIWVN3A-BRIHsB3G.js} +1 -1
  185. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-Bt1fJKmc.js → journeyDiagram-VCZTEJTY-aKNgmoHd.js} +1 -1
  186. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DVbksz_J.js → kanban-definition-6JOO6SKY-cwBwT-nm.js} +1 -1
  187. package/payload/server/public/assets/{line-BX2Ugx3B.js → line-DVtVRzUA.js} +1 -1
  188. package/payload/server/public/assets/{linear-Bdc-QJWI.js → linear-DtoOFPO2.js} +1 -1
  189. package/payload/server/public/assets/{mermaid-parser.core-qv1e-J5x.js → mermaid-parser.core-G7YD_zO3.js} +2 -2
  190. package/payload/server/public/assets/{mermaid.core-C_d9YQX_.js → mermaid.core-DpFyndHm.js} +3 -3
  191. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DwKGvF14.js → mindmap-definition-QFDTVHPH-CYXK_Pvz.js} +1 -1
  192. package/payload/server/public/assets/operator-KYXcuQ4Y.js +1 -0
  193. package/payload/server/public/assets/{ordinal-BRQ5CzZY.js → ordinal-CBZeH4Yp.js} +1 -1
  194. package/payload/server/public/assets/packet-4T2RLAQJ-DiU2yS9m.js +1 -0
  195. package/payload/server/public/assets/page-Cfsv97nq.js +32 -0
  196. package/payload/server/public/assets/pie-ZZUOXDRM-zHUKKlVv.js +1 -0
  197. package/payload/server/public/assets/{pieDiagram-DEJITSTG-dUvQC_4S.js → pieDiagram-DEJITSTG-DFo4N6WH.js} +1 -1
  198. package/payload/server/public/assets/{public-DgltXhnD.js → public-49guEjCh.js} +1 -1
  199. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CebX_oPa.js → quadrantDiagram-34T5L4WZ-BlH5iIhl.js} +1 -1
  200. package/payload/server/public/assets/radar-PYXPWWZC-BUnVoaPg.js +1 -0
  201. package/payload/server/public/assets/{reduce-CkcXOmmJ.js → reduce-PuPlFPRX.js} +1 -1
  202. package/payload/server/public/assets/{requirementDiagram-MS252O5E-h2euIqGj.js → requirementDiagram-MS252O5E-D5WLty8A.js} +1 -1
  203. package/payload/server/public/assets/rotate-ccw-CyR5o3Nq.js +1 -0
  204. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DCii3fkF.js → sankeyDiagram-XADWPNL6-vB85IxHG.js} +1 -1
  205. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-CQSGYmlq.js → sequenceDiagram-FGHM5R23-Cxraa0Ee.js} +1 -1
  206. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CVtU0iXH.js → stateDiagram-FHFEXIEX-BBPssYBx.js} +1 -1
  207. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BWmmUwDt.js +1 -0
  208. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-ChvsBltI.js → timeline-definition-GMOUNBTQ-Bgk6PT62.js} +1 -1
  209. package/payload/server/public/assets/treeView-SZITEDCU-C3Y-Q52h.js +1 -0
  210. package/payload/server/public/assets/treemap-W4RFUUIX-Dk0qZpAg.js +1 -0
  211. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-e-EZiiba.js → vennDiagram-DHZGUBPP-B-APTs3L.js} +1 -1
  212. package/payload/server/public/assets/wardley-RL74JXVD-BAWI02OA.js +1 -0
  213. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-4JaRn1s5.js → wardleyDiagram-NUSXRM2D-CkXJSs_i.js} +1 -1
  214. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-kxwmCNuM.js → xychartDiagram-5P7HB3ND-BkyshPMV.js} +1 -1
  215. package/payload/server/public/browser.html +4 -4
  216. package/payload/server/public/calendar.html +4 -4
  217. package/payload/server/public/chat.html +7 -6
  218. package/payload/server/public/data.html +4 -4
  219. package/payload/server/public/graph.html +7 -6
  220. package/payload/server/public/index.html +6 -6
  221. package/payload/server/public/operator.html +9 -8
  222. package/payload/server/public/public.html +7 -6
  223. package/payload/server/server.js +244 -24
  224. package/payload/server/public/assets/AdminShell-CDQDkT1R.js +0 -1
  225. package/payload/server/public/assets/OperatorConversations-CVH-FoJo.css +0 -1
  226. package/payload/server/public/assets/OperatorConversations-jqaPCHwB.js +0 -9
  227. package/payload/server/public/assets/admin-BkYc54bi.js +0 -1
  228. package/payload/server/public/assets/architecture-YZFGNWBL-Csj53u5T.js +0 -1
  229. package/payload/server/public/assets/calendar-DgP7lal2.js +0 -1
  230. package/payload/server/public/assets/channel-BUQUAUts.js +0 -1
  231. package/payload/server/public/assets/chat-gls5aV50.js +0 -1
  232. package/payload/server/public/assets/chunk-426QAEUC-CdknReB2.js +0 -1
  233. package/payload/server/public/assets/chunk-QZHKN3VN-8tHoEDE9.js +0 -1
  234. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BEGZ3DLg.js +0 -1
  235. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DsLxnm5U.js +0 -1
  236. package/payload/server/public/assets/clone-uiXbH_kh.js +0 -1
  237. package/payload/server/public/assets/data-CbI8-CX3.js +0 -1
  238. package/payload/server/public/assets/gitGraph-7Q5UKJZL-D_2KrZoP.js +0 -1
  239. package/payload/server/public/assets/info-OMHHGYJF-BP2TNwQ4.js +0 -1
  240. package/payload/server/public/assets/infoDiagram-42DDH7IO-D1kDtBOY.js +0 -2
  241. package/payload/server/public/assets/operator-DeCk_qYw.js +0 -1
  242. package/payload/server/public/assets/packet-4T2RLAQJ-BDg8fde8.js +0 -1
  243. package/payload/server/public/assets/page-jGwq-DpW.js +0 -32
  244. package/payload/server/public/assets/pie-ZZUOXDRM-CXDyYMkZ.js +0 -1
  245. package/payload/server/public/assets/radar-PYXPWWZC-xen_zv8F.js +0 -1
  246. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BywcXjtb.js +0 -1
  247. package/payload/server/public/assets/treeView-SZITEDCU-2FBf_1It.js +0 -1
  248. package/payload/server/public/assets/treemap-W4RFUUIX-BDdb30P-.js +0 -1
  249. package/payload/server/public/assets/wardley-RL74JXVD-BLq5MxjR.js +0 -1
  250. /package/payload/server/public/assets/{_baseFor-SRtUHe7G.js → _baseFor-brRjpUOX.js} +0 -0
  251. /package/payload/server/public/assets/{array-BpsnM-Py.js → array-BGFCBI0e.js} +0 -0
  252. /package/payload/server/public/assets/{cytoscape.esm-D4Rl1H5h.js → cytoscape.esm-TvRJ2tGX.js} +0 -0
  253. /package/payload/server/public/assets/{defaultLocale-C7sQPl-O.js → defaultLocale-CRZydyG6.js} +0 -0
  254. /package/payload/server/public/assets/{dist-CtUNt3w8.js → dist-B0CkUodR.js} +0 -0
  255. /package/payload/server/public/assets/{init-BydxaDEV.js → init-B8gtcn7T.js} +0 -0
  256. /package/payload/server/public/assets/{katex-B0fVeDx4.js → katex-RxgSu_dy.js} +0 -0
  257. /package/payload/server/public/assets/{path-jlWYQ2i9.js → path-DZF-JdEe.js} +0 -0
  258. /package/payload/server/public/assets/{preload-helper-uTix4PVD.js → preload-helper-CQ36nxok.js} +0 -0
  259. /package/payload/server/public/assets/{rough.esm-c4PR5shF.js → rough.esm-6CnTHTkH.js} +0 -0
  260. /package/payload/server/public/assets/{src-48kCpScq.js → src-CR_MU8uy.js} +0 -0
@@ -154,6 +154,8 @@ CLOUDFLARE_API_TOKEN="${PAGES_D1}" wrangler pages deploy ./dist --project-name <
154
154
 
155
155
  No `expires_on`: the per-scope token is permanent and reused, so decay is the job of the **reconcile pass** (§ Reconcile), not a per-token TTL — the old short-TTL guidance was never honored in practice and produced only never-expiring strays. Look up `<pages-edit-permission-group-id>` (and the ids for DNS Edit, D1 Edit, etc.) once via `GET /accounts/{account_id}/tokens/permission_groups`; they are stable per account. Before reusing or before reconciling, `GET …/tokens` (§ Curated endpoint map) shows what already exists, so a scope is never minted twice under different names.
156
156
 
157
+ **Per-scope token resources.** Each reused per-scope token carries the resource that matches its operation class. The Pages-and-D1 token (`<brand>-pages-d1`) and the Access token (`<brand>-access`) are account-scoped: `"resources": { "com.cloudflare.api.account.${CLOUDFLARE_ACCOUNT_ID}": "*" }`. The DNS token (`<brand>-dns`) is zone-scoped, but since it is a single stable token reused across every zone the install routes, its resource covers the account's zones: `"resources": { "com.cloudflare.api.account.zone.*": "*" }`. A per-zone DNS token would defeat the one-stable-token-per-scope model (one token, reused, not one per zone); the minted token is still strictly narrower than the master, which already carries Zone DNS Edit over the zones in scope.
158
+
157
159
  **Redaction is binding.** Every example above pipes the token into a variable or an `Authorization` header and never to stdout. The agent surfaces the operation as verb + target — "minting a Pages-deploy token", "creating CNAME `chat.example.com`" — never the secret. A failure surfaces the API error body with any `Authorization` value masked.
158
160
 
159
161
  ### A freshly-minted token is not instantly usable — verify with backoff
@@ -27,6 +27,20 @@ This is the entry point for every Cloudflare task on the install. Pick the opera
27
27
 
28
28
  Neither the master token nor any per-scope token is ever written into a project tree, committed, or echoed into chat — the per-scope tokens persist only in the account-scoped secrets file, never in a deployable project tree.
29
29
 
30
+ ### Token operations: run the helper first (binding)
31
+
32
+ Before **any** Cloudflare API token operation (verify, list, mint, reuse), resolve the per-scope token with the deterministic helper, never a hand-built `curl`:
33
+
34
+ ```bash
35
+ KEY=$(bash platform/plugins/cloudflare/bin/cf-token.sh <scope> <secrets-file>) # scope: pages | d1 | dns | access
36
+ set -a; . <secrets-file>; set +a
37
+ # the active, persisted per-scope token is now in the variable named by $KEY
38
+ ```
39
+
40
+ The helper owns the one decision the false-negative failure turns on: it reads the master's `cfat_`/`cfut_` prefix and routes verify, `permission_groups`, and mint to the matching endpoint family, mints once if absent (no expiry), verifies through the transient post-mint window, persists to the secrets file, and prints only the secrets key name. It never prints a token value.
41
+
42
+ A raw `curl` to a token endpoint chosen **before** the master's prefix is established is out of bounds. The wrong endpoint returns a stable false-negative that reads as "cannot mint" but is not: a `cfat_` master at `/user/tokens/verify` returns `Invalid API Token`, and a `cfut_` master at any `/accounts/{id}/...` endpoint returns `9109`. If you see either from a token probe, the cause is the endpoint, not the token. Stop and run the helper. Doing the verify or mint by hand is permitted only after reading the `references/api.md` section on routing token endpoints by prefix, and routing by the established prefix.
43
+
30
44
  ## Outcome contracts — what "done" means
31
45
 
32
46
  Every Cloudflare operation proves itself with a live behavioural signal surfaced verbatim in chat:
@@ -33,7 +33,16 @@ There is never a `sites/<brand>/` versus `output/<brand>-site/` pair, a `.bak` c
33
33
 
34
34
  ## Auth: reuse the per-scope token, never mint ad hoc
35
35
 
36
- A Pages deploy needs **Account · Cloudflare Pages · Edit**. A site with a D1-backed form also needs **Account · D1 · Edit** on the same token. Load the stable `<brand>-pages-d1` token from the account secrets file, minting it once only if absent and persisting it, exactly as `references/api.md` § Provisioning and reusing a stable per-scope token and `references/d1-data-capture.md` § 0 prescribe. The token is never written into the project tree, never committed, never echoed into chat. The master token stays in the secrets file. Surface every command as verb plus target ("deploying Pages project `<project>`"); `wrangler` prints the deployment URL, which is what gets relayed.
36
+ Resolve the Pages-and-D1 token with the deterministic helper **before** any token `curl`, never a hand-built one:
37
+
38
+ ```bash
39
+ KEY=$(bash platform/plugins/cloudflare/bin/cf-token.sh pages <secrets-file>)
40
+ set -a; . <secrets-file>; set +a # the active token is now in the variable named by $KEY
41
+ ```
42
+
43
+ The helper reads the master's `cfat_`/`cfut_` prefix and routes verify, `permission_groups`, and mint to the matching endpoint family, mints once if absent (no expiry), persists, and prints only the secrets key name. A hand-built verify at the wrong endpoint returns a false-negative (`Invalid API Token` or `9109`) that reads as "cannot mint" but is not; when that happens the cause is the endpoint, not the token. See the `references/api.md` section on routing token endpoints by prefix.
44
+
45
+ A Pages deploy needs **Account · Cloudflare Pages · Edit**. A site with a D1-backed form also needs **Account · D1 · Edit** on the same token. The helper resolves the stable `<brand>-pages-d1` token (carrying both) from the account secrets file, minting it once only if absent and persisting it, exactly as `references/api.md` § Provisioning and reusing a stable per-scope token and `references/d1-data-capture.md` § 0 prescribe. The token is never written into the project tree, never committed, never echoed into chat. The master token stays in the secrets file. Surface every command as verb plus target ("deploying Pages project `<project>`"); `wrangler` prints the deployment URL, which is what gets relayed.
37
46
 
38
47
  ## Deploy and attach the custom domain
39
48
 
@@ -37,6 +37,7 @@ Load these when performing admin tasks or diagnosing platform behaviour:
37
37
  - **Admin UI** → `references/admin-ui.md` — compact map of every `/api/admin/*` mount, every sidebar surface, the system-stats widget (CPU/RAM thresholds), the artefact pane, and the health-vs-version split. Load when diagnosing an admin route, explaining the CPU/RAM widget, or onboarding a new admin endpoint.
38
38
  - **Admin session** → `references/admin-session.md` — signed sessionKey + PIN-rebind survival contract, SDK-resume across `systemctl restart`, and the single-entry `POST /api/admin/claude-sessions` wrapper that owns every programmatic admin spawn-with-initialMessage. Load when diagnosing admin session continuity, designing a programmatic admin spawn.
39
39
  - **Cloudflare** → `references/cloudflare.md` — dashboard-first tunnel setup, the `cloudflared`-CLI-only tool surface, single-recovery-path (re-login) for every wrong-account failure.
40
+ - **claude.ai connectors** → `references/claudeai-connectors.md` — why a connector added on claude.ai can still need authentication (per-client, not per-account), and the in-chat authenticate path (the agent issues a link, the operator approves on claude.ai, the session reconnects). Separate from the Maxy connector plugin.
40
41
  - **Deployment** → `references/deployment.md` — Pi setup, Cloudflare tunnel, start script
41
42
 
42
43
  ## References
@@ -56,4 +57,5 @@ Load these when performing admin tasks or diagnosing platform behaviour:
56
57
  - references/admin-ui.md
57
58
  - references/admin-session.md
58
59
  - references/cloudflare.md
60
+ - references/claudeai-connectors.md
59
61
  - references/deployment.md
@@ -67,6 +67,8 @@ either is a regression.
67
67
 
68
68
  **`/chat` empty-state greeting panel.** While the admin webchat has no conversation JSONL yet (`GET /api/webchat/session` → `projectDir:null`), `app/chat/page.tsx` renders a "What's up next, {givenName}?" greeting (given name = first whitespace token of the admin session's `userName`) above two read-only lists from `GET /api/webchat/greeting` (`server/routes/webchat-greeting.ts`, `requireAdminSession`-gated, `accountId`-scoped): the next 5 upcoming `:Event` rows (`eventStatus IN ['scheduled','due']`, future `COALESCE(nextRun, startDate)`, soonest first) and the outstanding `:Task` rows (`status IN ['pending','active','running']`, 5 shown + `+N more`). Read failure returns HTTP 200 `{ ok: false }` and the page shows the headline alone — the panel never blocks the composer. A third section, **Your specialists**, shows the account's installed roster — every `*.md` under `data/accounts/<accountId>/specialists/agents/`, core and `--`-prefixed premium files alike — shown by frontmatter `name` + `summary` (fallback `description`), empty dir → "No specialists installed". The roster read (`app/lib/claude-agent/specialist-roster.ts`) is isolated from the graph fallback: malformed files are skipped (`op=specialist-skipped file=<name> reason=<…>`), a whole-roster failure degrades to `specialists: []` inside the `ok: true` payload (`op=specialists-read-failed`). Logs: `[webchat:greeting] op=read account=<id8> events=<n> tasks=<n> specialists=<n> ms=<n>` / `op=read-failed reason=…`; client warns `[admin-ui] greeting-unavailable …`. The full webchat architecture lives in `.docs/admin-webchat-native-channel.md`.
69
69
 
70
+ **`/chat` Conversations flyout + zero-sessions splash.** The admin `/chat` `HeaderMenu` carries a **Conversations** item (rendered only when `onOpenConversations` is wired, which scopes it to `/chat`) that opens an in-chat session-management pane (`app/chat/SessionList.tsx`) hosted by `chat/page.tsx` — distinct from, and sharing endpoints with, the `Sidebar` Sessions list (which stays hidden on narrow viewports). It enumerates the admin's own webchat sessions via `GET /api/admin/sidebar-sessions` (carries the per-row `live` marker and `archived` flag, install-wide), lists them newest-first with the live one marked and archived rows folded under a collapsible subsection, and offers per-row resume (`/chat?session=<id>`), rename, archive/unarchive, two-tap delete, an **End** control on the live row (`session-stop`), plus a New-session control (`session-rc-spawn`) and a copyable full id. When the canonical pointer is `known:false` (`canonical-empty`) and enumeration returns zero rows, the surface renders a splash (brand logo + New session) instead of a dead bootstrap thread; a freshly-spawned New session is `known:true`, so its greeting is preserved. Client breadcrumbs: `[chat-conversations] op=enumerate owned=<n>` and `op=action name=<open|rename|archive|delete|stop> sessionId=<id8>` (`op=action-failed … status=…` on a non-2xx). Detail lives in `.docs/admin-webchat-native-channel.md` ("Conversations flyout + zero-sessions splash").
71
+
70
72
  **`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp reader (`/whatsapp`) omits the prop and keeps the default `renderTimeline`, so its rendering is unchanged; both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx`, `app/chat/__tests__/transcript-render.test.tsx`). **Day-divider:** both renderers insert a centered `.day-divider` row between two consecutive timeline items on different local calendar days (label `Today`/`Yesterday`, else `Sat 14 Jun 2026`), so a thread spanning midnight is never an ambiguous run of HH:MM; the first dated item gets a leading divider, a null/unparseable `ts` marks no boundary, dividers are computed over the filtered `visibleItems`, and in `/chat` a day crossover flushes any open tool/think run first so a collapsed run never spans it. Per-bubble HH:MM stamps are unchanged. Shared helpers `dayKey`/`dayLabel`/`itemTs`/`DayDivider` live in `app/whatsapp/Transcript.tsx`.
71
73
 
72
74
  **`/chat` live activity line.** While a turn is in flight the transcript tail shows one ephemeral `ChatActivity` line (mounted only while `busy`, admin/operator only). It tracks real activity, not a timer: while a `Task` subagent runs it shows that subagent's headline (`agentType · description`, prefixed `N agents ·` when ≥2 are concurrent), sourced from `agent-<hex>.meta.json` via named `activity` SSE events the admin reader pushes from the session's `subagents/` dir; with no subagent active it shows a neutral word that advances only on a real turn arrival. The line carries a turn-elapsed clock and flips to a `stalled` state once nothing has been written for 5 minutes (`now − lastEmitAt`), so the operator can tell a wedge from progress without SSH. It is never added to the persisted timeline. Detail and the `[webchat-activity]` observability live in [`admin-webchat-native-channel.md`](../../../.docs/admin-webchat-native-channel.md).
@@ -0,0 +1,45 @@
1
+ # claude.ai connectors
2
+
3
+ claude.ai connectors (Zoom, Dropbox, GitHub, Google Calendar, and the rest you add on claude.ai) work
4
+ inside your admin chat once they are authorised for this Maxy client. This page explains why a
5
+ connector you already added can still say it needs authentication, and how to fix it without leaving
6
+ the chat.
7
+
8
+ ## Asking for a connector by name
9
+
10
+ You can ask the agent to use a connector you added on claude.ai by name — "can we connect my Zoom
11
+ account?", "save this to Dropbox", "check my Microsoft 365 calendar". The agent knows which connectors
12
+ are loaded for this client and whether each one is ready or still needs the one-off authentication
13
+ below, so it will reach for the connector rather than telling you it has no such integration. If a
14
+ connector you added is not yet authenticated for this client, the agent offers you the authentication
15
+ step straight away instead of dead-ending.
16
+
17
+ ## Why a connector can still need authentication
18
+
19
+ A claude.ai connector is authorised per client, not per account. Approving a connector in the
20
+ claude.ai web app authorises the web app only. Your Maxy admin chat is a separate client, so the first
21
+ time it uses a connector that client has to be authorised too. This is a one-off step per connector.
22
+
23
+ That is why some connectors work straight away while a newly added one does not. A connector you used
24
+ before was already authorised for this client; a brand new one has only been approved in the web app.
25
+
26
+ ## How to authenticate one from the chat
27
+
28
+ When the agent tries a connector that has not been authorised for this client, it will tell you the
29
+ connector needs authentication and hand you a link. You do not need a terminal and you do not need to
30
+ run anything yourself.
31
+
32
+ 1. The agent gives you an authorisation link.
33
+ 2. Open the link and approve the connector on claude.ai (sign in with the same account you use for
34
+ your connectors).
35
+ 3. Tell the agent you have approved it.
36
+ 4. The agent reconnects your chat session. Send your next message and the connector is ready to use.
37
+
38
+ If a connector still reports that it needs authentication after you have approved it and the session
39
+ has reconnected, that is unexpected. Tell your installer so they can look into it.
40
+
41
+ ## What this is not
42
+
43
+ This is about Anthropic's claude.ai connectors, which authenticate per client. It is separate from the
44
+ Maxy connector plugin, which registers ordinary REST APIs with credentials Maxy holds. The two are
45
+ unrelated.
@@ -93,6 +93,12 @@ The most common cause is wrong nameservers on the domain. The domain must use Cl
93
93
  - 5 failed login attempts → 15-minute lockout — wait for expiry.
94
94
  - The remote password is set during Cloudflare Tunnel onboarding — the agent asks for one in chat and stores it deterministically. The browser form at `/__remote-auth/setup` remains available for resets on the local network.
95
95
 
96
+ ### Large `/data` upload fails with a connection error
97
+
98
+ - Cloudflare proxies a request body of at most ~100 MB on the current plan. A single upload larger than that is cut at the edge before it reaches the server, so the browser sees a connection error rather than a clean size rejection.
99
+ - The `/data` page handles this itself: files over 95 MB are split into ~48 MB parts and sent one at a time under the cap, and the server reassembles them. No plan change or dashboard action is needed for uploads up to the 2 GB app ceiling.
100
+ - Raising the proxied body limit is a paid-plan change made on the Cloudflare dashboard, not something the agent does.
101
+
96
102
  ## What the agent does and does not do
97
103
 
98
104
  **Does:** invokes `cloudflared` directly via Bash, following `plugins/cloudflare/references/manual-setup.md` step by step; quotes click-paths from the reference files verbatim; verifies external reachability with `curl -I` and surfaces the response.
@@ -125,6 +125,8 @@ tail -200 ~/.maxy/logs/maxy-ui.log | rg '\[remote-auth\].*resolvedKind='
125
125
 
126
126
  **If a background task goes silent and the chat shows "A background task went silent — K of M completed":** {{productName}}'s subagent stopped emitting progress for over 2 minutes. Tap "Continue" — the next turn resumes the prior session and reads a synthetic tool_result describing what completed before the pause, so the agent re-plans without losing the work it had done. Most stalls are upstream API latency rather than the subagent's approach failing — the resume-first path treats both correctly. Greppable post-deploy invariants: `[stall-recovery] kind=subagent_stalled … completed=<K>/? handoff=resume-first` followed by `[stall-resume] consumed kind=subagent_stalled toolUseId=<8>` on the next turn. If the button reads "Start over" instead, the parent's pending tool_use_id was not captured — the fallback path took over; the prior conversation is preserved as a `<recovery-context>` block in the cold-started session.
127
127
 
128
+ **The stop button is stuck and the spinner never clears.** If the chat shows a stop button and a working spinner that never resolves, and the session dot is grey (not live), the agent process for that session was killed mid-turn (most often the device ran low on memory). There is no live turn to interrupt, so the old behaviour left you stranded. Now it self-heals: within a few seconds the spinner clears on its own and the composer shows "The agent stopped. Send a message to resume." Pressing stop clears it immediately. Either way, just send your next message — the session resumes from where it left off. Greppable post-deploy invariants: the manager logs `[rc-life] op=turn-aborted reason=child-exit-mid-turn` on the death and `[webchat-interrupt] op=dead-child-recovered` if you press stop; the browser console logs `[admin-ui] op=phantom-turn-cleared` (self-heal) or `[admin-ui] op=stop-dead-child` (stop press). If a session keeps dying mid-turn, the device is memory-constrained — that is a capacity concern, separate from this recovery.
129
+
128
130
  **Agent searches the filesystem after uploading a zip.** If you uploaded a zip and the agent burns several turns running `find` / `Glob` instead of unzipping, that is the symptom of the recovery-retry attachment-context regression (now closed by the recovery context preservation contract in `.docs/agents.md`). Greppable confirmation is the `[context-overflow-recovery] retry … attachmentsCarried=<n>` line in the conversation stream log. If you see `[context-overflow-recovery] WARN attachment-context-lost`, the regression has returned — surface to support.
129
131
 
130
132
  **Turn budget exhausted with a horizontal rule separating two assistant turns.** When {{productName}} reaches its turn budget and the doubled retry also runs out, the chat now shows a one-paragraph assistant message that opens with `error_max_turns turns=A→B` (initial budget → final budget) followed by the recovery copy: "I reached my turn budget of N before I could finish this request. Try sending a smaller or more focused request, or ask me to use higher effort." That message is persisted to the graph, so the next page-refresh still shows it. The thin horizontal rule labelled "Session restored after timeout." that appears above your following turn signals that the prior turn forced a cold SDK-session restart inside the same conversation (pool eviction) — the agent's response after the rule is from a fresh SDK session even though the conversation thread is unchanged. Greppable post-deploy invariants: `[context-overflow-recovery] exhausted cause=max-turns-interrupted` count equals `[admin-persist] writer=persistMessageExhaust outcome=ok` count for the same sessionId window, and one `[session-store] storeAgentSessionId` line marks the cold-restart that drove the on-screen rule.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "email",
3
- "description": "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :ConversationArchive {source:'email'} with :Section chunks (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox (with best-effort per-archive section hints from the graph). Ingestion (operator-initiated, human-in-the-loop): email-fetch lists new messages, email-ingest writes the operator-approved subset via the conversation-archive pipeline. Sending: email-send (new), email-reply (threaded — resolves the original via IMAP Message-ID search), email-draft (compose to the mailbox Drafts folder, unsent, for operator review; pass messageId for a threaded draft-reply), email-draft-edit (revise a stored draft by Drafts UID), email-draft-send (dispatch a stored draft by Drafts UID, then remove it). Config: email-provider-info (pre-password host + app-password lookup from an address alone), email-setup, email-status, email-otp-extract.",
3
+ "description": "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :ConversationArchive {source:'email'} with :Section chunks (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox previews (with best-effort per-archive section hints from the graph); email-fetch-body for the COMPLETE decoded body of one message (by uid or message_id) when a preview is not enough. Ingestion (operator-initiated, human-in-the-loop): email-fetch lists new messages, email-ingest writes the operator-approved subset via the conversation-archive pipeline. Sending: email-send (new), email-reply (threaded — resolves the original via IMAP Message-ID search), email-draft (compose to the mailbox Drafts folder, unsent, for operator review; pass messageId for a threaded draft-reply), email-draft-edit (revise a stored draft, located by its Drafts UID or, when Gmail has renumbered it, its draft Message-ID), email-draft-send (dispatch a stored draft by Drafts UID, then remove it). Config: email-provider-info (pre-password host + app-password lookup from an address alone), email-setup, email-status, email-otp-extract.",
4
4
  "version": "0.1.0",
5
5
  "author": {
6
6
  "name": "Rubytech LLC"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: email
3
- description: "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :ConversationArchive {source:'email'} with :Section chunks (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox (with best-effort per-archive section hints from the graph). Ingestion (operator-initiated, human-in-the-loop): email-fetch lists new messages, email-ingest writes the operator-approved subset via the conversation-archive pipeline. Sending: email-send (new), email-reply (threaded — resolves the original via IMAP Message-ID search), email-draft (compose to the mailbox Drafts folder, unsent, for operator review; pass messageId for a threaded draft-reply), email-draft-edit (revise a stored draft by Drafts UID), email-draft-send (dispatch a stored draft by Drafts UID, then remove it). Config: email-provider-info (pre-password host + app-password lookup from an address alone), email-setup, email-status, email-otp-extract."
3
+ description: "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :ConversationArchive {source:'email'} with :Section chunks (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox previews (with best-effort per-archive section hints from the graph); email-fetch-body for the COMPLETE decoded body of one message (by uid or message_id) when a preview is not enough. Ingestion (operator-initiated, human-in-the-loop): email-fetch lists new messages, email-ingest writes the operator-approved subset via the conversation-archive pipeline. Sending: email-send (new), email-reply (threaded — resolves the original via IMAP Message-ID search), email-draft (compose to the mailbox Drafts folder, unsent, for operator review; pass messageId for a threaded draft-reply), email-draft-edit (revise a stored draft, located by its Drafts UID or, when Gmail has renumbered it, its draft Message-ID), email-draft-send (dispatch a stored draft by Drafts UID, then remove it). Config: email-provider-info (pre-password host + app-password lookup from an address alone), email-setup, email-status, email-otp-extract."
4
4
  tools:
5
5
  - name: email-provider-info
6
6
  publicAllowlist: false
@@ -11,6 +11,9 @@ tools:
11
11
  - name: email-read
12
12
  publicAllowlist: false
13
13
  adminAllowlist: false
14
+ - name: email-fetch-body
15
+ publicAllowlist: false
16
+ adminAllowlist: false
14
17
  - name: email-send
15
18
  publicAllowlist: false
16
19
  adminAllowlist: false
@@ -75,10 +78,11 @@ Manages the agent's own dedicated email account — IMAP for reading, SMTP for s
75
78
  - **Setup:** `email-setup` — collect credentials in plain chat and connect IMAP/SMTP. Hosts are auto-inferred for known providers; supports alias addresses (`agentAddress`).
76
79
  - **Read inbox:** `email-read` — metadata only (UID, sender, subject, date), plus a best-effort `Archive`/`Archive-Section` hint when the IMAP message's `receivedAt` falls inside a stored `:ConversationArchive {source:'email'}` section, plus an `Attachments (N): filename (mime, size); …` footer when the message carries enclosures. Supports pagination (`before_uid`), folders (`inbox`/`sent`), filtering by sender/date/subject. Metadata is derived from IMAP `bodyStructure` — no bytes downloaded.
77
80
  - **Search inbox:** `email-search` — live IMAP search by sender, subject, body keyword, date range. Same per-archive hint and attachment footer as `email-read`.
81
+ - **Read one whole message:** `email-fetch-body` — the COMPLETE decoded body of a single message addressed by `uid` (with optional `folder`) or `message_id` (resolved across inbox and sent). No 500-char preview cap. Downloads the full RFC822 source and decodes it with `mailparser`, so every MIME shape — flat text, single-part HTML, `multipart/alternative`, and nested `multipart/related`/`multipart/mixed` (Outlook's inline-image house style) — yields a body; the preview tools above intentionally stay preview-only. Use this when the operator wants to read or act on a message's actual content.
78
82
  - **Send:** `email-send` — new outbound email. Pass `cc`/`bcc` (each an array of email addresses) to copy or blind-copy recipients — CC appears in the message header, BCC recipients receive the message without appearing in any header. Pass `attachments` (absolute file paths under the account directory, ≤25 MB each) to attach files as SMTP attachments; an invalid path fails the send with no email dispatched. The success message names the CC recipients and reports the BCC count without naming them.
79
83
  - **Reply:** `email-reply` — threaded reply to an existing email by `messageId`. Resolves the original envelope via IMAP `SEARCH HEADER Message-ID` (INBOX then `\Sent`), so threading works for any message still present on the server even if the graph never ingested it. Supports `replyAll`, `cc`/`bcc`, and `attachments` (same path rules as `email-send`). Explicit `cc`/`bcc` are added in addition to whatever `replyAll` places in `To`, passed through as given (no overlap de-duplication against `To`).
80
- - **Compose to Drafts:** `email-draft` — builds the same MIME message as `email-send` (same `cc`/`bcc`/`attachments` rules; unlike a dispatched send, the stored draft keeps its `Bcc:` header, because the draft bytes are the only recipient carrier) but APPENDs it to the mailbox's `\Drafts` special-use folder with the `\Draft` flag instead of dispatching it. Nothing is sent. Pass `messageId` to compose a threaded draft-reply: the parent is resolved via IMAP and the draft carries `In-Reply-To`/`References` plus a `Re:` subject from the parent, exactly like `email-reply` (the `subject` argument is then optional and ignored). The success message names the Drafts folder and the APPEND UID so a saved draft is never indistinguishable from a silent no-op. Fails naming the mailbox when the server advertises no `\Drafts` special-use folder — no fallback folder is picked. Use when the operator wants to review and send by hand.
81
- - **Revise a draft:** `email-draft-edit` — replace a stored draft addressed by its Drafts UID. Composes the full replacement from the parameters (same shape as `email-draft`, plus `targetUid` and an optional `messageId` for a threaded revision), APPENDs it with `\Draft`, then deletes the old UID — the replacement is always appended before the old copy is expunged, so a mid-cycle failure never leaves zero copies. An absent `targetUid` fails before any append. Nothing is sent. The confirmation names the folder and both the old and new UIDs.
84
+ - **Compose to Drafts:** `email-draft` — builds the same MIME message as `email-send` (same `cc`/`bcc`/`attachments` rules; unlike a dispatched send, the stored draft keeps its `Bcc:` header, because the draft bytes are the only recipient carrier) but APPENDs it to the mailbox's `\Drafts` special-use folder with the `\Draft` flag instead of dispatching it. Nothing is sent. Pass `messageId` to compose a threaded draft-reply: the parent is resolved via IMAP and the draft carries `In-Reply-To`/`References` plus a `Re:` subject from the parent, exactly like `email-reply` (the `subject` argument is then optional and ignored). The success message names the Drafts folder, the APPEND UID, and the draft's own `Message-ID` (`draft id`) so a saved draft is never indistinguishable from a silent no-op and a later edit has a stable handle. Fails naming the mailbox when the server advertises no `\Drafts` special-use folder — no fallback folder is picked. Use when the operator wants to review and send by hand.
85
+ - **Revise a draft:** `email-draft-edit` — replace a stored draft. The `targetUid` is a fast-path hint; the draft's own `Message-ID` (`draftMessageId`) is the stable identity, because Gmail renumbers a draft's UID when it is touched. The tool tries the UID first, then relocates by a `Message-ID` header search, then composes the replacement from the parameters (same shape as `email-draft`, plus `targetUid`, optional `draftMessageId`, and an optional `messageId` for a threaded revision), APPENDs it with `\Draft`, and deletes the resolved old copy — the replacement is always appended before the old copy is expunged, so a mid-cycle failure never leaves zero copies. When neither identity resolves a live draft, the prior draft is gone: the replacement is saved as a fresh draft (`created`) rather than failing. A single transient transport drop is retried on a fresh connection; auth and other permanent errors surface immediately. Nothing is sent. The confirmation names the folder, the new UID, and the new draft id.
82
86
  - **Send a draft:** `email-draft-send` — dispatch a stored draft addressed by its Drafts UID via SMTP, then remove it from Drafts. Recipients come from the draft's own To/Cc/Bcc headers (the `\Drafts` copy keeps its `Bcc:`), deduped, sent from the agent alias with an explicit SMTP envelope. The draft is deleted only after SMTP accepts; an SMTP failure leaves it in place and surfaces verbatim. A draft with no recipients is refused before sending. Operator-approved sends only.
83
87
  - **Ingestion — fetch:** `email-fetch` — list new IMAP messages since the stored high-water mark. Metadata + body preview only — including attachment names, mimetypes, and sizes so the operator sees what's attached before approving. No bytes downloaded, no graph writes. Stages the batch in-memory for `email-ingest`.
84
88
  - **Ingestion — apply:** `email-ingest` — apply the operator's per-message decisions to the staged batch. Each Message-ID must carry a disposition (`ingest` or `discard`). Approved messages land on `:ConversationArchive {source:'email'}` via the source-agnostic conversation-archive pipeline (one archive per thread, sessionised into `:Section` chunks). Attachment bytes are fetched, archived to `{accountDir}/archive/email/<uidValidity>-<uid>/<sha256>-<filename>` (0o600, 25 MB cap), and each attachment lands as a content-addressed `:DigitalDocument` keyed on `attachmentId = sha256(bytes)`; the `:HAS_ENCLOSURE` edge from the parent `:ConversationArchive` is wired by `memory-ingest` on its next pass via the `pendingArchiveEdges` queue. Advances the inbox high-water mark only after a successful write.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=body-extract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-extract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/body-extract.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,99 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { extractBody, previewBody } from "../lib/imap.js";
3
+ const CRLF = "\r\n";
4
+ const plain = [
5
+ "From: a@x.com",
6
+ "To: b@x.com",
7
+ "Subject: Hi",
8
+ "Content-Type: text/plain; charset=utf-8",
9
+ "",
10
+ "Hello plain world.",
11
+ "",
12
+ ].join(CRLF);
13
+ const alternative = [
14
+ "From: a@x.com",
15
+ "Subject: Alt",
16
+ 'Content-Type: multipart/alternative; boundary="B"',
17
+ "",
18
+ "--B",
19
+ "Content-Type: text/plain; charset=utf-8",
20
+ "",
21
+ "Plain wins.",
22
+ "",
23
+ "--B",
24
+ "Content-Type: text/html; charset=utf-8",
25
+ "",
26
+ "<p>HTML loses.</p>",
27
+ "",
28
+ "--B--",
29
+ "",
30
+ ].join(CRLF);
31
+ // Outlook house style: multipart/related → nested multipart/alternative
32
+ // carrying ONLY text/html (no top-level text/plain) + an inline image part.
33
+ // The hand-rolled extractor returned "(body unavailable)" for this shape.
34
+ const outlook = [
35
+ "From: max@outlook.com",
36
+ "Subject: Proposal",
37
+ 'Content-Type: multipart/related; boundary="R"',
38
+ "",
39
+ "--R",
40
+ 'Content-Type: multipart/alternative; boundary="A"',
41
+ "",
42
+ "--A",
43
+ "Content-Type: text/html; charset=utf-8",
44
+ "",
45
+ "<p>Real Outlook <b>body</b> text.</p>",
46
+ "",
47
+ "--A--",
48
+ "",
49
+ "--R",
50
+ "Content-Type: image/png",
51
+ "Content-Transfer-Encoding: base64",
52
+ "",
53
+ "iVBORw0KGgo=",
54
+ "",
55
+ "--R--",
56
+ "",
57
+ ].join(CRLF);
58
+ const longText = "x".repeat(1200);
59
+ const longMsg = [
60
+ "Subject: Long",
61
+ "Content-Type: text/plain; charset=utf-8",
62
+ "",
63
+ longText,
64
+ "",
65
+ ].join(CRLF);
66
+ describe("extractBody", () => {
67
+ it("decodes a flat text/plain body", async () => {
68
+ const r = await extractBody(plain);
69
+ expect(r.body).toBe("Hello plain world.");
70
+ expect(r.kind).toBe("text");
71
+ });
72
+ it("prefers text/plain in multipart/alternative", async () => {
73
+ const r = await extractBody(alternative);
74
+ expect(r.body).toContain("Plain wins.");
75
+ expect(r.kind).toBe("text");
76
+ });
77
+ it("yields the body for nested multipart/related html-only (Outlook regression guard)", async () => {
78
+ const r = await extractBody(outlook);
79
+ expect(r.body).toContain("Real Outlook");
80
+ expect(r.body).toContain("body");
81
+ expect(r.body).not.toBe("(body unavailable)");
82
+ expect(r.kind).toBe("html");
83
+ });
84
+ it("returns the whole long body uncapped", async () => {
85
+ const r = await extractBody(longMsg);
86
+ expect(r.body.length).toBeGreaterThanOrEqual(1200);
87
+ });
88
+ });
89
+ describe("previewBody", () => {
90
+ it("truncates a >500-char body with an ellipsis", () => {
91
+ const p = previewBody("y".repeat(1200));
92
+ expect(p.length).toBe(501);
93
+ expect(p.endsWith("…")).toBe(true);
94
+ });
95
+ it("passes short bodies through unchanged", () => {
96
+ expect(previewBody("short")).toBe("short");
97
+ });
98
+ });
99
+ //# sourceMappingURL=body-extract.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-extract.test.js","sourceRoot":"","sources":["../../src/__tests__/body-extract.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=compose-draft-id.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose-draft-id.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/compose-draft-id.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { composeDraft } from "../lib/compose.js";
3
+ // Standalone (non-threaded) compose touches no IMAP and no filesystem when
4
+ // there are no attachments, so it can be exercised directly.
5
+ const config = {
6
+ email: "login@example.com",
7
+ agentAddress: "agent@example.com",
8
+ };
9
+ describe("Task 1177 — composeDraft stamps a stable draft Message-ID", () => {
10
+ it("returns a draftMessageId on the agent-address domain", async () => {
11
+ const composed = await composeDraft(config, "pw", "acc-1", {
12
+ to: "c@d.e",
13
+ subject: "Quote",
14
+ body: "Body",
15
+ });
16
+ expect(composed.draftMessageId).toMatch(/^<.+@example\.com>$/);
17
+ });
18
+ it("stamps the same Message-ID into the composed raw bytes", async () => {
19
+ const composed = await composeDraft(config, "pw", "acc-1", {
20
+ to: "c@d.e",
21
+ subject: "Quote",
22
+ body: "Body",
23
+ });
24
+ expect(composed.raw.toString()).toContain(`Message-ID: ${composed.draftMessageId}`);
25
+ });
26
+ it("gives each composed draft its own unique Message-ID", async () => {
27
+ const a = await composeDraft(config, "pw", "acc-1", { to: "c@d.e", subject: "Q", body: "1" });
28
+ const b = await composeDraft(config, "pw", "acc-1", { to: "c@d.e", subject: "Q", body: "2" });
29
+ expect(a.draftMessageId).not.toBe(b.draftMessageId);
30
+ });
31
+ });
32
+ //# sourceMappingURL=compose-draft-id.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose-draft-id.test.js","sourceRoot":"","sources":["../../src/__tests__/compose-draft-id.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,2EAA2E;AAC3E,6DAA6D;AAC7D,MAAM,MAAM,GAAG;IACb,KAAK,EAAE,mBAAmB;IAC1B,YAAY,EAAE,mBAAmB;CACnB,CAAC;AAEjB,QAAQ,CAAC,2DAA2D,EAAE,GAAG,EAAE;IACzE,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;YACzD,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;YACzD,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC,eAAe,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9F,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9F,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -4,9 +4,17 @@ const { composeMock, replaceMock } = vi.hoisted(() => ({
4
4
  raw: Buffer.from("MIME"),
5
5
  resolvedSubject: "Re: Quote",
6
6
  threadedParentId: null,
7
+ draftMessageId: "<new-draft@x>",
7
8
  attachments: [],
8
9
  })),
9
- replaceMock: vi.fn(async () => ({ folder: "Drafts", oldUid: 5, newUid: 99, expunged: true })),
10
+ replaceMock: vi.fn(async () => ({
11
+ folder: "Drafts",
12
+ oldUid: 5,
13
+ newUid: 99,
14
+ expunged: true,
15
+ created: false,
16
+ addressing: "uid-hit",
17
+ })),
10
18
  }));
11
19
  vi.mock("../lib/compose.js", () => ({ composeDraft: composeMock }));
12
20
  vi.mock("../lib/imap.js", () => ({ replaceDraft: replaceMock }));
@@ -23,9 +31,17 @@ describe("Task 819 — email-draft-edit", () => {
23
31
  raw: Buffer.from("MIME"),
24
32
  resolvedSubject: "Re: Quote",
25
33
  threadedParentId: null,
34
+ draftMessageId: "<new-draft@x>",
26
35
  attachments: [],
27
36
  });
28
- replaceMock.mockResolvedValue({ folder: "Drafts", oldUid: 5, newUid: 99, expunged: true });
37
+ replaceMock.mockResolvedValue({
38
+ folder: "Drafts",
39
+ oldUid: 5,
40
+ newUid: 99,
41
+ expunged: true,
42
+ created: false,
43
+ addressing: "uid-hit",
44
+ });
29
45
  });
30
46
  it("composes the replacement then replaces by UID; names the folder and both UIDs", async () => {
31
47
  const text = await emailDraftEdit({
@@ -36,17 +52,59 @@ describe("Task 819 — email-draft-edit", () => {
36
52
  body: "Revised body.",
37
53
  });
38
54
  expect(composeMock).toHaveBeenCalledTimes(1);
39
- expect(replaceMock).toHaveBeenCalledWith(expect.anything(), "pw", 5, expect.any(Buffer));
55
+ expect(replaceMock).toHaveBeenCalledWith(expect.anything(), "pw", 5, expect.any(Buffer), null);
40
56
  expect(text).toContain("Drafts");
41
57
  expect(text).toContain("5");
42
58
  expect(text).toContain("99");
43
59
  expect(text).toMatch(/unsent/); // a revise never dispatches
44
60
  });
61
+ it("passes the prior draft Message-ID to replaceDraft for relocation", async () => {
62
+ await emailDraftEdit({
63
+ accountId: "acc-1",
64
+ targetUid: 5,
65
+ to: "c@d.e",
66
+ subject: "Quote",
67
+ body: "v2",
68
+ draftMessageId: "<old-draft@x>",
69
+ });
70
+ expect(replaceMock).toHaveBeenCalledWith(expect.anything(), "pw", 5, expect.any(Buffer), "<old-draft@x>");
71
+ });
72
+ it("surfaces the new draft's Message-ID so the next edit can relocate it", async () => {
73
+ const text = await emailDraftEdit({
74
+ accountId: "acc-1",
75
+ targetUid: 5,
76
+ to: "c@d.e",
77
+ subject: "Quote",
78
+ body: "v2",
79
+ });
80
+ expect(text).toContain("draft id: <new-draft@x>");
81
+ });
82
+ it("reports the create-on-absent recovery when the prior draft was gone", async () => {
83
+ replaceMock.mockResolvedValueOnce({
84
+ folder: "Drafts",
85
+ oldUid: 5,
86
+ newUid: 77,
87
+ expunged: false,
88
+ created: true,
89
+ addressing: "created-fresh",
90
+ });
91
+ const text = await emailDraftEdit({
92
+ accountId: "acc-1",
93
+ targetUid: 5,
94
+ to: "c@d.e",
95
+ subject: "Quote",
96
+ body: "v2",
97
+ draftMessageId: "<old-draft@x>",
98
+ });
99
+ expect(text).toMatch(/no longer present/i);
100
+ expect(text).toContain("77");
101
+ });
45
102
  it("names the threaded parent when the revision is a threaded draft", async () => {
46
103
  composeMock.mockResolvedValueOnce({
47
104
  raw: Buffer.from("MIME"),
48
105
  resolvedSubject: "Re: Quote",
49
106
  threadedParentId: "<parent@x>",
107
+ draftMessageId: "<new-draft@x>",
50
108
  attachments: [],
51
109
  });
52
110
  const text = await emailDraftEdit({
@@ -63,9 +121,9 @@ describe("Task 819 — email-draft-edit", () => {
63
121
  await expect(emailDraftEdit({ accountId: "acc-1", targetUid: 5, to: "c@d.e", body: "v2", messageId: "<gone@x>" })).rejects.toThrow(/No email found/);
64
122
  expect(replaceMock).not.toHaveBeenCalled();
65
123
  });
66
- it("surfaces a missing-target-UID error from replaceDraft verbatim", async () => {
67
- replaceMock.mockRejectedValueOnce(new Error("Draft UID 404 not found in Drafts."));
68
- await expect(emailDraftEdit({ accountId: "acc-1", targetUid: 404, to: "c@d.e", subject: "Q", body: "v2" })).rejects.toThrow(/Draft UID 404 not found/);
124
+ it("surfaces a persistent transient-drop error from replaceDraft verbatim", async () => {
125
+ replaceMock.mockRejectedValueOnce(new Error("Connection not available"));
126
+ await expect(emailDraftEdit({ accountId: "acc-1", targetUid: 404, to: "c@d.e", subject: "Q", body: "v2" })).rejects.toThrow(/Connection not available/);
69
127
  });
70
128
  });
71
129
  //# sourceMappingURL=email-draft-edit.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"email-draft-edit.test.js","sourceRoot":"","sources":["../../src/__tests__/email-draft-edit.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"email-draft-edit.test.js","sourceRoot":"","sources":["../../src/__tests__/email-draft-edit.test.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,18 @@ describe("Task 815 — email-draft tool", () => {
46
46
  expect(text).toContain("27675");
47
47
  expect(text).toContain("joel@example.com");
48
48
  });
49
+ it("stamps a draft Message-ID into the bytes and surfaces it in the confirmation", async () => {
50
+ const text = await emailDraft({
51
+ accountId: "acc-1",
52
+ to: "joel@example.com",
53
+ subject: "Quote",
54
+ body: "Body.",
55
+ });
56
+ const [, , raw] = appendDraftMock.mock.calls[0];
57
+ const stamped = raw.toString().match(/^Message-ID: (<.+@example\.com>)/m);
58
+ expect(stamped).not.toBeNull();
59
+ expect(text).toContain(`draft id: ${stamped[1]}`);
60
+ });
49
61
  it("preserves the Bcc header in the draft bytes (keepBcc — the stored draft is the only recipient carrier)", async () => {
50
62
  await emailDraft({
51
63
  accountId: "acc-1",
@@ -1 +1 @@
1
- {"version":3,"file":"email-draft.test.js","sourceRoot":"","sources":["../../src/__tests__/email-draft.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"email-draft.test.js","sourceRoot":"","sources":["../../src/__tests__/email-draft.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=email-status.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-status.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/email-status.test.ts"],"names":[],"mappings":""}