@rubytech/create-maxy-code 0.1.295 → 0.1.297
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.
- package/package.json +1 -1
- package/payload/platform/lib/models/dist/index.d.ts +1 -0
- package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/models/dist/index.js +4 -2
- package/payload/platform/lib/models/dist/index.js.map +1 -1
- package/payload/platform/lib/models/src/index.ts +3 -1
- package/payload/platform/neo4j/schema.cypher +10 -2
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-compliance.test.sh +27 -0
- package/payload/platform/plugins/admin/hooks/prompt-optimiser-compliance.sh +24 -5
- package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/admin/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -13
- package/payload/platform/plugins/aeo/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/browser/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/browser/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/contacts/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/docs/references/getting-started.md +1 -1
- package/payload/platform/plugins/docs/references/platform.md +1 -11
- package/payload/platform/plugins/email/.claude-plugin/plugin.json +6 -2
- package/payload/platform/plugins/email/PLUGIN.md +6 -2
- package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/email/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js +75 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js +58 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js +74 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js +69 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js +46 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.js +56 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.js +46 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/index.js +44 -0
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +16 -3
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js +62 -5
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts +42 -0
- package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js +72 -0
- package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +16 -6
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +37 -20
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js +1 -2
- package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts +13 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js +45 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +2 -8
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +25 -3
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +15 -0
- package/payload/platform/plugins/email/skills/email-composition/SKILL.md +15 -4
- package/payload/platform/plugins/memory/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/memory/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js +214 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js +113 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +52 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +90 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +3 -0
- package/payload/platform/plugins/memory/references/schema-base.md +6 -2
- package/payload/platform/plugins/memory/references/schema-construction.md +8 -6
- package/payload/platform/plugins/memory/references/schema-estate-agent.md +1 -1
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/replicate/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/scheduling/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/telegram/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/whatsapp/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/work/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/work/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/workflows/.claude-plugin/plugin.json +5 -1
- package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/scripts/smoke-boot-services.sh +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.d.ts +10 -0
- package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.d.ts.map +1 -0
- package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.js +70 -0
- package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.js.map +1 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +10 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +15 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts +6 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +38 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/templates/account.json +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/premium-plugins/writer-craft/.claude-plugin/plugin.json +5 -1
- package/payload/premium-plugins/writer-craft/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/premium-plugins/writer-craft/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/server/public/assets/AdminShell-DpjiG4KO.js +1 -0
- package/payload/server/public/assets/{Checkbox-DTrIyIFP.js → Checkbox-o5EbM1Sd.js} +1 -1
- package/payload/server/public/assets/{Transcript-C3aDVJ-n.js → Transcript-B-roO2vK.js} +1 -1
- package/payload/server/public/assets/{admin-DVdyV-Q6.js → admin-DmBG61gA.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DR9W0q1P.js → architectureDiagram-Q4EWVU46-DCLfcVZf.js} +1 -1
- package/payload/server/public/assets/{audio-attachment-mime-DGEfApkA.js → audio-attachment-mime-D_YMUIBb.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-C3uwaI7p.js → blockDiagram-DXYQGD6D-DtTb6oGR.js} +1 -1
- package/payload/server/public/assets/{browser-DrJReVEG.js → browser-DPqQnY8B.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-C8hmUDdd.js → c4Diagram-AHTNJAMY-DHMgkbse.js} +1 -1
- package/payload/server/public/assets/channel-BGB5Q-QM.js +1 -0
- package/payload/server/public/assets/chat-BpceL2qA.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-BRCubMCb.js → chunk-336JU56O-DQja-fc4.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-BNINkVsL.js → chunk-426QAEUC-uBZXKz4Z.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DSMj_AZh.js → chunk-4TB4RGXK-DViPFnGL.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-6DNGaUkf.js → chunk-5FUZZQ4R-CdKJ7vdW.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-DPhkkS4p.js → chunk-5PVQY5BW-BIJiayBe.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-BjWSqn7_.js → chunk-EDXVE4YY-CDDqx-TB.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-BX1ZnU4A.js → chunk-ENJZ2VHE-BVNFvue5.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-DvYSWH7x.js → chunk-ICPOFSXX-DEZQolUW.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-7_m3mEOK.js → chunk-OYMX7WX6-Dn0reHna.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-Bl1a895I.js → chunk-U2HBQHQK-sqMpBHaS.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-WkSpBPYx.js → chunk-X2U36JSP-ByhTOa14.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-DpWRmPUo.js → chunk-YZCP3GAM-CGo_et0d.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-D9Dgmeso.js → chunk-ZZ45TVLE-B9aPwq_o.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-DdUR3hKH.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B0ZE2WR0.js +1 -0
- package/payload/server/public/assets/clone-B5aO4uPo.js +1 -0
- package/payload/server/public/assets/{dagre-PrVfCcSt.js → dagre-DE88U4Vk.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-DPq3dcLH.js → dagre-KV5264BT-oeoQWi1f.js} +1 -1
- package/payload/server/public/assets/data-6mvcS2_6.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-DoszElKb.js → diagram-5BDNPKRD-HmWmPhlY.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BRuqosix.js → diagram-G4DWMVQ6-Bkao4d6n.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-CpigG1d_.js → diagram-MMDJMWI5-Eh2fnSb-.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-BS0eYiq9.js → diagram-TYMM5635-C8705_ZE.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-VEQyXCFl.js → erDiagram-SMLLAGMA-Bkhe0ZPv.js} +1 -1
- package/payload/server/public/assets/{file-download-C3pBZjt9.js → file-download-DVUMxBgB.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-2NYMfqHX.js → flowDiagram-DWJPFMVM-rQKH0HF0.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-AAAa2sqE.js → ganttDiagram-T4ZO3ILL-C3oSBbAe.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-d8NUAIz5.js → gitGraphDiagram-UUTBAWPF-28GEOzIR.js} +1 -1
- package/payload/server/public/assets/{graph-Bx9_2qbJ.js → graph-B5R9qDya.js} +1 -1
- package/payload/server/public/assets/{graph-labels-Cc1nU1_f.js → graph-labels-Bcq_R9X9.js} +1 -1
- package/payload/server/public/assets/{graphlib-DUlqr2mr.js → graphlib-DhAwTSya.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-D4dh4-0g.js → infoDiagram-42DDH7IO-DnSzN29F.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DPTmm2IE.js → ishikawaDiagram-UXIWVN3A-B0mYhBS0.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-B85vjqkE.js → journeyDiagram-VCZTEJTY-CIcZskca.js} +1 -1
- package/payload/server/public/assets/{jsx-runtime-D3PZpOAF.css → jsx-runtime-DqAwfhuD.css} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-C2Lfb5Xh.js → kanban-definition-6JOO6SKY-DWEpWX0D.js} +1 -1
- package/payload/server/public/assets/{line-CODKFpwO.js → line-D6evlE4c.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DYdFZnXH.js → mermaid-parser.core-DyRhDebz.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-Bamjzahu.js → mermaid.core-DaD391Xr.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CLK90bKJ.js → mindmap-definition-QFDTVHPH-D7IMib-k.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-DEsnxhqP.js → pieDiagram-DEJITSTG-CyOSJozN.js} +1 -1
- package/payload/server/public/assets/{public-BFMu-jux.js → public-Cj7vjoG1.js} +5 -5
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-uIP9V2jZ.js → quadrantDiagram-34T5L4WZ-CHWWRW-7.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-CVS6t5tv.js → requirementDiagram-MS252O5E-x4-mHKrQ.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BIsmtyZA.js → sankeyDiagram-XADWPNL6-DvKrAe78.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-Cu8TfQiW.js → sequenceDiagram-FGHM5R23-DW778VnP.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-ax4vYGft.js → stateDiagram-FHFEXIEX-DVnPPuE8.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B3nWH_hq.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-3l7ojkMA.js → timeline-definition-GMOUNBTQ-CO4Sp85K.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-C_EBRd2k.js → useSelectionMode-BK4pznA6.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-C_sv0qMD.js → vennDiagram-DHZGUBPP-OCcztoT8.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7u4IHMB.js → wardleyDiagram-NUSXRM2D-C_1o3jux.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-A-uLXr1a.js → xychartDiagram-5P7HB3ND-BPJxl9U1.js} +1 -1
- package/payload/server/public/browser.html +6 -6
- package/payload/server/public/chat.html +8 -8
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +8 -8
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +6 -6
- package/payload/server/public/whatsapp-wallpaper.webp +0 -0
- package/payload/server/server.js +6 -2
- package/payload/server/public/assets/AdminShell-DDieHnzi.js +0 -1
- package/payload/server/public/assets/channel-drVqp11B.js +0 -1
- package/payload/server/public/assets/chat-DeEYwIKE.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Dplkw_pj.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-sJXv1Ihp.js +0 -1
- package/payload/server/public/assets/clone-Q_B6oO0c.js +0 -1
- package/payload/server/public/assets/data-CYyR2m_B.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BRv1By5g.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-5auA0FEj.js → jsx-runtime-CynkhuPm.js} +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
const { appendDraftMock, sendEmailMock } = vi.hoisted(() => ({
|
|
3
|
+
appendDraftMock: vi.fn(async () => ({ folder: "[Gmail]/Drafts", uid: 27675 })),
|
|
4
|
+
sendEmailMock: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
vi.mock("../lib/imap.js", () => ({ appendDraft: appendDraftMock }));
|
|
7
|
+
vi.mock("../lib/smtp.js", async (importOriginal) => {
|
|
8
|
+
const actual = await importOriginal();
|
|
9
|
+
// Real buildMailOptions/formatCopyNote (the shared composer under test);
|
|
10
|
+
// sendEmail mocked so any SMTP call on the draft path is a test failure.
|
|
11
|
+
return { ...actual, sendEmail: sendEmailMock };
|
|
12
|
+
});
|
|
13
|
+
vi.mock("../lib/credentials.js", () => ({
|
|
14
|
+
loadCredentials: vi.fn(async () => ({
|
|
15
|
+
credentials: {
|
|
16
|
+
config: { email: "agent@example.com", agentAddress: "agent@example.com" },
|
|
17
|
+
password: "pw",
|
|
18
|
+
},
|
|
19
|
+
})),
|
|
20
|
+
}));
|
|
21
|
+
import { emailDraft } from "../tools/email-draft.js";
|
|
22
|
+
describe("Task 815 — email-draft tool", () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.clearAllMocks();
|
|
25
|
+
});
|
|
26
|
+
it("composes MIME and appends once to Drafts; never touches SMTP", async () => {
|
|
27
|
+
const text = await emailDraft({
|
|
28
|
+
accountId: "acc-1",
|
|
29
|
+
to: "joel@example.com",
|
|
30
|
+
subject: "Quote follow-up",
|
|
31
|
+
body: "Please review.",
|
|
32
|
+
});
|
|
33
|
+
expect(appendDraftMock).toHaveBeenCalledTimes(1);
|
|
34
|
+
const [, , raw] = appendDraftMock.mock.calls[0];
|
|
35
|
+
const mime = raw.toString();
|
|
36
|
+
expect(mime).toContain("To: joel@example.com");
|
|
37
|
+
expect(mime).toContain("Subject: Quote follow-up");
|
|
38
|
+
expect(mime).toContain("From: agent@example.com");
|
|
39
|
+
expect(mime).toContain("Please review.");
|
|
40
|
+
expect(sendEmailMock).not.toHaveBeenCalled();
|
|
41
|
+
expect(text).toContain("[Gmail]/Drafts");
|
|
42
|
+
expect(text).toContain("27675");
|
|
43
|
+
expect(text).toContain("joel@example.com");
|
|
44
|
+
});
|
|
45
|
+
it("preserves the Bcc header in the draft bytes (keepBcc — the stored draft is the only recipient carrier)", async () => {
|
|
46
|
+
await emailDraft({
|
|
47
|
+
accountId: "acc-1",
|
|
48
|
+
to: "joel@example.com",
|
|
49
|
+
subject: "s",
|
|
50
|
+
body: "b",
|
|
51
|
+
cc: ["copy@example.com"],
|
|
52
|
+
bcc: ["hidden@example.com"],
|
|
53
|
+
});
|
|
54
|
+
const [, , raw] = appendDraftMock.mock.calls[0];
|
|
55
|
+
const mime = raw.toString();
|
|
56
|
+
expect(mime).toMatch(/^Cc: copy@example\.com/m);
|
|
57
|
+
expect(mime).toMatch(/^Bcc: hidden@example\.com/m);
|
|
58
|
+
});
|
|
59
|
+
it("reports when the server did not return an APPENDUID", async () => {
|
|
60
|
+
appendDraftMock.mockResolvedValueOnce({ folder: "Drafts", uid: null });
|
|
61
|
+
const text = await emailDraft({
|
|
62
|
+
accountId: "acc-1",
|
|
63
|
+
to: "joel@example.com",
|
|
64
|
+
subject: "s",
|
|
65
|
+
body: "b",
|
|
66
|
+
});
|
|
67
|
+
expect(text).toContain("Drafts");
|
|
68
|
+
expect(text).toContain("UID not reported");
|
|
69
|
+
});
|
|
70
|
+
it("surfaces the no-Drafts-folder error verbatim", async () => {
|
|
71
|
+
appendDraftMock.mockRejectedValueOnce(new Error("Drafts folder not found for agent@example.com — the server does not advertise a \\Drafts special-use folder, so the draft cannot be stored."));
|
|
72
|
+
await expect(emailDraft({ accountId: "acc-1", to: "j@x.y", subject: "s", body: "b" })).rejects.toThrow(/Drafts folder not found for agent@example\.com/);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=email-draft.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-draft.test.js","sourceRoot":"","sources":["../../src/__tests__/email-draft.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,6 +35,19 @@ describe("email-setup short-circuits Microsoft addresses", () => {
|
|
|
35
35
|
expect(smtp.testConnection).not.toHaveBeenCalled();
|
|
36
36
|
expect(resolveMx).not.toHaveBeenCalled();
|
|
37
37
|
});
|
|
38
|
+
it("emits an op=request and op=result outcome=fail lifeline even on the redirect path", async () => {
|
|
39
|
+
const writes = [];
|
|
40
|
+
const spy = vi.spyOn(process.stderr, "write").mockImplementation((s) => { writes.push(String(s)); return true; });
|
|
41
|
+
const result = await emailSetup({
|
|
42
|
+
email: "agent@outlook.com",
|
|
43
|
+
password: "irrelevant",
|
|
44
|
+
accountId: "acct-1",
|
|
45
|
+
});
|
|
46
|
+
spy.mockRestore();
|
|
47
|
+
expect(result.success).toBe(false);
|
|
48
|
+
expect(writes.some((l) => l.includes("[email] setup-probe op=request") && l.includes("domain=outlook.com"))).toBe(true);
|
|
49
|
+
expect(writes.some((l) => l.includes("op=result") && l.includes("outcome=fail"))).toBe(true);
|
|
50
|
+
});
|
|
38
51
|
it("refuses an M365 custom domain detected by MX, even with hosts supplied", async () => {
|
|
39
52
|
resolveMx.mockResolvedValue([
|
|
40
53
|
{ exchange: "contoso-com.mail.protection.outlook.com", priority: 0 },
|
|
@@ -52,4 +65,49 @@ describe("email-setup short-circuits Microsoft addresses", () => {
|
|
|
52
65
|
expect(smtp.testConnection).not.toHaveBeenCalled();
|
|
53
66
|
});
|
|
54
67
|
});
|
|
68
|
+
describe("email-setup probe lifecycle logging", () => {
|
|
69
|
+
beforeEach(() => {
|
|
70
|
+
resolveMx.mockReset();
|
|
71
|
+
imap.testConnection.mockReset();
|
|
72
|
+
imap.getInboxCount.mockReset();
|
|
73
|
+
smtp.testConnection.mockReset();
|
|
74
|
+
});
|
|
75
|
+
it("emits request → probe-imap → probe-smtp → result with one shared token", async () => {
|
|
76
|
+
const writes = [];
|
|
77
|
+
const spy = vi.spyOn(process.stderr, "write").mockImplementation((s) => { writes.push(String(s)); return true; });
|
|
78
|
+
imap.testConnection.mockResolvedValue(null);
|
|
79
|
+
smtp.testConnection.mockResolvedValue(null);
|
|
80
|
+
imap.getInboxCount.mockResolvedValue(7);
|
|
81
|
+
const result = await emailSetup({
|
|
82
|
+
email: "agent@example.org", password: "pw",
|
|
83
|
+
imapHost: "imap.example.org", smtpHost: "smtp.example.org",
|
|
84
|
+
accountId: "acct-1",
|
|
85
|
+
});
|
|
86
|
+
spy.mockRestore();
|
|
87
|
+
expect(result.success).toBe(true);
|
|
88
|
+
const probeLines = writes.filter((l) => l.includes("[email] setup-probe"));
|
|
89
|
+
const token = probeLines[0]?.match(/token=(\S+)/)?.[1];
|
|
90
|
+
expect(token).toBeTruthy();
|
|
91
|
+
expect(probeLines.some((l) => l.includes(`op=request token=${token}`) && l.includes("domain=example.org"))).toBe(true);
|
|
92
|
+
expect(probeLines.some((l) => l.includes(`op=probe-imap token=${token}`) && /ms=\d+/.test(l))).toBe(true);
|
|
93
|
+
expect(probeLines.some((l) => l.includes(`op=probe-smtp token=${token}`) && /ms=\d+/.test(l))).toBe(true);
|
|
94
|
+
expect(probeLines.some((l) => l.includes(`op=result token=${token} outcome=ok`))).toBe(true);
|
|
95
|
+
// The shared token reaches the probe helpers so acquired/released correlate.
|
|
96
|
+
expect(imap.testConnection).toHaveBeenCalledWith(expect.anything(), "pw", token);
|
|
97
|
+
expect(smtp.testConnection).toHaveBeenCalledWith(expect.anything(), "pw", token);
|
|
98
|
+
});
|
|
99
|
+
it("a failed imap probe logs outcome=fail", async () => {
|
|
100
|
+
const writes = [];
|
|
101
|
+
const spy = vi.spyOn(process.stderr, "write").mockImplementation((s) => { writes.push(String(s)); return true; });
|
|
102
|
+
imap.testConnection.mockResolvedValue("IMAP connection failed: nope");
|
|
103
|
+
const result = await emailSetup({
|
|
104
|
+
email: "agent@example.org", password: "pw",
|
|
105
|
+
imapHost: "imap.example.org", smtpHost: "smtp.example.org",
|
|
106
|
+
accountId: "acct-1",
|
|
107
|
+
});
|
|
108
|
+
spy.mockRestore();
|
|
109
|
+
expect(result.success).toBe(false);
|
|
110
|
+
expect(writes.some((l) => l.includes("op=result") && l.includes("outcome=fail"))).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
55
113
|
//# sourceMappingURL=email-setup.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-setup.test.js","sourceRoot":"","sources":["../../src/__tests__/email-setup.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE9D,gFAAgF;AAChF,yEAAyE;AACzE,8EAA8E;AAC9E,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACjE,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AAEpD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACrF,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7D,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACtC,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACtC,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;IACpB,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;IACtB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;IACrB,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACpD,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC5B,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAE/D,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,UAAU,CAAC,GAAG,EAAE;QACd,SAAS,CAAC,SAAS,EAAE,CAAC;QACtB,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,KAAK,EAAE,mBAAmB;YAC1B,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACnD,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,SAAS,CAAC,iBAAiB,CAAC;YAC1B,EAAE,QAAQ,EAAE,yCAAyC,EAAE,QAAQ,EAAE,CAAC,EAAE;SACrE,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,KAAK,EAAE,iBAAiB;YACxB,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,uBAAuB;YACjC,QAAQ,EAAE,oBAAoB;YAC9B,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"email-setup.test.js","sourceRoot":"","sources":["../../src/__tests__/email-setup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imap-drafts.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/imap-drafts.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
// Mock the imapflow module so appendDraft's internal createClient() yields our spy client.
|
|
3
|
+
const mockClient = {
|
|
4
|
+
connect: vi.fn(async () => { }),
|
|
5
|
+
list: vi.fn(async () => []),
|
|
6
|
+
append: vi.fn(async () => ({ destination: "[Gmail]/Drafts", uid: 27675 })),
|
|
7
|
+
logout: vi.fn(async () => { }),
|
|
8
|
+
close: vi.fn(() => { }),
|
|
9
|
+
};
|
|
10
|
+
vi.mock("imapflow", () => ({
|
|
11
|
+
// A constructible function — `new ImapFlow(...)` returns the spy client.
|
|
12
|
+
ImapFlow: function ImapFlow() {
|
|
13
|
+
return mockClient;
|
|
14
|
+
},
|
|
15
|
+
}));
|
|
16
|
+
import { appendDraft, resolveFolderName } from "../lib/imap.js";
|
|
17
|
+
const config = {
|
|
18
|
+
email: "agent@example.com",
|
|
19
|
+
imapHost: "imap.example.com",
|
|
20
|
+
imapPort: 993,
|
|
21
|
+
imapSecurity: "tls",
|
|
22
|
+
};
|
|
23
|
+
describe("Task 815 — resolveFolderName drafts branch", () => {
|
|
24
|
+
it("returns the \\Drafts special-use path when advertised", async () => {
|
|
25
|
+
const client = {
|
|
26
|
+
list: async () => [
|
|
27
|
+
{ path: "INBOX" },
|
|
28
|
+
{ path: "[Gmail]/Sent Mail", specialUse: "\\Sent" },
|
|
29
|
+
{ path: "[Gmail]/Drafts", specialUse: "\\Drafts" },
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
await expect(resolveFolderName(client, "drafts")).resolves.toBe("[Gmail]/Drafts");
|
|
33
|
+
});
|
|
34
|
+
it("throws a named error when no \\Drafts special-use folder is advertised", async () => {
|
|
35
|
+
const client = { list: async () => [{ path: "INBOX" }] };
|
|
36
|
+
await expect(resolveFolderName(client, "drafts")).rejects.toThrow(/\\Drafts special-use folder/);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("Task 815 — appendDraft", () => {
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
vi.clearAllMocks();
|
|
42
|
+
});
|
|
43
|
+
it("appends raw bytes to the resolved Drafts folder with the \\Draft flag and returns folder+uid", async () => {
|
|
44
|
+
mockClient.list.mockResolvedValueOnce([
|
|
45
|
+
{ path: "Drafts", specialUse: "\\Drafts" },
|
|
46
|
+
]);
|
|
47
|
+
const raw = Buffer.from("From: a@b.c\r\n\r\nbody");
|
|
48
|
+
const result = await appendDraft(config, "pw", raw);
|
|
49
|
+
expect(mockClient.append).toHaveBeenCalledTimes(1);
|
|
50
|
+
expect(mockClient.append).toHaveBeenCalledWith("Drafts", raw, ["\\Draft"]);
|
|
51
|
+
expect(result).toEqual({ folder: "Drafts", uid: 27675 });
|
|
52
|
+
expect(mockClient.logout).toHaveBeenCalled();
|
|
53
|
+
});
|
|
54
|
+
it("returns uid null when the server reports no APPENDUID (no UIDPLUS)", async () => {
|
|
55
|
+
mockClient.list.mockResolvedValueOnce([
|
|
56
|
+
{ path: "Drafts", specialUse: "\\Drafts" },
|
|
57
|
+
]);
|
|
58
|
+
mockClient.append.mockResolvedValueOnce({ destination: "Drafts" });
|
|
59
|
+
const result = await appendDraft(config, "pw", Buffer.from("x"));
|
|
60
|
+
expect(result).toEqual({ folder: "Drafts", uid: null });
|
|
61
|
+
});
|
|
62
|
+
it("does not re-brand an unrelated list() failure as a missing-Drafts error", async () => {
|
|
63
|
+
mockClient.list.mockRejectedValueOnce(new Error("connection reset by peer"));
|
|
64
|
+
await expect(appendDraft(config, "pw", Buffer.from("x"))).rejects.toThrow(/connection reset by peer/);
|
|
65
|
+
expect(mockClient.append).not.toHaveBeenCalled();
|
|
66
|
+
});
|
|
67
|
+
it("names the mailbox in the no-Drafts error and still logs out", async () => {
|
|
68
|
+
mockClient.list.mockResolvedValueOnce([{ path: "INBOX" }]);
|
|
69
|
+
await expect(appendDraft(config, "pw", Buffer.from("x"))).rejects.toThrow(/agent@example\.com/);
|
|
70
|
+
expect(mockClient.append).not.toHaveBeenCalled();
|
|
71
|
+
expect(mockClient.logout).toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=imap-drafts.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imap-drafts.test.js","sourceRoot":"","sources":["../../src/__tests__/imap-drafts.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imap-probe.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/imap-probe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
// Fake ImapFlow: an EventEmitter with controllable connect/logout/close.
|
|
4
|
+
// Each test arms the mock (mockImplementationOnce) BEFORE invoking the
|
|
5
|
+
// function under test, then drives the late-socket-event simulation by
|
|
6
|
+
// emitting 'error' on the captured client after the probe has resolved.
|
|
7
|
+
const state = vi.hoisted(() => ({ clients: [] }));
|
|
8
|
+
vi.mock("imapflow", () => ({ ImapFlow: vi.fn() }));
|
|
9
|
+
const { ImapFlow } = await import("imapflow");
|
|
10
|
+
const { testConnection, getInboxCount } = await import("../lib/imap.js");
|
|
11
|
+
function fakeClient(overrides = {}) {
|
|
12
|
+
const client = Object.assign(new EventEmitter(), {
|
|
13
|
+
connect: vi.fn().mockResolvedValue(undefined),
|
|
14
|
+
logout: vi.fn().mockResolvedValue(undefined),
|
|
15
|
+
close: vi.fn(),
|
|
16
|
+
mailboxOpen: vi.fn().mockResolvedValue({ exists: 42 }),
|
|
17
|
+
...overrides,
|
|
18
|
+
});
|
|
19
|
+
state.clients.push(client);
|
|
20
|
+
return client;
|
|
21
|
+
}
|
|
22
|
+
// new ImapFlow(...) requires a constructable mock — a regular function whose
|
|
23
|
+
// returned object overrides `this`.
|
|
24
|
+
function armImapFlow(overrides = {}) {
|
|
25
|
+
ImapFlow.mockImplementationOnce(function () {
|
|
26
|
+
return fakeClient(overrides);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const config = {
|
|
30
|
+
email: "a@b.test", agentAddress: "a@b.test",
|
|
31
|
+
imapHost: "imap.b.test", imapPort: 993, imapSecurity: "tls",
|
|
32
|
+
smtpHost: "smtp.b.test", smtpPort: 587, smtpSecurity: "starttls",
|
|
33
|
+
};
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
state.clients.length = 0;
|
|
36
|
+
vi.spyOn(process.stderr, "write").mockReturnValue(true);
|
|
37
|
+
});
|
|
38
|
+
describe("imap.testConnection", () => {
|
|
39
|
+
it("failure path: returns a message, closes the client, contains late errors", async () => {
|
|
40
|
+
armImapFlow({ connect: vi.fn().mockRejectedValue(new Error("Command failed")) });
|
|
41
|
+
const msg = await testConnection(config, "bad-password");
|
|
42
|
+
expect(msg).toMatch(/IMAP connection failed/);
|
|
43
|
+
const client = state.clients[0];
|
|
44
|
+
expect(client.close).toHaveBeenCalled();
|
|
45
|
+
expect(() => client.emit("error", new Error("late reset"))).not.toThrow();
|
|
46
|
+
});
|
|
47
|
+
it("failure path: error classification is unchanged", async () => {
|
|
48
|
+
armImapFlow({ connect: vi.fn().mockRejectedValue(new Error("AUTHENTICATIONFAILED bad creds")) });
|
|
49
|
+
const msg = await testConnection(config, "bad-password");
|
|
50
|
+
expect(msg).toMatch(/IMAP authentication failed for a@b\.test/);
|
|
51
|
+
});
|
|
52
|
+
it("success path: logs out, and a late 'error' after resolve is contained", async () => {
|
|
53
|
+
armImapFlow();
|
|
54
|
+
const msg = await testConnection(config, "good-password");
|
|
55
|
+
expect(msg).toBeNull();
|
|
56
|
+
const client = state.clients[0];
|
|
57
|
+
expect(client.logout).toHaveBeenCalled();
|
|
58
|
+
expect(() => client.emit("error", new Error("late FIN"))).not.toThrow();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe("imap.getInboxCount", () => {
|
|
62
|
+
it("returns the count and contains a late 'error' emit", async () => {
|
|
63
|
+
armImapFlow();
|
|
64
|
+
const count = await getInboxCount(config, "good-password");
|
|
65
|
+
expect(count).toBe(42);
|
|
66
|
+
expect(() => state.clients[0].emit("error", new Error("late"))).not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=imap-probe.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imap-probe.test.js","sourceRoot":"","sources":["../../src/__tests__/imap-probe.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-options.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mail-options.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { buildMailOptions } from "../lib/smtp.js";
|
|
3
|
+
const config = {
|
|
4
|
+
email: "login@example.com",
|
|
5
|
+
agentAddress: "agent@example.com",
|
|
6
|
+
};
|
|
7
|
+
const base = {
|
|
8
|
+
to: "joel@example.com",
|
|
9
|
+
subject: "Quote",
|
|
10
|
+
body: "Plain body",
|
|
11
|
+
};
|
|
12
|
+
describe("Task 815 — buildMailOptions shared composer input", () => {
|
|
13
|
+
it("maps the full send shape (from=agentAddress, text=body, passthroughs)", () => {
|
|
14
|
+
const opts = buildMailOptions(config, {
|
|
15
|
+
...base,
|
|
16
|
+
html: "<p>hi</p>",
|
|
17
|
+
inReplyTo: "<parent@id>",
|
|
18
|
+
references: "<parent@id>",
|
|
19
|
+
headers: { "X-Custom": "1" },
|
|
20
|
+
attachments: [{ filename: "doc.pdf", path: "/tmp/doc.pdf" }],
|
|
21
|
+
});
|
|
22
|
+
expect(opts).toEqual({
|
|
23
|
+
from: "agent@example.com",
|
|
24
|
+
to: "joel@example.com",
|
|
25
|
+
subject: "Quote",
|
|
26
|
+
text: "Plain body",
|
|
27
|
+
html: "<p>hi</p>",
|
|
28
|
+
inReplyTo: "<parent@id>",
|
|
29
|
+
references: "<parent@id>",
|
|
30
|
+
headers: { "X-Custom": "1" },
|
|
31
|
+
attachments: [{ filename: "doc.pdf", path: "/tmp/doc.pdf" }],
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
it("omits cc/bcc keys entirely when absent or empty (no-copy path byte-identity)", () => {
|
|
35
|
+
expect("cc" in buildMailOptions(config, base)).toBe(false);
|
|
36
|
+
expect("bcc" in buildMailOptions(config, base)).toBe(false);
|
|
37
|
+
expect("cc" in buildMailOptions(config, { ...base, cc: [], bcc: [] })).toBe(false);
|
|
38
|
+
expect("bcc" in buildMailOptions(config, { ...base, cc: [], bcc: [] })).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
it("sets cc/bcc when non-empty", () => {
|
|
41
|
+
const opts = buildMailOptions(config, { ...base, cc: ["c@x.y"], bcc: ["b@x.y"] });
|
|
42
|
+
expect(opts.cc).toEqual(["c@x.y"]);
|
|
43
|
+
expect(opts.bcc).toEqual(["b@x.y"]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=mail-options.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-options.test.js","sourceRoot":"","sources":["../../src/__tests__/mail-options.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAoB,MAAM,gBAAgB,CAAC;AAGpE,MAAM,MAAM,GAAG;IACb,KAAK,EAAE,mBAAmB;IAC1B,YAAY,EAAE,mBAAmB;CACnB,CAAC;AAEjB,MAAM,IAAI,GAAgB;IACxB,EAAE,EAAE,kBAAkB;IACtB,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,YAAY;CACnB,CAAC;AAEF,QAAQ,CAAC,mDAAmD,EAAE,GAAG,EAAE;IACjE,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACpC,GAAG,IAAI;YACP,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,aAAa;YACxB,UAAU,EAAE,aAAa;YACzB,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;YAC5B,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;SAC7D,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,mBAAmB;YACzB,EAAE,EAAE,kBAAkB;YACtB,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,aAAa;YACxB,UAAU,EAAE,aAAa;YACzB,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;YAC5B,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,CAAC,IAAI,IAAI,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,IAAI,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,IAAI,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnF,MAAM,CAAC,KAAK,IAAI,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-probe.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup-probe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { newProbeToken, trackProbe, releaseProbe, activeProbeCount, handleEscapedError, } from "../lib/setup-probe.js";
|
|
4
|
+
let stderrSpy;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
stderrSpy = vi.spyOn(process.stderr, "write").mockReturnValue(true);
|
|
7
|
+
});
|
|
8
|
+
afterEach(() => { stderrSpy.mockRestore(); });
|
|
9
|
+
const lines = () => stderrSpy.mock.calls.map((c) => String(c[0]));
|
|
10
|
+
describe("setup-probe census", () => {
|
|
11
|
+
it("acquired/released lines carry source, token, and a count returning to baseline", () => {
|
|
12
|
+
const base = activeProbeCount();
|
|
13
|
+
const token = newProbeToken();
|
|
14
|
+
trackProbe("imap", new EventEmitter(), token);
|
|
15
|
+
expect(activeProbeCount()).toBe(base + 1);
|
|
16
|
+
expect(lines().some((l) => l.includes("[email] setup-probe op=acquired source=imap") && l.includes(`token=${token}`))).toBe(true);
|
|
17
|
+
releaseProbe("imap", token);
|
|
18
|
+
expect(activeProbeCount()).toBe(base);
|
|
19
|
+
expect(lines().some((l) => l.includes("op=released source=imap") && l.includes(`token=${token}`))).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
describe("late-event containment", () => {
|
|
23
|
+
it("a late 'error' emit on a tracked emitter does not throw and logs contained=true", () => {
|
|
24
|
+
const emitter = new EventEmitter();
|
|
25
|
+
const token = newProbeToken();
|
|
26
|
+
trackProbe("imap", emitter, token);
|
|
27
|
+
releaseProbe("imap", token);
|
|
28
|
+
// Unlistened 'error' would throw synchronously — containment means it doesn't.
|
|
29
|
+
expect(() => emitter.emit("error", new Error("late TLS reset"))).not.toThrow();
|
|
30
|
+
expect(lines().some((l) => l.includes("op=late-event source=imap") && l.includes("err=late TLS reset") && l.includes("contained=true"))).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe("process-level guard (handleEscapedError)", () => {
|
|
34
|
+
it("contains an error whose stack references imapflow", () => {
|
|
35
|
+
const err = new Error("socket hang up");
|
|
36
|
+
err.stack = `Error: socket hang up\n at TLSSocket (/x/node_modules/imapflow/lib/imap-flow.js:1:1)`;
|
|
37
|
+
expect(handleEscapedError(err, "uncaughtException")).toBe(true);
|
|
38
|
+
expect(lines().some((l) => l.includes("op=late-event source=process") && l.includes("contained=true"))).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it("contains an error whose stack references nodemailer", () => {
|
|
41
|
+
const err = new Error("read ECONNRESET");
|
|
42
|
+
err.stack = `Error: read ECONNRESET\n at SMTPConnection (/x/node_modules/nodemailer/lib/smtp-connection/index.js:1:1)`;
|
|
43
|
+
expect(handleEscapedError(err, "unhandledRejection")).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
it("contains a foreign error while a probe is still unreleased", () => {
|
|
46
|
+
const token = newProbeToken();
|
|
47
|
+
trackProbe("smtp", new EventEmitter(), token);
|
|
48
|
+
expect(handleEscapedError(new Error("anything"), "uncaughtException")).toBe(true);
|
|
49
|
+
releaseProbe("smtp", token);
|
|
50
|
+
});
|
|
51
|
+
it("does NOT contain a foreign error with no active probe", () => {
|
|
52
|
+
expect(handleEscapedError(new Error("unrelated bug"), "uncaughtException")).toBe(false);
|
|
53
|
+
expect(lines().some((l) => l.includes("contained=false"))).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=setup-probe.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-probe.test.js","sourceRoot":"","sources":["../../src/__tests__/setup-probe.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp-probe.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/smtp-probe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
const state = vi.hoisted(() => ({ transports: [] }));
|
|
4
|
+
vi.mock("nodemailer", () => ({ createTransport: vi.fn() }));
|
|
5
|
+
const { createTransport } = await import("nodemailer");
|
|
6
|
+
const { testConnection } = await import("../lib/smtp.js");
|
|
7
|
+
function armTransport(overrides = {}) {
|
|
8
|
+
createTransport.mockImplementationOnce(() => {
|
|
9
|
+
const t = Object.assign(new EventEmitter(), {
|
|
10
|
+
verify: vi.fn().mockResolvedValue(true),
|
|
11
|
+
close: vi.fn(),
|
|
12
|
+
sendMail: vi.fn(),
|
|
13
|
+
...overrides,
|
|
14
|
+
});
|
|
15
|
+
state.transports.push(t);
|
|
16
|
+
return t;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
const config = {
|
|
20
|
+
email: "a@b.test", agentAddress: "a@b.test",
|
|
21
|
+
imapHost: "imap.b.test", imapPort: 993, imapSecurity: "tls",
|
|
22
|
+
smtpHost: "smtp.b.test", smtpPort: 587, smtpSecurity: "starttls",
|
|
23
|
+
};
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
state.transports.length = 0;
|
|
26
|
+
vi.spyOn(process.stderr, "write").mockReturnValue(true);
|
|
27
|
+
});
|
|
28
|
+
describe("smtp.testConnection", () => {
|
|
29
|
+
it("success path: closes transport; a late 'error' emit is contained", async () => {
|
|
30
|
+
armTransport();
|
|
31
|
+
const msg = await testConnection(config, "good");
|
|
32
|
+
expect(msg).toBeNull();
|
|
33
|
+
const t = state.transports[0];
|
|
34
|
+
expect(t.close).toHaveBeenCalled();
|
|
35
|
+
expect(() => t.emit("error", new Error("late 421"))).not.toThrow();
|
|
36
|
+
});
|
|
37
|
+
it("failure path: classification unchanged, transport closed, late error contained", async () => {
|
|
38
|
+
armTransport({ verify: vi.fn().mockRejectedValue(new Error("535 Authentication failed")) });
|
|
39
|
+
const msg = await testConnection(config, "bad");
|
|
40
|
+
expect(msg).toMatch(/SMTP authentication failed/);
|
|
41
|
+
const t = state.transports[0];
|
|
42
|
+
expect(t.close).toHaveBeenCalled();
|
|
43
|
+
expect(() => t.emit("error", new Error("late"))).not.toThrow();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=smtp-probe.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp-probe.test.js","sourceRoot":"","sources":["../../src/__tests__/smtp-probe.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
|
|
2
2
|
initStderrTee("email");
|
|
3
|
+
// After the tee (so guard lines are captured), before everything else (so no
|
|
4
|
+
// window exists where a probe error can escape). Never throws at module init.
|
|
5
|
+
import { installSetupProbeGuard } from "./lib/setup-probe.js";
|
|
6
|
+
installSetupProbeGuard();
|
|
3
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
8
|
import { eagerTool } from "../../../../lib/mcp-eager/dist/index.js";
|
|
5
9
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -7,6 +11,7 @@ import { z } from "zod";
|
|
|
7
11
|
import { emailSetup } from "./tools/email-setup.js";
|
|
8
12
|
import { emailRead } from "./tools/email-read.js";
|
|
9
13
|
import { emailSend } from "./tools/email-send.js";
|
|
14
|
+
import { emailDraft } from "./tools/email-draft.js";
|
|
10
15
|
import { emailSearch } from "./tools/email-search.js";
|
|
11
16
|
import { emailOtpExtract } from "./tools/email-otp-extract.js";
|
|
12
17
|
import { emailStatus } from "./tools/email-status.js";
|
|
@@ -191,6 +196,45 @@ eagerTool(server, "email-send", "Send an email from the agent's email account vi
|
|
|
191
196
|
}
|
|
192
197
|
});
|
|
193
198
|
// ===================================================================
|
|
199
|
+
// email-draft — compose an email into the mailbox Drafts folder (no send)
|
|
200
|
+
// ===================================================================
|
|
201
|
+
eagerTool(server, "email-draft", "Compose an email and save it unsent to the mailbox's Drafts folder for the operator to review and send by hand. Same inputs as email-send; nothing is dispatched. Use when the operator says 'draft it', 'leave it in drafts', 'don't send yet', or 'let me review before sending'.", {
|
|
202
|
+
to: z.string().email().describe("Recipient email address"),
|
|
203
|
+
subject: z.string().describe("Email subject line"),
|
|
204
|
+
body: z.string().describe("Plain text email body"),
|
|
205
|
+
html: z.string().optional().describe("Optional HTML email body"),
|
|
206
|
+
cc: z
|
|
207
|
+
.array(z.string().email())
|
|
208
|
+
.optional()
|
|
209
|
+
.describe("Optional CC recipients (visible in the message header). One or more email addresses."),
|
|
210
|
+
bcc: z
|
|
211
|
+
.array(z.string().email())
|
|
212
|
+
.optional()
|
|
213
|
+
.describe("Optional BCC recipients. Hidden — they receive the message but do not appear in any header."),
|
|
214
|
+
attachments: z
|
|
215
|
+
.array(z.string())
|
|
216
|
+
.optional()
|
|
217
|
+
.describe("Absolute local file paths to attach. Each must be a regular file inside the account directory and ≤25 MB. Omit for a text-only message."),
|
|
218
|
+
}, async (params) => {
|
|
219
|
+
if (!accountId)
|
|
220
|
+
return refuseNoAccount("email-draft");
|
|
221
|
+
try {
|
|
222
|
+
const text = await emailDraft({ ...params, accountId });
|
|
223
|
+
return { content: [{ type: "text", text }] };
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
return {
|
|
227
|
+
content: [
|
|
228
|
+
{
|
|
229
|
+
type: "text",
|
|
230
|
+
text: `Failed to save email draft: ${err instanceof Error ? err.message : String(err)}`,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
isError: true,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
// ===================================================================
|
|
194
238
|
// email-search — search inbox by criteria
|
|
195
239
|
// ===================================================================
|
|
196
240
|
eagerTool(server, "email-search", "Search messages by sender, subject, body, or date range. Returns message list (from, subject, date — no body content). Supports pagination via before_uid cursor and folder selection (inbox or sent). Max 50 messages per request.", {
|