@rubytech/create-maxy-code 0.1.445 → 0.1.447
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/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +6 -0
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/index.ts +7 -0
- package/payload/platform/neo4j/schema.cypher +32 -1
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +13 -3
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +8 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +20 -3
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +42 -5
- package/payload/platform/plugins/docs/references/calendar-booking.md +18 -1
- package/payload/platform/plugins/docs/references/claudeai-connectors.md +15 -0
- package/payload/platform/plugins/docs/references/outlook-guide.md +8 -3
- package/payload/platform/plugins/email/skills/email-composition/SKILL.md +4 -4
- package/payload/platform/plugins/memory/references/schema-construction.md +7 -2
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +24 -6
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js +70 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-edit.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/html-to-text.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/html-to-text.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/html-to-text.test.js +22 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/html-to-text.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-delete.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-delete.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-delete.test.js +60 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-delete.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-fetch-body.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-fetch-body.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-fetch-body.test.js +80 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-fetch-body.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-otp-extract.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-otp-extract.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-otp-extract.test.js +90 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-otp-extract.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-reply.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-reply.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-reply.test.js +194 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-reply.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.js +23 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-registry.test.js +34 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-registry.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/otp.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/otp.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/otp.test.js +16 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/otp.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/outbound-attachments.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/outbound-attachments.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/outbound-attachments.test.js +103 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/outbound-attachments.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.d.ts +26 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.js +20 -3
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/index.js +90 -2
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/html-to-text.d.ts +9 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/html-to-text.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/html-to-text.js +24 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/html-to-text.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/otp.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/otp.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/otp.js +49 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/otp.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts +58 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js +127 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/outbound-attachments.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.d.ts +28 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.js +54 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/upload-session.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts +21 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js +38 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-edit.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-delete.d.ts +14 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-delete.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-delete.js +39 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-delete.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.d.ts +23 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.js +44 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-otp-extract.d.ts +22 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-otp-extract.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-otp-extract.js +90 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-otp-extract.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.d.ts +27 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js +75 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.d.ts +7 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.js +4 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.js.map +1 -1
- package/payload/platform/plugins/outlook/references/graph-surfaces.md +57 -1
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +24 -7
- package/payload/platform/plugins/scheduling/PLUGIN.md +15 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +29 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.js +53 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +21 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +80 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.d.ts +4 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +68 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-connector-busy-sync.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-connector-busy-sync.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-connector-busy-sync.test.js +75 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-connector-busy-sync.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.d.ts +31 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.js +41 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.js.map +1 -0
- package/payload/platform/plugins/voice-mirror/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/voice-mirror/PLUGIN.md +72 -0
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/index.js +10 -10
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/index.js.map +1 -1
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/neo4j.d.ts +1 -1
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/neo4j.js +4 -4
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/neo4j.js.map +1 -1
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-record-feedback.js +1 -1
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-record-feedback.js.map +1 -1
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/package-lock.json +2 -2
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/package.json +1 -1
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/scripts/smoke.mjs +9 -9
- package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/skills/voice-mirror/SKILL.md +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 +12 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/templates/agents/admin/AGENTS.md +1 -1
- package/payload/platform/templates/specialists/agents/content-producer.md +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +6 -2
- package/payload/premium-plugins/writer-craft/.claude-plugin/plugin.json +1 -14
- package/payload/premium-plugins/writer-craft/PLUGIN.md +2 -51
- package/payload/server/public/assets/{AdminLoginScreens-D9L-CuWi.js → AdminLoginScreens-Bvf4HKmq.js} +1 -1
- package/payload/server/public/assets/AdminShell-CaGc8ODG.js +2 -0
- package/payload/server/public/assets/{Checkbox-CFdt8ljo.js → Checkbox-2SswiICc.js} +1 -1
- package/payload/server/public/assets/admin-B7GPCzpr.js +1 -0
- package/payload/server/public/assets/browser-CodHC_MO.js +1 -0
- package/payload/server/public/assets/calendar-DH7cyXKF.js +1 -0
- package/payload/server/public/assets/chat-BQyPAEMv.js +1 -0
- package/payload/server/public/assets/chevron-left-Cmev0R9v.js +1 -0
- package/payload/server/public/assets/data-DWxZzMfL.js +1 -0
- package/payload/server/public/assets/{graph-DrE7KupQ.js → graph-BToB78LG.js} +2 -2
- package/payload/server/public/assets/graph-labels-JRGrstzM.js +1 -0
- package/payload/server/public/assets/maximize-2-CEQRv64B.js +1 -0
- package/payload/server/public/assets/operator-Cx8cq2wf.js +1 -0
- package/payload/server/public/assets/page-D6kzsk18.js +32 -0
- package/payload/server/public/assets/page-TCsQy4eP.js +1 -0
- package/payload/server/public/assets/public-B61xcmAr.js +1 -0
- package/payload/server/public/assets/{rotate-ccw-Cqp4oqHV.js → rotate-ccw-7_3ol0Z4.js} +1 -1
- package/payload/server/public/assets/{tasks-bQKOhMga.js → tasks-BY9ajKXf.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-BIL4ZaDK.js → time-entry-format-DmNhIJnM.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-C5-GOl5l.js +1 -0
- package/payload/server/public/assets/useSelectionMode-UOUVnP9B.js +1 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-CVHKTSst.css → useSubAccountSwitcher-DgM1ergs.css} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-BAP3yGxs.js +2 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +10 -10
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +13 -13
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +365 -180
- package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.d.ts +0 -8
- package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.d.ts.map +0 -1
- package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.js +0 -71
- package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.js.map +0 -1
- package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/package.json +0 -7
- package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.d.ts +0 -51
- package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.d.ts.map +0 -1
- package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.js +0 -196
- package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.js.map +0 -1
- package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/package.json +0 -7
- package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.d.ts +0 -3
- package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.d.ts.map +0 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.js +0 -58
- package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.js.map +0 -1
- package/payload/premium-plugins/writer-craft/mcp/src/index.ts +0 -457
- package/payload/premium-plugins/writer-craft/mcp/src/lib/neo4j.ts +0 -56
- package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +0 -154
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +0 -833
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-ingest-session-text.ts +0 -153
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-record-feedback.ts +0 -148
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-retrieve-conditioning.ts +0 -270
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-tag-content.ts +0 -181
- package/payload/premium-plugins/writer-craft/mcp/tsconfig.json +0 -8
- package/payload/server/public/assets/AdminShell-DSQrvZXq.js +0 -2
- package/payload/server/public/assets/admin-Ch4n-G0j.js +0 -1
- package/payload/server/public/assets/browser-B2AIxiuk.js +0 -1
- package/payload/server/public/assets/calendar-BvItH3B0.js +0 -1
- package/payload/server/public/assets/chat-eQFMaX9y.js +0 -1
- package/payload/server/public/assets/chevron-left-D2AnCEyE.js +0 -1
- package/payload/server/public/assets/data-BzOmbHoe.js +0 -1
- package/payload/server/public/assets/file-download-CK9j_Jx2.js +0 -1
- package/payload/server/public/assets/graph-labels-CwEtvIRV.js +0 -1
- package/payload/server/public/assets/maximize-2-CuzEom3K.js +0 -1
- package/payload/server/public/assets/operator-DlboYPPu.js +0 -1
- package/payload/server/public/assets/page-BuWH5gNK.js +0 -1
- package/payload/server/public/assets/page-Co9E8U5x.js +0 -32
- package/payload/server/public/assets/public-DtFpPMTG.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-rB8QuqyH.js +0 -1
- package/payload/server/public/assets/useVoiceRecorder-Ctny8qWx.js +0 -2
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/lib/mcp-spawn-tee/index.js +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/lib/mcp-spawn-tee/package.json +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/index.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/index.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/neo4j.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/voice-corpus.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/voice-corpus.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/voice-corpus.js +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/lib/voice-corpus.js.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-distil-profile.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-distil-profile.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-distil-profile.js +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-distil-profile.js.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-ingest-session-text.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-ingest-session-text.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-ingest-session-text.js +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-ingest-session-text.js.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-record-feedback.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-record-feedback.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-retrieve-conditioning.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-retrieve-conditioning.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-retrieve-conditioning.js +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-retrieve-conditioning.js.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-tag-content.d.ts +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-tag-content.d.ts.map +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-tag-content.js +0 -0
- /package/payload/{premium-plugins/writer-craft → platform/plugins/voice-mirror}/mcp/dist/tools/voice-tag-content.js.map +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-CHEt_m6q.js → useSubAccountSwitcher-DF6bohQA.js} +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decode a Graph HTML mail body to readable plain text. No external dep: drop
|
|
3
|
+
* script/style, convert block boundaries to newlines, strip remaining tags,
|
|
4
|
+
* decode the common named + numeric entities, collapse runs of blank lines.
|
|
5
|
+
* Not a full HTML parser — good enough to read a mail body. Used by
|
|
6
|
+
* outlook-mail-fetch-body (full read) and outlook-mail-otp-extract.
|
|
7
|
+
*/
|
|
8
|
+
const NAMED = {
|
|
9
|
+
amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " ",
|
|
10
|
+
mdash: "—", ndash: "–", hellip: "…", rsquo: "’",
|
|
11
|
+
lsquo: "‘", ldquo: "“", rdquo: "”",
|
|
12
|
+
};
|
|
13
|
+
export function htmlToText(html) {
|
|
14
|
+
let s = html.replace(/<(script|style)[\s\S]*?<\/\1>/gi, "");
|
|
15
|
+
s = s.replace(/<br\s*\/?>/gi, "\n");
|
|
16
|
+
s = s.replace(/<\/(p|div|tr|li|h[1-6]|table|blockquote)>/gi, "\n");
|
|
17
|
+
s = s.replace(/<[^>]+>/g, "");
|
|
18
|
+
s = s.replace(/&#(\d+);/g, (_, n) => String.fromCodePoint(Number(n)));
|
|
19
|
+
s = s.replace(/&#x([0-9a-f]+);/gi, (_, n) => String.fromCodePoint(parseInt(n, 16)));
|
|
20
|
+
s = s.replace(/&([a-z]+);/gi, (m, name) => NAMED[name.toLowerCase()] ?? m);
|
|
21
|
+
s = s.replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
22
|
+
return s.trim();
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=html-to-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-to-text.js","sourceRoot":"","sources":["../../src/lib/html-to-text.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,KAAK,GAA2B;IACpC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG;IAC3D,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG;IAC/C,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG;CACnC,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,iCAAiC,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,6CAA6C,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otp.d.ts","sourceRoot":"","sources":["../../src/lib/otp.ts"],"names":[],"mappings":"AAgBA,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+B9D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTP extraction — one-time verification code parsing from a mail body.
|
|
3
|
+
* Copied verbatim from the email plugin's email-otp-extract so both mail
|
|
4
|
+
* surfaces recognise the same code shapes. Source-agnostic: it takes decoded
|
|
5
|
+
* text and returns the code (or null); the Graph fetch/poll lives in the tool.
|
|
6
|
+
*
|
|
7
|
+
* OTP context patterns — phrases that typically surround a verification code.
|
|
8
|
+
* None use the /g flag — they are stateless and safe for repeated exec() calls.
|
|
9
|
+
*/
|
|
10
|
+
const OTP_CONTEXT_PATTERNS = [
|
|
11
|
+
/(?:verification|verify|security|confirmation|one[- ]time|otp|login|sign[- ]?in|access)\s*(?:code|pin|number|token)\s*(?:is|:)?\s*(\d{4,8})/i,
|
|
12
|
+
/(\d{4,8})\s*(?:is your|is the)\s*(?:verification|security|confirmation|one[- ]time|otp|login|sign[- ]?in)/i,
|
|
13
|
+
/(?:code|pin|token)\s*(?:is|:)\s*(\d{4,8})/i,
|
|
14
|
+
/(?:enter|use|input|type)\s*(?:the\s*)?(?:code\s*)?(\d{4,8})/i,
|
|
15
|
+
];
|
|
16
|
+
export function extractOtpFromText(text) {
|
|
17
|
+
// Try context-aware patterns first
|
|
18
|
+
for (const pattern of OTP_CONTEXT_PATTERNS) {
|
|
19
|
+
const match = pattern.exec(text);
|
|
20
|
+
if (match?.[1])
|
|
21
|
+
return match[1];
|
|
22
|
+
}
|
|
23
|
+
// Fallback: extract standalone 4-8 digit numbers, filtering false positives.
|
|
24
|
+
// Pattern created locally to avoid /g lastIndex state leaking between calls.
|
|
25
|
+
const standalonePattern = /\b(\d{4,8})\b/g;
|
|
26
|
+
const matches = [];
|
|
27
|
+
let match;
|
|
28
|
+
while ((match = standalonePattern.exec(text)) !== null) {
|
|
29
|
+
const num = match[1];
|
|
30
|
+
// Filter out likely years (1900-2099)
|
|
31
|
+
if (/^(19|20)\d{2}$/.test(num))
|
|
32
|
+
continue;
|
|
33
|
+
// Filter out numbers that are part of a phone-like sequence
|
|
34
|
+
const surrounding = text.slice(Math.max(0, match.index - 5), match.index + num.length + 5);
|
|
35
|
+
if (/\+?\d[\d\s\-()]{9,}/.test(surrounding))
|
|
36
|
+
continue;
|
|
37
|
+
matches.push(num);
|
|
38
|
+
}
|
|
39
|
+
// If exactly one candidate remains, it's likely the OTP
|
|
40
|
+
if (matches.length === 1)
|
|
41
|
+
return matches[0];
|
|
42
|
+
// Multiple candidates — prefer 6-digit codes (most common OTP length)
|
|
43
|
+
const sixDigit = matches.find((m) => m.length === 6);
|
|
44
|
+
if (sixDigit)
|
|
45
|
+
return sixDigit;
|
|
46
|
+
// Return the first candidate if any exist
|
|
47
|
+
return matches[0] ?? null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=otp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otp.js","sourceRoot":"","sources":["../../src/lib/otp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,oBAAoB,GAAa;IACrC,6IAA6I;IAC7I,4GAA4G;IAC5G,4CAA4C;IAC5C,8DAA8D;CAC/D,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,mCAAmC;IACnC,KAAK,MAAM,OAAO,IAAI,oBAAoB,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,6EAA6E;IAC7E,6EAA6E;IAC7E,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;IAC3C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACvD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,sCAAsC;QACtC,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QACzC,4DAA4D;QAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3F,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,SAAS;QACtD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,wDAAwD;IACxD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IAE5C,sEAAsE;IACtE,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IACrD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,0CAA0C;IAC1C,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound attachment resolver for outlook-mail-reply. Mirrors the email
|
|
3
|
+
* plugin's account-scope check (realpath under the account directory, regular
|
|
4
|
+
* file, size cap), then classifies each file by how it must reach the reply
|
|
5
|
+
* draft:
|
|
6
|
+
*
|
|
7
|
+
* - `inline` — at or under Graph's ~3 MB fileAttachment limit; sent as a
|
|
8
|
+
* single base64 `POST /messages/{id}/attachments`.
|
|
9
|
+
* - `session` — above the inline limit and up to the 25 MB account cap; sent
|
|
10
|
+
* through a Graph upload session (see `upload-session.ts`).
|
|
11
|
+
*
|
|
12
|
+
* The account cap (25 MB) matches the email plugin's outbound cap, so an
|
|
13
|
+
* Outlook reply and the equivalent IMAP reply carry the same maximum.
|
|
14
|
+
*
|
|
15
|
+
* Resolution reads no bytes — it returns per-file metadata (path, size, mode)
|
|
16
|
+
* so `mail-reply` can choose the path. Path validation still happens before any
|
|
17
|
+
* Graph write, so a bad path leaves no orphan draft; bytes are read at send
|
|
18
|
+
* time by `toInlineAttachment` (inline) or the upload session (session).
|
|
19
|
+
*/
|
|
20
|
+
/** Graph fileAttachment inline limit for POST /messages/{id}/attachments. */
|
|
21
|
+
export declare const OUTLOOK_ATTACHMENT_INLINE_MAX_BYTES: number;
|
|
22
|
+
/** Per-file account cap; parity with the email plugin's outbound cap. */
|
|
23
|
+
export declare const OUTLOOK_ATTACHMENT_MAX_BYTES: number;
|
|
24
|
+
export interface GraphFileAttachment {
|
|
25
|
+
"@odata.type": "#microsoft.graph.fileAttachment";
|
|
26
|
+
name: string;
|
|
27
|
+
contentType: string;
|
|
28
|
+
contentBytes: string;
|
|
29
|
+
}
|
|
30
|
+
/** A validated, account-scoped file and the Graph path it must take. */
|
|
31
|
+
export interface OutboundAttachment {
|
|
32
|
+
/** realpath, verified under the account directory. */
|
|
33
|
+
path: string;
|
|
34
|
+
name: string;
|
|
35
|
+
contentType: string;
|
|
36
|
+
size: number;
|
|
37
|
+
mode: "inline" | "session";
|
|
38
|
+
}
|
|
39
|
+
/** ACCOUNT_DIR (spawn-set) wins; else derive from PLATFORM_ROOT + accountId,
|
|
40
|
+
* matching the email plugin's resolver. Null when neither resolves. */
|
|
41
|
+
export declare function resolveAccountDir(accountId: string): string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Validate agent-supplied paths and classify each as inline or session. Each
|
|
44
|
+
* path must realpath to a regular file under the account directory and be within
|
|
45
|
+
* the 25 MB account cap. Any violation throws a precise error naming the
|
|
46
|
+
* offending path, so the caller sends nothing rather than a reply that silently
|
|
47
|
+
* drops the file. Absent/empty input returns [] (a text-only reply).
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveOutboundAttachments(accountId: string, paths: string[] | undefined): OutboundAttachment[];
|
|
50
|
+
/**
|
|
51
|
+
* Read an inline attachment's bytes and base64-encode them into the Graph
|
|
52
|
+
* fileAttachment shape a reply draft accepts. Only called for `mode: "inline"`
|
|
53
|
+
* files; larger files go through the upload session instead.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toInlineAttachment(att: OutboundAttachment): GraphFileAttachment;
|
|
56
|
+
/** The " with N attachment(s): a, b" suffix for a reply success message. */
|
|
57
|
+
export declare function attachNote(names: string[]): string;
|
|
58
|
+
//# sourceMappingURL=outbound-attachments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-attachments.d.ts","sourceRoot":"","sources":["../../src/lib/outbound-attachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,6EAA6E;AAC7E,eAAO,MAAM,mCAAmC,QAAkB,CAAC;AACnE,yEAAyE;AACzE,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,iCAAiC,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wEAAwE;AACxE,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAqBD;wEACwE;AACxE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlE;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,GAC1B,kBAAkB,EAAE,CAgDtB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,mBAAmB,CAO/E;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAGlD"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound attachment resolver for outlook-mail-reply. Mirrors the email
|
|
3
|
+
* plugin's account-scope check (realpath under the account directory, regular
|
|
4
|
+
* file, size cap), then classifies each file by how it must reach the reply
|
|
5
|
+
* draft:
|
|
6
|
+
*
|
|
7
|
+
* - `inline` — at or under Graph's ~3 MB fileAttachment limit; sent as a
|
|
8
|
+
* single base64 `POST /messages/{id}/attachments`.
|
|
9
|
+
* - `session` — above the inline limit and up to the 25 MB account cap; sent
|
|
10
|
+
* through a Graph upload session (see `upload-session.ts`).
|
|
11
|
+
*
|
|
12
|
+
* The account cap (25 MB) matches the email plugin's outbound cap, so an
|
|
13
|
+
* Outlook reply and the equivalent IMAP reply carry the same maximum.
|
|
14
|
+
*
|
|
15
|
+
* Resolution reads no bytes — it returns per-file metadata (path, size, mode)
|
|
16
|
+
* so `mail-reply` can choose the path. Path validation still happens before any
|
|
17
|
+
* Graph write, so a bad path leaves no orphan draft; bytes are read at send
|
|
18
|
+
* time by `toInlineAttachment` (inline) or the upload session (session).
|
|
19
|
+
*/
|
|
20
|
+
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
21
|
+
import { basename, extname, join } from "node:path";
|
|
22
|
+
/** Graph fileAttachment inline limit for POST /messages/{id}/attachments. */
|
|
23
|
+
export const OUTLOOK_ATTACHMENT_INLINE_MAX_BYTES = 3 * 1024 * 1024;
|
|
24
|
+
/** Per-file account cap; parity with the email plugin's outbound cap. */
|
|
25
|
+
export const OUTLOOK_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
26
|
+
const MIME = {
|
|
27
|
+
".pdf": "application/pdf",
|
|
28
|
+
".png": "image/png",
|
|
29
|
+
".jpg": "image/jpeg",
|
|
30
|
+
".jpeg": "image/jpeg",
|
|
31
|
+
".gif": "image/gif",
|
|
32
|
+
".txt": "text/plain",
|
|
33
|
+
".csv": "text/csv",
|
|
34
|
+
".doc": "application/msword",
|
|
35
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
36
|
+
".xls": "application/vnd.ms-excel",
|
|
37
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
38
|
+
".zip": "application/zip",
|
|
39
|
+
};
|
|
40
|
+
function contentTypeOf(rp) {
|
|
41
|
+
return MIME[extname(rp).toLowerCase()] ?? "application/octet-stream";
|
|
42
|
+
}
|
|
43
|
+
/** ACCOUNT_DIR (spawn-set) wins; else derive from PLATFORM_ROOT + accountId,
|
|
44
|
+
* matching the email plugin's resolver. Null when neither resolves. */
|
|
45
|
+
export function resolveAccountDir(accountId) {
|
|
46
|
+
const direct = process.env.ACCOUNT_DIR;
|
|
47
|
+
if (direct && direct.trim())
|
|
48
|
+
return direct;
|
|
49
|
+
const platformRoot = process.env.PLATFORM_ROOT;
|
|
50
|
+
if (platformRoot && accountId && !accountId.includes("/") && !accountId.includes("..")) {
|
|
51
|
+
return join(platformRoot, "..", "data", "accounts", accountId);
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate agent-supplied paths and classify each as inline or session. Each
|
|
57
|
+
* path must realpath to a regular file under the account directory and be within
|
|
58
|
+
* the 25 MB account cap. Any violation throws a precise error naming the
|
|
59
|
+
* offending path, so the caller sends nothing rather than a reply that silently
|
|
60
|
+
* drops the file. Absent/empty input returns [] (a text-only reply).
|
|
61
|
+
*/
|
|
62
|
+
export function resolveOutboundAttachments(accountId, paths) {
|
|
63
|
+
if (!paths || paths.length === 0)
|
|
64
|
+
return [];
|
|
65
|
+
const dir = resolveAccountDir(accountId);
|
|
66
|
+
if (!dir) {
|
|
67
|
+
throw new Error("Cannot attach files: no account context (ACCOUNT_DIR unset and PLATFORM_ROOT+ACCOUNT_ID unavailable) to validate paths against.");
|
|
68
|
+
}
|
|
69
|
+
let accountResolved;
|
|
70
|
+
try {
|
|
71
|
+
accountResolved = realpathSync(dir);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
throw new Error(`Cannot attach files: account directory ${dir} is not accessible (${err instanceof Error ? err.message : String(err)}).`);
|
|
75
|
+
}
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const p of paths) {
|
|
78
|
+
let rp;
|
|
79
|
+
try {
|
|
80
|
+
rp = realpathSync(p);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
if (err.code === "ENOENT") {
|
|
84
|
+
throw new Error(`Attachment not found: ${p}`);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Cannot read attachment ${p}: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
}
|
|
88
|
+
if (!rp.startsWith(accountResolved + "/")) {
|
|
89
|
+
throw new Error(`Attachment ${p} is outside the account directory and cannot be sent.`);
|
|
90
|
+
}
|
|
91
|
+
const st = statSync(rp);
|
|
92
|
+
if (!st.isFile()) {
|
|
93
|
+
throw new Error(`Attachment ${p} is not a regular file.`);
|
|
94
|
+
}
|
|
95
|
+
if (st.size > OUTLOOK_ATTACHMENT_MAX_BYTES) {
|
|
96
|
+
throw new Error(`Attachment ${basename(rp)} is ${(st.size / 1024 / 1024).toFixed(1)} MB; Outlook reply attachments are capped at 25 MB per file.`);
|
|
97
|
+
}
|
|
98
|
+
out.push({
|
|
99
|
+
path: rp,
|
|
100
|
+
name: basename(rp),
|
|
101
|
+
contentType: contentTypeOf(rp),
|
|
102
|
+
size: st.size,
|
|
103
|
+
mode: st.size > OUTLOOK_ATTACHMENT_INLINE_MAX_BYTES ? "session" : "inline",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Read an inline attachment's bytes and base64-encode them into the Graph
|
|
110
|
+
* fileAttachment shape a reply draft accepts. Only called for `mode: "inline"`
|
|
111
|
+
* files; larger files go through the upload session instead.
|
|
112
|
+
*/
|
|
113
|
+
export function toInlineAttachment(att) {
|
|
114
|
+
return {
|
|
115
|
+
"@odata.type": "#microsoft.graph.fileAttachment",
|
|
116
|
+
name: att.name,
|
|
117
|
+
contentType: att.contentType,
|
|
118
|
+
contentBytes: readFileSync(att.path).toString("base64"),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** The " with N attachment(s): a, b" suffix for a reply success message. */
|
|
122
|
+
export function attachNote(names) {
|
|
123
|
+
if (names.length === 0)
|
|
124
|
+
return "";
|
|
125
|
+
return ` with ${names.length} attachment(s): ${names.join(", ")}`;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=outbound-attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-attachments.js","sourceRoot":"","sources":["../../src/lib/outbound-attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph upload-session path for reply attachments above the inline limit.
|
|
3
|
+
*
|
|
4
|
+
* Two steps, distinct in auth and host:
|
|
5
|
+
* 1. `POST /me/messages/{draftId}/attachments/createUploadSession` — through
|
|
6
|
+
* the Graph SDK (auth handled by `postGraph`), returns a pre-authenticated
|
|
7
|
+
* `uploadUrl`.
|
|
8
|
+
* 2. Chunked `PUT` to that `uploadUrl` — a plain fetch to a non-Graph host
|
|
9
|
+
* with NO bearer token (the URL itself is the credential). Each chunk is a
|
|
10
|
+
* multiple of 320 KiB except the last, per Graph's contract, and carries a
|
|
11
|
+
* `Content-Range` header. Graph returns 200 for an intermediate chunk and
|
|
12
|
+
* 201 for the final one.
|
|
13
|
+
*
|
|
14
|
+
* Every non-2xx PUT throws with the response status and body preserved, so a
|
|
15
|
+
* session that stalls mid-chunk is diagnosable rather than silent.
|
|
16
|
+
*/
|
|
17
|
+
import type { GraphClientConfig } from "./graph-client.js";
|
|
18
|
+
import type { OutboundAttachment } from "./outbound-attachments.js";
|
|
19
|
+
/** Chunk size for the upload PUT: 3.125 MiB, a whole multiple of 320 KiB as
|
|
20
|
+
* Graph requires for every chunk except the final remainder. */
|
|
21
|
+
export declare const UPLOAD_CHUNK_BYTES: number;
|
|
22
|
+
/**
|
|
23
|
+
* Upload one large attachment to an existing reply draft via a Graph upload
|
|
24
|
+
* session. Returns the number of chunks PUT (for observability). The draft must
|
|
25
|
+
* already exist; the attachment must have passed `resolveOutboundAttachments`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function uploadAttachmentSession(config: GraphClientConfig, draftId: string, att: OutboundAttachment): Promise<number>;
|
|
28
|
+
//# sourceMappingURL=upload-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-session.d.ts","sourceRoot":"","sources":["../../src/lib/upload-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE;iEACiE;AACjE,eAAO,MAAM,kBAAkB,QAAkB,CAAC;AAMlD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,GACtB,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph upload-session path for reply attachments above the inline limit.
|
|
3
|
+
*
|
|
4
|
+
* Two steps, distinct in auth and host:
|
|
5
|
+
* 1. `POST /me/messages/{draftId}/attachments/createUploadSession` — through
|
|
6
|
+
* the Graph SDK (auth handled by `postGraph`), returns a pre-authenticated
|
|
7
|
+
* `uploadUrl`.
|
|
8
|
+
* 2. Chunked `PUT` to that `uploadUrl` — a plain fetch to a non-Graph host
|
|
9
|
+
* with NO bearer token (the URL itself is the credential). Each chunk is a
|
|
10
|
+
* multiple of 320 KiB except the last, per Graph's contract, and carries a
|
|
11
|
+
* `Content-Range` header. Graph returns 200 for an intermediate chunk and
|
|
12
|
+
* 201 for the final one.
|
|
13
|
+
*
|
|
14
|
+
* Every non-2xx PUT throws with the response status and body preserved, so a
|
|
15
|
+
* session that stalls mid-chunk is diagnosable rather than silent.
|
|
16
|
+
*/
|
|
17
|
+
import { readFileSync } from "node:fs";
|
|
18
|
+
import { postGraph } from "./graph-client.js";
|
|
19
|
+
/** Chunk size for the upload PUT: 3.125 MiB, a whole multiple of 320 KiB as
|
|
20
|
+
* Graph requires for every chunk except the final remainder. */
|
|
21
|
+
export const UPLOAD_CHUNK_BYTES = 320 * 1024 * 10;
|
|
22
|
+
/**
|
|
23
|
+
* Upload one large attachment to an existing reply draft via a Graph upload
|
|
24
|
+
* session. Returns the number of chunks PUT (for observability). The draft must
|
|
25
|
+
* already exist; the attachment must have passed `resolveOutboundAttachments`.
|
|
26
|
+
*/
|
|
27
|
+
export async function uploadAttachmentSession(config, draftId, att) {
|
|
28
|
+
const { json } = await postGraph(config, `/me/messages/${encodeURIComponent(draftId)}/attachments/createUploadSession`, { AttachmentItem: { attachmentType: "file", name: att.name, size: att.size, contentType: att.contentType } }, { tool: "mail-reply" });
|
|
29
|
+
const uploadUrl = json?.uploadUrl;
|
|
30
|
+
if (!uploadUrl) {
|
|
31
|
+
throw new Error(`outlook-mail-reply: createUploadSession for ${att.name} returned no uploadUrl.`);
|
|
32
|
+
}
|
|
33
|
+
const buf = readFileSync(att.path);
|
|
34
|
+
const total = buf.length;
|
|
35
|
+
let start = 0;
|
|
36
|
+
let chunks = 0;
|
|
37
|
+
while (start < total) {
|
|
38
|
+
const end = Math.min(start + UPLOAD_CHUNK_BYTES, total);
|
|
39
|
+
const slice = buf.subarray(start, end);
|
|
40
|
+
const res = await fetch(uploadUrl, {
|
|
41
|
+
method: "PUT",
|
|
42
|
+
headers: { "Content-Range": `bytes ${start}-${end - 1}/${total}` },
|
|
43
|
+
body: slice,
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
const text = await res.text().catch(() => "");
|
|
47
|
+
throw new Error(`outlook-mail-reply: upload session PUT ${res.status} for ${att.name} (bytes ${start}-${end - 1}/${total}): ${text.slice(0, 300) || "no response body"}`);
|
|
48
|
+
}
|
|
49
|
+
chunks += 1;
|
|
50
|
+
start = end;
|
|
51
|
+
}
|
|
52
|
+
return chunks;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=upload-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-session.js","sourceRoot":"","sources":["../../src/lib/upload-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C;iEACiE;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;AAMlD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,MAAyB,EACzB,OAAe,EACf,GAAuB;IAEvB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAC9B,MAAM,EACN,gBAAgB,kBAAkB,CAAC,OAAO,CAAC,kCAAkC,EAC7E,EAAE,cAAc,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,EAC5G,EAAE,IAAI,EAAE,YAAY,EAAE,CACvB,CAAC;IACF,MAAM,SAAS,GAAI,IAA6B,EAAE,SAAS,CAAC;IAC5D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,+CAA+C,GAAG,CAAC,IAAI,yBAAyB,CACjF,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC;IACzB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO,KAAK,GAAG,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;YACjC,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,eAAe,EAAE,SAAS,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,EAAE,EAAE;YAClE,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CACb,0CAA0C,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,WAAW,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,kBAAkB,EAAE,CACzJ,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,CAAC,CAAC;QACZ,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
export interface DraftEditArgs {
|
|
3
|
+
draftId: string;
|
|
4
|
+
to?: string[];
|
|
5
|
+
cc?: string[];
|
|
6
|
+
bcc?: string[];
|
|
7
|
+
subject?: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
isHtml?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Update an existing draft in place via PATCH /me/messages/{draftId}. Graph
|
|
13
|
+
* drafts are mutable, so no delete-and-reappend. Only the supplied fields are
|
|
14
|
+
* patched; at least one editable field is required. Graph rejects a PATCH on a
|
|
15
|
+
* sent (non-draft) message — that error is surfaced to the caller unchanged.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runDraftEdit(config: GraphClientConfig, args: DraftEditArgs): Promise<{
|
|
18
|
+
draftId: string;
|
|
19
|
+
updated: true;
|
|
20
|
+
}>;
|
|
21
|
+
//# sourceMappingURL=draft-edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-edit.d.ts","sourceRoot":"","sources":["../../src/tools/draft-edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,CAyB7C"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { patchGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log } from "../lib/log.js";
|
|
3
|
+
function recip(list) {
|
|
4
|
+
return list.map((address) => ({ emailAddress: { address } }));
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Update an existing draft in place via PATCH /me/messages/{draftId}. Graph
|
|
8
|
+
* drafts are mutable, so no delete-and-reappend. Only the supplied fields are
|
|
9
|
+
* patched; at least one editable field is required. Graph rejects a PATCH on a
|
|
10
|
+
* sent (non-draft) message — that error is surfaced to the caller unchanged.
|
|
11
|
+
*/
|
|
12
|
+
export async function runDraftEdit(config, args) {
|
|
13
|
+
const patch = {};
|
|
14
|
+
if (args.subject !== undefined)
|
|
15
|
+
patch.subject = args.subject;
|
|
16
|
+
if (args.body !== undefined) {
|
|
17
|
+
patch.body = { contentType: args.isHtml ? "HTML" : "Text", content: args.body };
|
|
18
|
+
}
|
|
19
|
+
if (args.to !== undefined)
|
|
20
|
+
patch.toRecipients = recip(args.to);
|
|
21
|
+
if (args.cc !== undefined)
|
|
22
|
+
patch.ccRecipients = recip(args.cc);
|
|
23
|
+
if (args.bcc !== undefined)
|
|
24
|
+
patch.bccRecipients = recip(args.bcc);
|
|
25
|
+
if (Object.keys(patch).length === 0) {
|
|
26
|
+
throw new Error("outlook-draft-edit: pass at least one field to change (to, cc, bcc, subject, or body).");
|
|
27
|
+
}
|
|
28
|
+
await patchGraph(config, `/me/messages/${encodeURIComponent(args.draftId)}`, patch, { tool: "draft-edit" });
|
|
29
|
+
log({
|
|
30
|
+
event: "draft-edit",
|
|
31
|
+
op: "draft-edit",
|
|
32
|
+
account: config.accountId,
|
|
33
|
+
id: args.draftId,
|
|
34
|
+
fields: Object.keys(patch).join(","),
|
|
35
|
+
});
|
|
36
|
+
return { draftId: args.draftId, updated: true };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=draft-edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-edit.js","sourceRoot":"","sources":["../../src/tools/draft-edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAYpC,SAAS,KAAK,CAAC,IAAc;IAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAyB,EACzB,IAAmB;IAEnB,MAAM,KAAK,GAA4B,EAAE,CAAC;IAC1C,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAClF,CAAC;IACD,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;QAAE,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAElE,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,wFAAwF,CACzF,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,CAAC,MAAM,EAAE,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IAC5G,GAAG,CAAC;QACF,KAAK,EAAE,YAAY;QACnB,EAAE,EAAE,YAAY;QAChB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,EAAE,EAAE,IAAI,CAAC,OAAO;QAChB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KACrC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Move each named message to Deleted Items (POST /me/messages/{id}/move with
|
|
4
|
+
* destinationId "deleteditems"). Recoverable — never hard-deletes, never
|
|
5
|
+
* expunges. A message already gone (Graph 404) is counted not-moved without
|
|
6
|
+
* failing the rest; any other Graph error aborts the batch.
|
|
7
|
+
*/
|
|
8
|
+
export declare function runMailDelete(config: GraphClientConfig, args: {
|
|
9
|
+
ids: string[];
|
|
10
|
+
}): Promise<{
|
|
11
|
+
moved: string[];
|
|
12
|
+
notMoved: string[];
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=mail-delete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-delete.d.ts","sourceRoot":"","sources":["../../src/tools/mail-delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAgClD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { postGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log } from "../lib/log.js";
|
|
3
|
+
/**
|
|
4
|
+
* Move each named message to Deleted Items (POST /me/messages/{id}/move with
|
|
5
|
+
* destinationId "deleteditems"). Recoverable — never hard-deletes, never
|
|
6
|
+
* expunges. A message already gone (Graph 404) is counted not-moved without
|
|
7
|
+
* failing the rest; any other Graph error aborts the batch.
|
|
8
|
+
*/
|
|
9
|
+
export async function runMailDelete(config, args) {
|
|
10
|
+
const moved = [];
|
|
11
|
+
const notMoved = [];
|
|
12
|
+
for (const id of args.ids) {
|
|
13
|
+
try {
|
|
14
|
+
await postGraph(config, `/me/messages/${encodeURIComponent(id)}/move`, { destinationId: "deleteditems" }, { tool: "mail-delete" });
|
|
15
|
+
moved.push(id);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
// Key the "already gone" decision off the structured status code the
|
|
19
|
+
// writeGraph error carries (err.statusCode), never the prose message —
|
|
20
|
+
// matching graph-client's classification doctrine. A 404 means the id was
|
|
21
|
+
// already gone; any other status aborts the batch.
|
|
22
|
+
if (err.statusCode === 404) {
|
|
23
|
+
notMoved.push(id);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
log({
|
|
31
|
+
event: "mail-delete",
|
|
32
|
+
op: "delete",
|
|
33
|
+
account: config.accountId,
|
|
34
|
+
moved: moved.length,
|
|
35
|
+
notMoved: notMoved.length,
|
|
36
|
+
});
|
|
37
|
+
return { moved, notMoved };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=mail-delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-delete.js","sourceRoot":"","sources":["../../src/tools/mail-delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAyB,EACzB,IAAuB;IAEvB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,SAAS,CACb,MAAM,EACN,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAC7C,EAAE,aAAa,EAAE,cAAc,EAAE,EACjC,EAAE,IAAI,EAAE,aAAa,EAAE,CACxB,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,qEAAqE;YACrE,uEAAuE;YACvE,0EAA0E;YAC1E,mDAAmD;YACnD,IAAK,GAA+B,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IACD,GAAG,CAAC;QACF,KAAK,EAAE,aAAa;QACpB,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,QAAQ,EAAE,QAAQ,CAAC,MAAM;KAC1B,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
export interface FetchBodyResult {
|
|
3
|
+
id: string;
|
|
4
|
+
subject: string | null;
|
|
5
|
+
from: string | null;
|
|
6
|
+
to: string[];
|
|
7
|
+
cc: string[];
|
|
8
|
+
receivedDateTime: string;
|
|
9
|
+
conversationId: string | null;
|
|
10
|
+
isRead: boolean;
|
|
11
|
+
contentType: "html" | "text";
|
|
12
|
+
body: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read the COMPLETE body of one message by id. Graph's bodyPreview (returned by
|
|
16
|
+
* outlook-mail-list/-search) is capped near 255 chars; this requests the full
|
|
17
|
+
* `body` and decodes HTML to text. Never falls back to bodyPreview — an empty
|
|
18
|
+
* body is returned as-is (empty), and the logged `bytes` surfaces a shortfall.
|
|
19
|
+
*/
|
|
20
|
+
export declare function runMailFetchBody(config: GraphClientConfig, args: {
|
|
21
|
+
messageId: string;
|
|
22
|
+
}): Promise<FetchBodyResult>;
|
|
23
|
+
//# sourceMappingURL=mail-fetch-body.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-fetch-body.d.ts","sourceRoot":"","sources":["../../src/tools/mail-fetch-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAwBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAC1B,OAAO,CAAC,eAAe,CAAC,CAqC1B"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { callGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { htmlToText } from "../lib/html-to-text.js";
|
|
3
|
+
import { log } from "../lib/log.js";
|
|
4
|
+
const SELECT = "id,subject,from,toRecipients,ccRecipients,receivedDateTime,conversationId,isRead,body";
|
|
5
|
+
function addrs(list) {
|
|
6
|
+
return (list ?? []).map((r) => r.emailAddress?.address).filter((a) => !!a);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Read the COMPLETE body of one message by id. Graph's bodyPreview (returned by
|
|
10
|
+
* outlook-mail-list/-search) is capped near 255 chars; this requests the full
|
|
11
|
+
* `body` and decodes HTML to text. Never falls back to bodyPreview — an empty
|
|
12
|
+
* body is returned as-is (empty), and the logged `bytes` surfaces a shortfall.
|
|
13
|
+
*/
|
|
14
|
+
export async function runMailFetchBody(config, args) {
|
|
15
|
+
const msg = await callGraph(config, async (client) => (await client
|
|
16
|
+
.api(`/me/messages/${encodeURIComponent(args.messageId)}`)
|
|
17
|
+
.select(SELECT)
|
|
18
|
+
.get()), { tool: "mail-fetch-body" });
|
|
19
|
+
const rawType = (msg.body?.contentType ?? "text").toLowerCase();
|
|
20
|
+
const contentType = rawType === "html" ? "html" : "text";
|
|
21
|
+
const raw = msg.body?.content ?? "";
|
|
22
|
+
const body = contentType === "html" ? htmlToText(raw) : raw;
|
|
23
|
+
log({
|
|
24
|
+
event: "mail-fetch-body",
|
|
25
|
+
op: "fetch-body",
|
|
26
|
+
account: config.accountId,
|
|
27
|
+
id: args.messageId,
|
|
28
|
+
bytes: body.length,
|
|
29
|
+
contentType,
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
id: msg.id,
|
|
33
|
+
subject: msg.subject ?? null,
|
|
34
|
+
from: msg.from?.emailAddress?.address ?? null,
|
|
35
|
+
to: addrs(msg.toRecipients),
|
|
36
|
+
cc: addrs(msg.ccRecipients),
|
|
37
|
+
receivedDateTime: msg.receivedDateTime,
|
|
38
|
+
conversationId: msg.conversationId ?? null,
|
|
39
|
+
isRead: msg.isRead ?? false,
|
|
40
|
+
contentType,
|
|
41
|
+
body,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=mail-fetch-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-fetch-body.js","sourceRoot":"","sources":["../../src/tools/mail-fetch-body.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AA8BpC,MAAM,MAAM,GACV,uFAAuF,CAAC;AAE1F,SAAS,KAAK,CAAC,IAAgC;IAC7C,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAyB,EACzB,IAA2B;IAE3B,MAAM,GAAG,GAAG,MAAM,SAAS,CACzB,MAAM,EACN,KAAK,EAAE,MAAM,EAAE,EAAE,CACf,CAAC,MAAM,MAAM;SACV,GAAG,CAAC,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;SACzD,MAAM,CAAC,MAAM,CAAC;SACd,GAAG,EAAE,CAAe,EACzB,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAC5B,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAChE,MAAM,WAAW,GAAoB,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1E,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAE5D,GAAG,CAAC;QACF,KAAK,EAAE,iBAAiB;QACxB,EAAE,EAAE,YAAY;QAChB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,EAAE,EAAE,IAAI,CAAC,SAAS;QAClB,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,IAAI,IAAI;QAC7C,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC;QAC3B,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC;QAC3B,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,cAAc,EAAE,GAAG,CAAC,cAAc,IAAI,IAAI;QAC1C,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,KAAK;QAC3B,WAAW;QACX,IAAI;KACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
export interface OtpArgs {
|
|
3
|
+
sender: string;
|
|
4
|
+
subjectPattern?: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface OtpResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
code?: string;
|
|
10
|
+
message: string;
|
|
11
|
+
from?: string;
|
|
12
|
+
subject?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Poll the inbox for a one-time code from a specific sender. Lists recent
|
|
16
|
+
* messages, keeps those whose sender matches `sender` (and optional subject
|
|
17
|
+
* regex), reads each candidate's full body via runMailFetchBody, and extracts
|
|
18
|
+
* the code. Scans immediately, then polls every 5 s until `timeout` (default
|
|
19
|
+
* 60 s). The OTP extractor is shared verbatim with the email plugin.
|
|
20
|
+
*/
|
|
21
|
+
export declare function runMailOtpExtract(config: GraphClientConfig, args: OtpArgs): Promise<OtpResult>;
|
|
22
|
+
//# sourceMappingURL=mail-otp-extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-otp-extract.d.ts","sourceRoot":"","sources":["../../src/tools/mail-otp-extract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQhE,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAmDD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,SAAS,CAAC,CAqDpB"}
|