@rubytech/create-maxy-code 0.1.23 → 0.1.26

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 (209) hide show
  1. package/dist/index.js +63 -16
  2. package/package.json +1 -1
  3. package/payload/platform/plugins/admin/PLUGIN.md +50 -23
  4. package/payload/platform/plugins/admin/skills/admin-user-management/SKILL.md +47 -0
  5. package/payload/platform/plugins/admin/skills/commitment-followthrough/SKILL.md +60 -0
  6. package/payload/platform/plugins/admin/skills/file-presentation/SKILL.md +67 -0
  7. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +111 -126
  8. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +62 -0
  9. package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +37 -0
  10. package/payload/platform/plugins/cloudflare/references/manual-setup.md +81 -1
  11. package/payload/platform/plugins/cloudflare/scripts/__tests__/tunnel-ingress.test.ts +241 -0
  12. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +267 -28
  13. package/payload/platform/plugins/cloudflare/scripts/tunnel-ingress.ts +291 -0
  14. package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +42 -0
  15. package/payload/platform/plugins/contacts/PLUGIN.md +18 -9
  16. package/payload/platform/plugins/deep-research/.claude-plugin/plugin.json +1 -1
  17. package/payload/platform/plugins/deep-research/PLUGIN.md +7 -1
  18. package/payload/platform/plugins/deep-research/recipes/README.md +36 -0
  19. package/payload/platform/plugins/deep-research/skills/academic-verify/SKILL.md +75 -0
  20. package/payload/platform/plugins/deep-research/skills/book-mirror/SKILL.md +68 -0
  21. package/payload/platform/plugins/deep-research/skills/data-research/SKILL.md +108 -0
  22. package/payload/platform/plugins/deep-research/skills/strategic-reading/SKILL.md +69 -0
  23. package/payload/platform/plugins/docs/references/deployment.md +3 -2
  24. package/payload/platform/plugins/docs/references/platform.md +2 -0
  25. package/payload/platform/plugins/docs/references/troubleshooting.md +12 -0
  26. package/payload/platform/plugins/email/PLUGIN.md +18 -9
  27. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts +17 -0
  28. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +1 -0
  29. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +185 -0
  30. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -0
  31. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
  32. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js +34 -111
  33. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js.map +1 -1
  34. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts +7 -2
  35. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts.map +1 -1
  36. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +7 -2
  37. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
  38. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +2 -0
  39. package/payload/platform/plugins/memory/PLUGIN.md +64 -29
  40. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts +3 -1
  41. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +105 -4
  43. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
  44. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  45. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +16 -3
  46. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  47. package/payload/platform/plugins/memory/skills/archive-crawler/SKILL.md +67 -0
  48. package/payload/platform/plugins/memory/skills/concept-synthesis/SKILL.md +80 -0
  49. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -0
  50. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +2 -0
  51. package/payload/platform/plugins/outlook/PLUGIN.md +14 -7
  52. package/payload/platform/plugins/replicate/PLUGIN.md +6 -3
  53. package/payload/platform/plugins/scheduling/PLUGIN.md +19 -8
  54. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts +7 -3
  55. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts.map +1 -1
  56. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +7 -3
  57. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  58. package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +75 -0
  59. package/payload/platform/plugins/scheduling/skills/daily-prep/SKILL.md +61 -0
  60. package/payload/platform/plugins/tasks/PLUGIN.md +28 -14
  61. package/payload/platform/plugins/telegram/PLUGIN.md +6 -3
  62. package/payload/platform/plugins/waitlist/PLUGIN.md +12 -6
  63. package/payload/platform/plugins/whatsapp/PLUGIN.md +25 -13
  64. package/payload/platform/plugins/workflows/PLUGIN.md +16 -8
  65. package/payload/platform/scripts/conversation-id-allowlist.txt +0 -1
  66. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  67. package/payload/platform/services/claude-session-manager/dist/http-server.js +27 -2
  68. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  69. package/payload/platform/services/claude-session-manager/dist/index.js +27 -0
  70. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  71. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +36 -0
  72. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  73. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +41 -3
  74. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  75. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +25 -1
  76. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  77. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +54 -3
  78. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  79. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +25 -0
  80. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -0
  81. package/payload/platform/services/claude-session-manager/dist/tool-surface.js +149 -0
  82. package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -0
  83. package/payload/platform/templates/agents/admin/IDENTITY.md +38 -284
  84. package/payload/platform/templates/agents/admin/SOUL.md +4 -4
  85. package/payload/platform/templates/specialists/agents/content-producer.md +24 -69
  86. package/payload/platform/templates/specialists/agents/database-operator.md +49 -155
  87. package/payload/platform/templates/specialists/agents/personal-assistant.md +27 -177
  88. package/payload/platform/templates/specialists/agents/project-manager.md +29 -96
  89. package/payload/platform/templates/specialists/agents/research-assistant.md +36 -78
  90. package/payload/premium-plugins/real-agency/agents/compliance.md +14 -0
  91. package/payload/premium-plugins/real-agency/agents/negotiator.md +22 -0
  92. package/payload/premium-plugins/real-agency/agents/valuer.md +16 -0
  93. package/payload/premium-plugins/real-agency/plugins/estate-business/.claude-plugin/plugin.json +1 -1
  94. package/payload/premium-plugins/real-agency/plugins/estate-business/PLUGIN.md +44 -13
  95. package/payload/premium-plugins/real-agency/plugins/estate-business/skills/commission-calculator/SKILL.md +40 -0
  96. package/payload/premium-plugins/real-agency/plugins/estate-business/skills/month-end-close/SKILL.md +69 -0
  97. package/payload/premium-plugins/real-agency/plugins/estate-business/skills/payment-batch-stager/SKILL.md +42 -0
  98. package/payload/premium-plugins/real-agency/plugins/estate-business/skills/period-reconciler/SKILL.md +42 -0
  99. package/payload/premium-plugins/real-agency/plugins/estate-sales/.claude-plugin/plugin.json +1 -1
  100. package/payload/premium-plugins/real-agency/plugins/estate-sales/PLUGIN.md +32 -13
  101. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/chase-progression/SKILL.md +107 -0
  102. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/risk-scorer/SKILL.md +42 -0
  103. package/payload/premium-plugins/real-agency/plugins/leads/.claude-plugin/plugin.json +1 -1
  104. package/payload/premium-plugins/real-agency/plugins/leads/PLUGIN.md +40 -10
  105. package/payload/premium-plugins/real-agency/plugins/leads/skills/chain-progression-tracker/SKILL.md +51 -0
  106. package/payload/premium-plugins/real-agency/plugins/leads/skills/diary-builder/SKILL.md +38 -0
  107. package/payload/premium-plugins/real-agency/plugins/leads/skills/enquiry-triage/SKILL.md +36 -0
  108. package/payload/premium-plugins/real-agency/plugins/leads/skills/morning-round/SKILL.md +72 -0
  109. package/payload/premium-plugins/real-agency/plugins/listings/.claude-plugin/plugin.json +1 -1
  110. package/payload/premium-plugins/real-agency/plugins/listings/PLUGIN.md +82 -12
  111. package/payload/premium-plugins/real-agency/plugins/listings/skills/comparable-finder/SKILL.md +52 -0
  112. package/payload/premium-plugins/real-agency/plugins/listings/skills/epc-checker/SKILL.md +38 -0
  113. package/payload/premium-plugins/real-agency/plugins/listings/skills/listing-copy-writer/SKILL.md +55 -0
  114. package/payload/premium-plugins/real-agency/plugins/listings/skills/local-market-stats/SKILL.md +33 -0
  115. package/payload/premium-plugins/real-agency/plugins/listings/skills/new-instruction/SKILL.md +78 -0
  116. package/payload/premium-plugins/real-agency/plugins/listings/skills/particulars-builder/SKILL.md +48 -0
  117. package/payload/premium-plugins/real-agency/plugins/listings/skills/portal-launch-scheduler/SKILL.md +49 -0
  118. package/payload/premium-plugins/real-agency/plugins/listings/skills/pricing-scenario-builder/SKILL.md +35 -0
  119. package/payload/premium-plugins/real-agency/plugins/listings/skills/supplier-booker/SKILL.md +39 -0
  120. package/payload/premium-plugins/real-agency/plugins/listings/skills/talk-track-composer/SKILL.md +36 -0
  121. package/payload/premium-plugins/real-agency/plugins/listings/skills/terms-of-business-drafter/SKILL.md +54 -0
  122. package/payload/premium-plugins/real-agency/plugins/listings/skills/valuation-prep/SKILL.md +69 -0
  123. package/payload/premium-plugins/real-agency/plugins/loop/PLUGIN.md +35 -0
  124. package/payload/premium-plugins/real-agency/plugins/loop/skills/compliance-flag-checker/SKILL.md +53 -0
  125. package/payload/premium-plugins/real-agency/plugins/loop/skills/priority-ranker/SKILL.md +40 -0
  126. package/payload/premium-plugins/real-agency/plugins/loop/skills/tone-matched-drafter/SKILL.md +53 -0
  127. package/payload/premium-plugins/real-agency/plugins/loop/skills/variance-narrator/SKILL.md +50 -0
  128. package/payload/premium-plugins/real-agency/plugins/loop/skills/vendor-research/SKILL.md +54 -0
  129. package/payload/server/{chunk-2ZNKHCQB.js → chunk-2MRZBQMH.js} +1 -1
  130. package/payload/server/{chunk-GPUCA2RQ.js → chunk-NL7QLVAD.js} +0 -192
  131. package/payload/server/{chunk-IDKWGLM5.js → chunk-YPZFYTYP.js} +1 -247
  132. package/payload/server/{cloudflare-task-tracker-LYI5BTYI.js → cloudflare-task-tracker-QVOGHKWV.js} +2 -2
  133. package/payload/server/maxy-edge.js +2 -2
  134. package/payload/server/package.json +0 -2
  135. package/payload/server/public/assets/{Checkbox-D1OQD43b.js → Checkbox-YIF0payo.js} +1 -1
  136. package/payload/server/public/assets/{admin-czNBxWor.js → admin-DW8IJcLc.js} +1 -1
  137. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-BcwgT80u.js → architectureDiagram-Q4EWVU46-Bz8mlxZZ.js} +1 -1
  138. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BMSyZUQA.js → blockDiagram-DXYQGD6D-DwV8Z8-i.js} +1 -1
  139. package/payload/server/public/assets/{brand-2cku8WFs.css → brand-DqiRNMlu.css} +1 -1
  140. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DPRGY1jJ.js → c4Diagram-AHTNJAMY-DiUTejMp.js} +1 -1
  141. package/payload/server/public/assets/channel-PtVtoBEL.js +1 -0
  142. package/payload/server/public/assets/{chunk-336JU56O-B7oQ3g1c.js → chunk-336JU56O-4mHZpBXe.js} +2 -2
  143. package/payload/server/public/assets/{chunk-426QAEUC-C1P0yFXw.js → chunk-426QAEUC-Cbv0vrN9.js} +1 -1
  144. package/payload/server/public/assets/{chunk-4TB4RGXK-LI7kOJd0.js → chunk-4TB4RGXK-BvLhId_2.js} +1 -1
  145. package/payload/server/public/assets/{chunk-5FUZZQ4R-CXQRGTQE.js → chunk-5FUZZQ4R-bBafOTkw.js} +1 -1
  146. package/payload/server/public/assets/{chunk-5PVQY5BW-NSyzpXRy.js → chunk-5PVQY5BW-B0NqBKVy.js} +1 -1
  147. package/payload/server/public/assets/{chunk-EDXVE4YY-voNwxbDs.js → chunk-EDXVE4YY-CFd4SqI6.js} +1 -1
  148. package/payload/server/public/assets/{chunk-ENJZ2VHE-CMEMPzYY.js → chunk-ENJZ2VHE-ajf2sb6c.js} +1 -1
  149. package/payload/server/public/assets/{chunk-ICPOFSXX-hEbwu-pe.js → chunk-ICPOFSXX-pWg6bug7.js} +1 -1
  150. package/payload/server/public/assets/{chunk-OYMX7WX6-DxskDrLs.js → chunk-OYMX7WX6-OjEd-17c.js} +1 -1
  151. package/payload/server/public/assets/{chunk-U2HBQHQK-D7TKgUo0.js → chunk-U2HBQHQK-DbEFSPoh.js} +1 -1
  152. package/payload/server/public/assets/{chunk-X2U36JSP-BvPUQEPm.js → chunk-X2U36JSP-COdNwrBb.js} +1 -1
  153. package/payload/server/public/assets/{chunk-YZCP3GAM-BY-RWQUW.js → chunk-YZCP3GAM-CHMWuY9B.js} +1 -1
  154. package/payload/server/public/assets/{chunk-ZZ45TVLE-DZvOYDY6.js → chunk-ZZ45TVLE-B-uDLQOB.js} +1 -1
  155. package/payload/server/public/assets/classDiagram-6PBFFD2Q-RVH_SEhY.js +1 -0
  156. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Cm3rAb93.js +1 -0
  157. package/payload/server/public/assets/clone-BjY0Wzht.js +1 -0
  158. package/payload/server/public/assets/{dagre-KV5264BT-Cnj0mUZl.js → dagre-KV5264BT-CMEzmhIL.js} +1 -1
  159. package/payload/server/public/assets/{dagre-Bt-fpckL.js → dagre-bhIG_KnW.js} +1 -1
  160. package/payload/server/public/assets/data-K_kS__sL.js +1 -0
  161. package/payload/server/public/assets/{device-url-actions-Bjz3Xzbm.js → device-url-actions-AcOyLSeF.js} +1 -1
  162. package/payload/server/public/assets/{diagram-5BDNPKRD-DjLzvOlx.js → diagram-5BDNPKRD-6RIoQhIL.js} +1 -1
  163. package/payload/server/public/assets/{diagram-G4DWMVQ6-DTfuRd-T.js → diagram-G4DWMVQ6-BSp36TVv.js} +1 -1
  164. package/payload/server/public/assets/{diagram-MMDJMWI5-BaL2mCnx.js → diagram-MMDJMWI5-D54fo52D.js} +1 -1
  165. package/payload/server/public/assets/{diagram-TYMM5635-C5InWY5R.js → diagram-TYMM5635-CWL8z-Pq.js} +1 -1
  166. package/payload/server/public/assets/{erDiagram-SMLLAGMA-DO7BXTpn.js → erDiagram-SMLLAGMA-AnnHBo3z.js} +1 -1
  167. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-DDdAKfLf.js → flowDiagram-DWJPFMVM-laWmBl5o.js} +1 -1
  168. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-arJD8Utm.js → ganttDiagram-T4ZO3ILL-B94ko8ie.js} +1 -1
  169. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C55GH-OS.js → gitGraphDiagram-UUTBAWPF-DxzL1fxZ.js} +1 -1
  170. package/payload/server/public/assets/graph-DeEigyO_.js +1 -0
  171. package/payload/server/public/assets/graph-labels-C7I5QvNv.js +1 -0
  172. package/payload/server/public/assets/{graphlib-DL9PM7Ex.js → graphlib-CY-zIElM.js} +1 -1
  173. package/payload/server/public/assets/{infoDiagram-42DDH7IO-BMSGqUbG.js → infoDiagram-42DDH7IO-BMTajIIr.js} +1 -1
  174. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-Dw6BZ6BG.js → ishikawaDiagram-UXIWVN3A-B_QauE5O.js} +1 -1
  175. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DrywUGXw.js → journeyDiagram-VCZTEJTY-DmlqSIih.js} +1 -1
  176. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DuwtVBBc.js → kanban-definition-6JOO6SKY-ZGDQT7xB.js} +1 -1
  177. package/payload/server/public/assets/{line-JAksyKHj.js → line-D13opgep.js} +1 -1
  178. package/payload/server/public/assets/{mermaid-parser.core-BMq-ApBW.js → mermaid-parser.core-C650Sual.js} +1 -1
  179. package/payload/server/public/assets/{mermaid.core-tH4oX0Kh.js → mermaid.core-BqnQoXTp.js} +3 -3
  180. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-D1OiiJga.js → mindmap-definition-QFDTVHPH-BS_8y-tY.js} +1 -1
  181. package/payload/server/public/assets/{page-BZpoS7iR.js → page-B_rpjIRr.js} +1 -1
  182. package/payload/server/public/assets/{page-CkvBvezS.js → page-qSH972X0.js} +1 -1
  183. package/payload/server/public/assets/{pieDiagram-DEJITSTG-Ckwm69PW.js → pieDiagram-DEJITSTG-B5OmNvBO.js} +1 -1
  184. package/payload/server/public/assets/{public-C-dTMgXu.js → public-DDsYgotk.js} +3 -3
  185. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-COw3yZ1j.js → quadrantDiagram-34T5L4WZ-DTYITdNo.js} +1 -1
  186. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DqGzM4K-.js → requirementDiagram-MS252O5E-CRZWxH06.js} +1 -1
  187. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-D-l1c_Pl.js → sankeyDiagram-XADWPNL6-DazRENhe.js} +1 -1
  188. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BeIi0DtJ.js → sequenceDiagram-FGHM5R23-BcHTxmPy.js} +1 -1
  189. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-C-jgegLk.js → stateDiagram-FHFEXIEX-DYU7nbqg.js} +1 -1
  190. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BgljVtlp.js +1 -0
  191. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BGFKkYmi.js → timeline-definition-GMOUNBTQ-BKGmqkST.js} +1 -1
  192. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-5NuIhJLS.js → vennDiagram-DHZGUBPP-BXvLPmX7.js} +1 -1
  193. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-Be9ytVut.js → wardleyDiagram-NUSXRM2D-BCclUa3Z.js} +1 -1
  194. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DCyHg41R.js → xychartDiagram-5P7HB3ND-C-Xp-Eoc.js} +1 -1
  195. package/payload/server/public/data.html +5 -5
  196. package/payload/server/public/graph.html +6 -6
  197. package/payload/server/public/index.html +8 -8
  198. package/payload/server/public/public.html +5 -5
  199. package/payload/server/server.js +1152 -2564
  200. package/payload/platform/scripts/check-sdk-oauth.mjs +0 -185
  201. package/payload/server/public/assets/channel-fxEghWew.js +0 -1
  202. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BsWzGW0N.js +0 -1
  203. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BGVa3h90.js +0 -1
  204. package/payload/server/public/assets/clone-Khvocke2.js +0 -1
  205. package/payload/server/public/assets/data-DBd-Buhp.js +0 -1
  206. package/payload/server/public/assets/graph-DUtVdnZ6.js +0 -1
  207. package/payload/server/public/assets/graph-labels-Dxfue-fP.js +0 -1
  208. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BaMs8Znv.js +0 -1
  209. /package/payload/server/public/assets/{brand-CSQuxS9w.js → brand-Bm671owU.js} +0 -0
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: data-research
3
+ description: "Recipe-driven structured-data extraction. Takes a named recipe and a set of sources (emails, reports, web pages, forms, PDFs) and writes typed entities to the graph per the recipe's schema. Triggers when the owner says 'extract X from these emails', 'track investor updates', 'pull donation amounts', 'build a table of Y from these documents'."
4
+ ---
5
+
6
+ # Data research
7
+
8
+ This skill turns unstructured-looking sources (emails, reports, forms, web pages) into structured graph entities. The transformation is always recipe-driven: a named YAML recipe declares what fields to extract, what validations to apply, and what graph nodes to write. The skill runs a named recipe; it never invents a schema on the fly.
9
+
10
+ **Default parent.** Every recipe declares its hierarchy parent via `graph_target.parent` — either `Project` (the run-time recipe argument names which Project elementId to attach to) or `LocalBusiness` (the account root, for cross-project recipes like investor-updates). The skill refuses to run a recipe whose `parent` field is missing or whose named Project does not exist. Per-row writes attach to that parent via the canonical containment edge; the recipe's `relationships:` block describes cross-hierarchy edges (e.g. `ROUND_FOR → Organization`) which are written separately and do not substitute for the parent.
11
+
12
+ ## When to run
13
+
14
+ Run when the owner wants the same extraction repeated across many sources. The trigger phrases are above. Do not run for one-off extractions; a one-off is what `document-ingest` does.
15
+
16
+ ## Inputs
17
+
18
+ | Input | Meaning |
19
+ |---|---|
20
+ | `recipe` | The name of an existing recipe at `plugins/deep-research/recipes/<name>.yaml`. |
21
+ | `sources` | One or more source paths or URLs. Email thread paths, PDF paths, web URLs, or a folder. |
22
+ | `parent` | The Project elementId (or `LocalBusiness` for cross-project recipes) the writes anchor to. Required when the recipe's `parent` field is `Project`; ignored when the recipe's parent is `LocalBusiness` (the account root resolves automatically). |
23
+
24
+ If `recipe` does not match any file in the recipes directory, refuse. List the available recipe names. Do not invent a recipe.
25
+
26
+ If the owner asks for an extraction shape that no existing recipe covers, the answer is "no recipe exists for that yet. Want me to draft one?". The skill never extracts data without a recipe; that is the point of the recipe layer.
27
+
28
+ ## Recipe shape
29
+
30
+ A recipe is a YAML file with this shape:
31
+
32
+ ```yaml
33
+ name: investor-updates
34
+ description: One-line description of what this recipe extracts.
35
+ source_kinds:
36
+ - email-thread
37
+ - web-page
38
+ - pdf
39
+ fields:
40
+ - name: company_name
41
+ type: string
42
+ required: true
43
+ - name: round
44
+ type: string
45
+ required: false
46
+ - name: amount_gbp
47
+ type: number
48
+ required: false
49
+ validation:
50
+ min: 0
51
+ - name: date_announced
52
+ type: date
53
+ required: true
54
+ graph_target:
55
+ label: FundingRound
56
+ parent: LocalBusiness # or `Project` — names the hierarchy anchor for every row
57
+ identity:
58
+ - company_name
59
+ - date_announced
60
+ relationships:
61
+ - type: ROUND_FOR
62
+ target_label: Organization
63
+ target_match: company_name
64
+ ```
65
+
66
+ ## Method
67
+
68
+ 1. **Load and validate the recipe.** Read the recipe file. Check that every field declared has a `name` and `type`. Check that `graph_target.label` is a label in the live ontology (`maxy-graph-get_neo4j_schema`). Check that `graph_target.parent` is present and resolves (Project elementId supplied at call time, or `LocalBusiness` resolved from the account root). If anything fails, refuse and report the recipe's defect.
69
+ 2. **Iterate sources.** For each source: classify by kind against `source_kinds`. Skip sources whose kind is not in the recipe's allowed list, list them in the report.
70
+ 3. **Extract per source.** Fetch the source. Use Haiku-driven classification (`memory-classify` with a recipe-specific prompt) to extract each declared field. Apply each field's validation. Reject rows that fail required-field checks; capture them in a rejected list.
71
+ 4. **Write to the graph.** For each accepted row, `memory-write` a node with the declared label and the extracted properties. Attach it to the resolved hierarchy parent via the canonical containment edge. Stamp `createdByAgent: data-research`, `createdByRecipe: <recipe name>`, `sourceDocumentId: <source>`. Write the declared cross-hierarchy relationships, resolving target nodes via `memory-search` on the named match property.
72
+ 5. **Report.** Return one line per source (accepted count, rejected count) and one summary line: total rows written, total rejected, total relationships created.
73
+
74
+ ## Output format
75
+
76
+ ```
77
+ **Recipe.** <name>
78
+ **Sources.** <N> processed.
79
+
80
+ | Source | Accepted | Rejected | Reason |
81
+ |---|---|---|---|
82
+ | <source path or URL> | 3 | 1 | "amount_gbp negative" |
83
+ | ... | | | |
84
+
85
+ **Total.** 12 rows written as :<Label>, 9 relationships created via <RelType>.
86
+ **Rejections.** 3 rows rejected (full list below).
87
+ ```
88
+
89
+ ## Why recipes
90
+
91
+ A recipe is a contract. The owner reads the recipe and knows what will be written. The recipe is version-controlled and auditable. Without recipes, the skill would extract whatever the LLM thinks is interesting, which means the graph schema drifts with every run and the owner cannot trust what arrives. The recipe layer is the difference between a controlled pipeline and a junk shop.
92
+
93
+ ## Failure modes
94
+
95
+ - **Recipe file is malformed.** Surface the YAML error literally and refuse.
96
+ - **Recipe declares a `graph_target.label` not in the ontology.** Refuse. Tell the owner the label is missing and recommend either adjusting the recipe or extending the ontology.
97
+ - **Recipe's `graph_target.parent` is missing or unresolvable.** Refuse. The hierarchy parent is mandatory; without it, every row would land as an orphan.
98
+ - **No sources match the recipe's allowed kinds.** Refuse. List what the recipe accepts.
99
+ - **Target-match relationship cannot resolve** (the recipe wants `ROUND_FOR -> Organization` and the named company is not in the graph). Capture in the rejected list with the reason "target organisation not found"; do not create a placeholder organisation.
100
+ - **Embedding service unavailable mid-batch.** Stop. Report which sources completed and which did not.
101
+
102
+ ## Where recipes live
103
+
104
+ Recipes live at `platform/plugins/deep-research/recipes/<name>.yaml`. The directory is part of the plugin and ships with the platform. To author a new recipe, the owner names the extraction they want; the skill can scaffold the YAML and the owner reviews and saves it. Recipe authoring is a separate path; this skill consumes recipes, it does not write them inline.
105
+
106
+ ## What this skill does not do
107
+
108
+ It does not run free-form extractions. It does not write to the graph without an approved recipe. It does not modify recipes during a run; if the recipe needs changing, the run aborts, the owner edits the recipe, and the run is re-issued.
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: strategic-reading
3
+ description: "Reads a source (article, book, report, document) through a specific lens the owner names, and produces both a faithful summary and an applied playbook. Triggers when the owner says 'read this through the lens of X', 'apply this to my problem', 'extract a playbook for Y from this', 'what can I learn from this about Z'."
4
+ ---
5
+
6
+ # Strategic reading
7
+
8
+ This skill reads a document with a specific question in mind. The owner names the lens (a project, a problem, a goal). The skill summarises what the source actually says, then translates each section into how it applies to the named lens, and closes with a playbook of three to seven concrete steps. Both halves are grounded: the left half in the source text, the right half in the graph.
9
+
10
+ ## When to run
11
+
12
+ Run when the owner has a specific problem and wants to test what a particular source teaches them about it. Not for general reading; for applied reading. The trigger phrases are above.
13
+
14
+ ## Inputs
15
+
16
+ | Input | Meaning |
17
+ |---|---|
18
+ | `source` | The text to read. Path to a file, a URL, or pasted text. |
19
+ | `lens` | The named focus. A `:Project`, a `:Goal`, a problem statement in the owner's words, or an entity in the graph the owner wants to apply the source to. |
20
+
21
+ If `lens` is missing, ask once: "Through which lens: a project, a goal, or a problem statement?".
22
+
23
+ ## Method
24
+
25
+ 1. **Confirm the source.** Read or fetch it. If it cannot be read, refuse; do not paraphrase from training memory.
26
+ 2. **Resolve the lens.** If the lens is a named entity, `memory-search` for it and pull its current state, recent obstacles, related entities. If the lens is a free-text problem, capture it verbatim; it is the question every section will be tested against.
27
+ 3. **Walk the source in sections.** Section boundaries are the source's own headings. For each section, two paragraphs:
28
+ - **The section.** One paragraph: what it claims and what its evidence is. Quote verbatim only when the wording matters.
29
+ - **Applied to <lens>.** One paragraph: how the section's claim helps or hurts the lens. Use graph specifics. Name entities. Do not write "this could apply" or "consider how this might"; write the specific implication for the specific lens.
30
+ 4. **Produce the playbook.** After the last section, compose a single list of three to seven concrete actions the owner could take. Each action is imperative, names a specific next step, and (where possible) names the entity it touches.
31
+ 5. **Save the result.** Compose the whole pack as one `:KnowledgeDocument` linked to the lens's underlying entity via `INFORMS` (or `REFERENCES` if `INFORMS` is not in the live ontology).
32
+
33
+ ## Output format
34
+
35
+ ```
36
+ # Strategic reading: <source title> for <lens>
37
+
38
+ ## Lens
39
+ <one-paragraph restatement of the lens, including the graph context the skill loaded>
40
+
41
+ ## Section 1: <section heading>
42
+
43
+ **The section.** <one paragraph on the source's claim>
44
+
45
+ **Applied to <lens>.** <one paragraph on the implication for this owner>
46
+
47
+ ## Section 2: ...
48
+
49
+ ## Playbook
50
+ 1. <imperative action, names entity>
51
+ 2. <imperative action, names entity>
52
+ ... (three to seven items)
53
+ ```
54
+
55
+ Render the pack via `render-component name: document-editor` for review before save.
56
+
57
+ ## Difference from book-mirror
58
+
59
+ Book mirror walks every chapter and produces a chapter-by-chapter application: the unit of work is the chapter. Strategic reading uses the source's own sections and is filtered by a specific question: the unit of work is the section, and the filter is the lens. A book mirrored is a personalised version of the whole book. A source read strategically is the answer to one question about that source.
60
+
61
+ ## Failure modes
62
+
63
+ - **Lens resolves to an entity with no graph context.** Surface the gap and ask whether to proceed with the lens as a free-text problem instead.
64
+ - **Source covers a topic the lens does not touch.** Each section's right-hand column will read as "this section does not apply directly to <lens>". Surface this pattern after section 3; the owner may want to abandon the read or change the lens.
65
+ - **Source is shorter than three sections** (a short blog post, a one-page memo). Use paragraph boundaries instead of section boundaries. If the source is fewer than 200 words, do not run; the owner can read it themselves faster than the skill can mirror it.
66
+
67
+ ## What this skill does not do
68
+
69
+ It does not produce a critical review of the source. It does not score the source. It does not compare it against other sources. It produces one specific output: one source read with one lens, ending in one playbook.
@@ -45,8 +45,8 @@ After install, the first time you open the admin URL, {{productName}} walks you
45
45
 
46
46
  - `seed-neo4j.sh` writes the node at install time with `currentStep=0`. The installer re-reads it before exiting; a missing node or an unreachable Neo4j fails the install loudly (`[install-invariant] onboarding-state-MISSING` or `onboarding-state-UNREACHABLE`).
47
47
  - Every admin session-create reads `currentStep`. Anything below 9 keeps `onboarding_complete=false` on `/api/health` and `/api/admin/session`, and the chat opens on the next step's component (multi-select, dropdown, etc.).
48
- - The first input on a freshly-spawned admin claude session is prepended with an `<onboarding-state currentStep="N">` directive that tells the agent to call `skill-load skillName=onboarding`. Resumed sessions skip this prepend so the agent doesn't re-ask the same step.
49
- - If Neo4j is unreachable at session-create, the prepend becomes a loud-fail block (`graphUnreachable="true"`) and `onboarding_complete` is reported false — never silently skipped.
48
+ - Every freshly-spawned admin claude session ships the `<onboarding-state currentStep="N">` directive as a third sentinel-wrapped section in `--append-system-prompt` (alongside `<host>` and `<attachment-ceiling>`). The agent's first turn calls `skill-load skillName=onboarding`. Resumed sessions skip the section so the agent doesn't re-ask the same step. (Task 043 — pre-fix the directive was prepended to the first user message; the Claude CLI's Ink TextInput interpreted each `\n` in the block as Enter, dropping the directive bytes before they reached the agent. The system prompt is the only multi-line-safe surface for PTY-spawned Claude Code.)
49
+ - If Neo4j is unreachable at session-create, the section becomes a loud-fail block (`graphUnreachable="true"`) and `onboarding_complete` is reported false — never silently skipped.
50
50
 
51
51
  Diagnostic command on the Pi (substitute the brand's Neo4j port from `~/.maxy/.env` or `~/.realagent/.env`):
52
52
 
@@ -61,6 +61,7 @@ Failure signals to grep in `~/.maxy/logs/server.log` (or `~/.realagent/logs/serv
61
61
  - `[install-invariant] onboarding-state-MISSING`
62
62
  - `[onboarding-gate] step=null complete=true` (the pre-Task-033 bug)
63
63
  - missing `[skill-load] name=onboarding` while `[onboarding-gate]` reports `complete=false`
64
+ - missing `[onboarding-prompt] step=<n|missing|graph-unreachable> bytes=<n>` for a fresh spawn whose `[pty-spawn] appendSystemPromptBytes=` is at the bare 622-byte host + ceiling size (Task 043 — the onboarding directive failed to ship in the system prompt)
64
65
 
65
66
  ## Service Management
66
67
 
@@ -69,6 +69,8 @@ The admin interface is a three-pane layout: a sidebar on the left with your bran
69
69
 
70
70
  Page titles are brand-aware: the browser tab shows your product name (e.g. `Real Agent` instead of `Maxy`) on every shell — chat, graph, and data — so a non-default brand never leaks the default name in tab strips or browser history.
71
71
 
72
+ **Sidebar sessions list — 3s poll contract.** The sidebar Sessions list and the ConversationsModal share one fetch loop (`useAdminSessions`). It hits `/api/admin/claude-sessions` every 3s while the operator is signed in, but the poll path is render-quiet: `setLoading` is not toggled, and the sessions array is only re-committed when the projection `{ sessionId, displayName, lastMessageAt, status }` actually changes. Byte-identical responses do nothing visible to React. Each tick emits exactly one diagnostic line: `[admin-ui] sessions-poll outcome=<unchanged|changed|error> count=<n> cacheKey=<8>` (in the browser DevTools console; mirrored to `~/.maxy/logs/admin-ui-console.log` where the operator forwards them). The explicit operator-initiated paths — first load (`ensureLoaded`) and post-action `refetch()` (after spawn / delete) — still toggle `loading` so consumers can show a spinner. The 3s manager-truth reconciliation is unchanged; only the React-side noise was removed.
73
+
72
74
  The Data search panel ranks results by combining vector similarity with keyword (BM25) matching. Each row shows a one-line score breakdown — `vector 0.NN · bm25 0.NN · combined 0.NN` — so you can tell whether a row surfaced because of meaning, exact-keyword match, or both. A bm25 column of `0.00` across every row means your search term wasn't in the keyword index, so ranking fell back to pure vector similarity (this can produce surprising results — the breakdown tells you when to interpret with caution). Above the result list, a chip row shows the unique types in your current results — click one to filter, click again to clear. Click any row to jump straight to that node's neighbourhood in the Graph; from the artefact pane the graph opens alongside chat, from the standalone Data page it opens in place.
73
75
 
74
76
  ## Software Update and Cloudflare Setup
@@ -530,3 +530,15 @@ sudo systemctl --user start maxy-ui
530
530
  **Installer aborted with "identity-match FAILED":** Multi-account installs where no sibling matches `users.json[0].userId` abort loud — the installer refuses to pick one and refuses to sweep. Resolution: inspect `account.json` in each candidate dir (listed in the abort output), identify the correct owner, move the other(s) aside manually, then re-run the installer.
531
531
 
532
532
  **A chat turn looks broken — assistant bubble never rendered:** Open `claude-agent-stream-<sessionKey>.log` and grep for `[sse-client]`. The five phases (`connected`, `event_received`, `render_complete`, `error`, `close`) tell the story in order. Missing `connected` = the chat fetch never returned 200; missing `event_received` = the server emitted nothing or the client lost the stream before the first frame; missing `render_complete` = the reducer never committed the assistant bubble (persist_ack never arrived). The operator can also click "Report this turn" in the chat menu to append a `[failure-report]` line carrying the same sessionKey + conversationId + clientSnapshot, plus copy the payload to the clipboard.
533
+
534
+ ## Admin DevTools console floods with `onboarding-banner-mount` or unsorted `sessions-poll` lines
535
+
536
+ **Symptom:** Open DevTools on the admin shell at `/` with `onboardingComplete=false`, leave the page idle for a minute or two, then scroll back through the console. Pre-Task-050 you would see thousands of `[admin-ui] onboarding-banner-mount onboardingComplete=false` lines (one per AdminShell render — roughly 40/min from the 3s sessions poll alone) and no per-tick poll telemetry at all.
537
+
538
+ **Post-Task-050 invariants (steady-state idle at `/`):**
539
+
540
+ - `grep -c '\[admin-ui\] onboarding-banner-mount' ~/.maxy/logs/admin-ui-console.log` equals page-load count plus onboarding-flip count, not the render count. Sustained climb at idle ⇒ the banner mount log regressed back into the render body.
541
+ - `grep -c '\[admin-ui\] sessions-poll' ~/.maxy/logs/admin-ui-console.log` grows ~20/min (one per 3s tick) and `outcome=unchanged` dominates `outcome=changed` once the cache is warm. `outcome=changed` every idle tick ⇒ the `useAdminSessions` projection (`sessionId / displayName / lastMessageAt / status`) is missing a field that is churning on every fetch, or a downstream component is mutating the response in place before comparison.
542
+ - `outcome=error` lines name a real fetch failure — they do NOT update sidebar state and do NOT set the `error` field (the operator-initiated `refetch()` still owns that channel).
543
+
544
+ **Why this matters.** The render-body log was misleading: it read as "the admin agent is checking onboarding state continuously", when in fact `onboardingComplete` had not changed at all — it was just the sessions poll re-rendering AdminShell twice per tick. With the structured poll line in place, the console is a faithful record of what the page actually did each tick.
@@ -2,15 +2,24 @@
2
2
  name: email
3
3
  description: "Email — dedicated email account. Retrieval: email-graph-query for stored email history, recall, and search ('what emails are in memory?', 'emails about X', 'what did Y send?'); email-read / email-search for live IMAP inbox. Sending: email-send (new), email-reply (threaded). Config: email-setup, email-status, email-auto-respond-config, email-otp-extract."
4
4
  tools:
5
- - email-setup
6
- - email-read
7
- - email-send
8
- - email-reply
9
- - email-search
10
- - email-graph-query
11
- - email-otp-extract
12
- - email-status
13
- - email-auto-respond-config
5
+ - name: email-setup
6
+ publicAllowlist: false
7
+ - name: email-read
8
+ publicAllowlist: false
9
+ - name: email-send
10
+ publicAllowlist: false
11
+ - name: email-reply
12
+ publicAllowlist: false
13
+ - name: email-search
14
+ publicAllowlist: false
15
+ - name: email-graph-query
16
+ publicAllowlist: false
17
+ - name: email-otp-extract
18
+ publicAllowlist: false
19
+ - name: email-status
20
+ publicAllowlist: false
21
+ - name: email-auto-respond-config
22
+ publicAllowlist: false
14
23
  always: false
15
24
  embed: ["admin"]
16
25
  metadata: {"platform":{}}
@@ -0,0 +1,17 @@
1
+ export interface DispatchInput {
2
+ accountId: string;
3
+ senderEmail: string;
4
+ text: string;
5
+ timeoutMs: number;
6
+ }
7
+ export type DispatchResult = {
8
+ turnText: string;
9
+ } | {
10
+ error: string;
11
+ };
12
+ /** Send an email body to the per-sender claude PTY session, await the
13
+ * next assistant end_turn, return the response text. Reuses the session
14
+ * across cron invocations via the manager's senderId index. */
15
+ export declare function dispatchEmailToClaude(input: DispatchInput): Promise<DispatchResult>;
16
+ export declare function emailTurnTimeoutMs(): number;
17
+ //# sourceMappingURL=claude-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-bridge.d.ts","sourceRoot":"","sources":["../../src/lib/claude-bridge.ts"],"names":[],"mappings":"AAmDA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA8HtE;;gEAEgE;AAChE,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAqCzF;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
@@ -0,0 +1,185 @@
1
+ // Email → claude PTY bridge.
2
+ //
3
+ // Task 004 Track B. The email-auto-respond cron script dispatches each
4
+ // inbound email through this module: find-or-spawn a per-sender PTY
5
+ // session via the loopback claude-session-manager, write the email text
6
+ // to the session's PTY stdin, follow claude's per-session JSONL until
7
+ // `stop_reason: "end_turn"`, return the assistant turn text. The cron
8
+ // script then SMTPs the response.
9
+ //
10
+ // This module lives inside the email plugin's MCP source (not under
11
+ // platform/ui/app/lib/) because the cron script is a separate Node
12
+ // process — it cannot share in-process state with the platform/ui
13
+ // channel-pty-bridge instance. Each cron invocation queries the manager
14
+ // for the existing session via `GET /list?senderId=...` rather than
15
+ // caching it in memory.
16
+ //
17
+ // Doctrine references:
18
+ // - Manager HTTP contract: ../../../../services/claude-session-manager/src/http-server.ts
19
+ // - Shared bridge core (in-process, used by whatsapp / webchat):
20
+ // ../../../../../ui/app/lib/channel-pty-bridge/
21
+ // - Task 004 brief: maxy-code/.tasks/004-channel-adaptors-rest.md
22
+ const TAG = "[email-adaptor]";
23
+ function managerBase() {
24
+ const port = Number(process.env.CLAUDE_SESSION_MANAGER_PORT ?? "19400");
25
+ return `http://127.0.0.1:${port}`;
26
+ }
27
+ // ─── Manager HTTP ─────────────────────────────────────────────────────
28
+ async function findExistingSession(senderId) {
29
+ try {
30
+ const res = await fetch(`${managerBase()}/list?senderId=${encodeURIComponent(senderId)}`);
31
+ if (!res.ok)
32
+ return null;
33
+ const sessions = (await res.json());
34
+ const alive = sessions.find((s) => s.status === "alive" && s.channel === "email");
35
+ return alive?.sessionId ?? null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ async function spawnSession(opts) {
42
+ try {
43
+ const res = await fetch(`${managerBase()}/spawn`, {
44
+ method: "POST",
45
+ headers: { "content-type": "application/json" },
46
+ body: JSON.stringify({
47
+ senderId: opts.senderId,
48
+ role: "public",
49
+ channel: "email",
50
+ accountId: opts.accountId,
51
+ }),
52
+ });
53
+ if (!res.ok) {
54
+ console.error(`${TAG} reject reason=spawn-failed senderId=${opts.senderId} status=${res.status}`);
55
+ return null;
56
+ }
57
+ const body = (await res.json());
58
+ return body.sessionId;
59
+ }
60
+ catch (err) {
61
+ const m = err instanceof Error ? err.message : String(err);
62
+ console.error(`${TAG} reject reason=spawn-unreachable senderId=${opts.senderId} message=${m}`);
63
+ return null;
64
+ }
65
+ }
66
+ async function writeInput(sessionId, text) {
67
+ try {
68
+ const res = await fetch(`${managerBase()}/${sessionId}/input`, {
69
+ method: "POST",
70
+ headers: { "content-type": "application/json" },
71
+ body: JSON.stringify({ text }),
72
+ });
73
+ return res.ok;
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ }
79
+ // ─── JSONL follower (one-shot, waits for next end_turn) ──────────────
80
+ async function awaitNextTurn(sessionId, timeoutMs) {
81
+ const abort = new AbortController();
82
+ const timeoutHandle = setTimeout(() => abort.abort(), timeoutMs);
83
+ try {
84
+ const res = await fetch(`${managerBase()}/${sessionId}/log?follow=1`, { signal: abort.signal });
85
+ if (!res.ok || !res.body) {
86
+ return { error: `follow-status-${res.status}` };
87
+ }
88
+ const reader = res.body.getReader();
89
+ const decoder = new TextDecoder("utf8");
90
+ let buffered = "";
91
+ let turnText = "";
92
+ while (!abort.signal.aborted) {
93
+ const { value, done } = await reader.read();
94
+ if (done)
95
+ break;
96
+ buffered += decoder.decode(value, { stream: true });
97
+ let nl = buffered.indexOf("\n");
98
+ while (nl !== -1) {
99
+ const line = buffered.slice(0, nl);
100
+ buffered = buffered.slice(nl + 1);
101
+ nl = buffered.indexOf("\n");
102
+ if (!line)
103
+ continue;
104
+ let event;
105
+ try {
106
+ event = JSON.parse(line);
107
+ }
108
+ catch {
109
+ continue;
110
+ }
111
+ if (event.type === "user") {
112
+ turnText = "";
113
+ continue;
114
+ }
115
+ if (event.type !== "assistant")
116
+ continue;
117
+ const msg = event.message;
118
+ if (!msg)
119
+ continue;
120
+ if (Array.isArray(msg.content)) {
121
+ for (const block of msg.content) {
122
+ if (block?.type === "text" && typeof block.text === "string") {
123
+ turnText += block.text;
124
+ }
125
+ }
126
+ }
127
+ if (msg.stop_reason === "end_turn") {
128
+ if (turnText.trim()) {
129
+ // Abort the stream so the manager closes the follower
130
+ // immediately; we have our turn.
131
+ abort.abort();
132
+ return { turnText };
133
+ }
134
+ turnText = "";
135
+ }
136
+ }
137
+ }
138
+ return { error: abort.signal.aborted ? "timeout" : "stream-closed" };
139
+ }
140
+ catch (err) {
141
+ if (abort.signal.aborted)
142
+ return { error: "timeout" };
143
+ return { error: err instanceof Error ? err.message : String(err) };
144
+ }
145
+ finally {
146
+ clearTimeout(timeoutHandle);
147
+ }
148
+ }
149
+ // ─── Public dispatch ─────────────────────────────────────────────────
150
+ /** Send an email body to the per-sender claude PTY session, await the
151
+ * next assistant end_turn, return the response text. Reuses the session
152
+ * across cron invocations via the manager's senderId index. */
153
+ export async function dispatchEmailToClaude(input) {
154
+ if (!input.text.trim())
155
+ return { error: "empty-text" };
156
+ const bytes = Buffer.byteLength(input.text, "utf8");
157
+ console.error(`${TAG} inbound from=${input.senderEmail} bytes=${bytes} accountId=${input.accountId}`);
158
+ let sessionId = await findExistingSession(input.senderEmail);
159
+ let action = "reuse";
160
+ if (!sessionId) {
161
+ action = "spawn";
162
+ sessionId = await spawnSession({ senderId: input.senderEmail, accountId: input.accountId });
163
+ if (!sessionId)
164
+ return { error: "spawn-failed" };
165
+ }
166
+ console.error(`${TAG} session-resolved senderId=${input.senderEmail} action=${action} sessionId=${sessionId.slice(0, 8)}`);
167
+ const writeOk = await writeInput(sessionId, input.text);
168
+ if (!writeOk) {
169
+ console.error(`${TAG} reject reason=input-failed senderId=${input.senderEmail} sessionId=${sessionId.slice(0, 8)}`);
170
+ return { error: "input-failed" };
171
+ }
172
+ const startedAt = Date.now();
173
+ const result = await awaitNextTurn(sessionId, input.timeoutMs);
174
+ const idleMs = Date.now() - startedAt;
175
+ if ("error" in result) {
176
+ console.error(`${TAG} reject reason=turn-${result.error} senderId=${input.senderEmail} sessionId=${sessionId.slice(0, 8)} idle-ms=${idleMs}`);
177
+ return result;
178
+ }
179
+ console.error(`${TAG} outbound to=${input.senderEmail} bytes=${Buffer.byteLength(result.turnText, "utf8")} sessionId=${sessionId.slice(0, 8)} idle-ms=${idleMs}`);
180
+ return result;
181
+ }
182
+ export function emailTurnTimeoutMs() {
183
+ return Number(process.env.EMAIL_POLL_TURN_TIMEOUT_MS ?? String(10 * 60_000));
184
+ }
185
+ //# sourceMappingURL=claude-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-bridge.js","sourceRoot":"","sources":["../../src/lib/claude-bridge.ts"],"names":[],"mappings":"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"}
@@ -134,7 +134,7 @@ export declare function searchMessages(config: EmailConfig, password: string, qu
134
134
  beforeUid?: number;
135
135
  }): Promise<PaginatedMessages>;
136
136
  /**
137
- * Result from an incremental email fetch for the polling cron.
137
+ * Result from an incremental email fetch performed by the email-fetch dispatcher.
138
138
  * Includes the raw envelope data needed for graph storage (not just display).
139
139
  */
140
140
  export interface FetchedEmail {