@agenticmail/enterprise 0.5.319 → 0.5.321
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/CHANGELOG.md +68 -0
- package/CODE_OF_CONDUCT.md +31 -0
- package/README.md +118 -38
- package/SECURITY.md +42 -0
- package/dist/agent-heartbeat-3FWNHZFX.js +510 -0
- package/dist/agent-heartbeat-4RWHZR7H.js +510 -0
- package/dist/agent-heartbeat-6ZGB5ILY.js +510 -0
- package/dist/agent-heartbeat-BIVHLKFM.js +510 -0
- package/dist/agent-heartbeat-HRKVFK2T.js +510 -0
- package/dist/agent-heartbeat-JC5GWVXD.js +510 -0
- package/dist/agent-heartbeat-K6A4HMHB.js +510 -0
- package/dist/agent-heartbeat-LCDXWFVB.js +510 -0
- package/dist/agent-heartbeat-P7HZCZAQ.js +510 -0
- package/dist/agent-heartbeat-PUIRSNIO.js +510 -0
- package/dist/agent-heartbeat-SN5ILQ6Y.js +510 -0
- package/dist/agent-heartbeat-TW5YTDYC.js +510 -0
- package/dist/agent-heartbeat-Z2QQXROL.js +510 -0
- package/dist/agent-notify-OEQBCZLN.js +43 -0
- package/dist/{agent-tools-263HM5QU.js → agent-tools-3W7XLUYA.js} +1 -1
- package/dist/agent-tools-4QK7LLNP.js +9 -0
- package/dist/agent-tools-54VZGT6L.js +9 -0
- package/dist/{agent-tools-AT4D276V.js → agent-tools-AYYDPO27.js} +7 -7
- package/dist/{agent-tools-MSTAPX2I.js → agent-tools-F2X47FKF.js} +7 -7
- package/dist/{agent-tools-FA26SY5O.js → agent-tools-O6W3QAZL.js} +11 -6
- package/dist/agent-tools-OAWVZBMW.js +9 -0
- package/dist/agent-tools-QCCU74PN.js +13949 -0
- package/dist/chunk-2LHUARN6.js +4929 -0
- package/dist/chunk-2WVCNCYC.js +5087 -0
- package/dist/{chunk-6PWDS7KY.js → chunk-3FM6YQUK.js} +20 -20
- package/dist/chunk-3UAFHUEC.js +212 -0
- package/dist/{chunk-WJO57PMO.js → chunk-46GOWZT4.js} +20 -20
- package/dist/{chunk-BNRE7TSX.js → chunk-5KYJAUZV.js} +3 -3
- package/dist/chunk-6C5PKREN.js +467 -0
- package/dist/{chunk-447MTPZF.js → chunk-6ZMLNEHB.js} +3 -3
- package/dist/chunk-BPZQT5N5.js +25652 -0
- package/dist/chunk-BQM7MBPS.js +1380 -0
- package/dist/{chunk-ZRFKGPIU.js → chunk-C52OQNNY.js} +20 -20
- package/dist/chunk-C7HGQF4Y.js +25652 -0
- package/dist/chunk-CAHNZGGK.js +25656 -0
- package/dist/{chunk-FL3CH3ET.js → chunk-CK7R6UHE.js} +51 -27
- package/dist/chunk-D36RPWB7.js +25652 -0
- package/dist/{chunk-36NM2B4C.js → chunk-DJK2UPFH.js} +63 -93
- package/dist/chunk-DM7FTF7W.js +4929 -0
- package/dist/chunk-DMD24UFZ.js +5101 -0
- package/dist/{chunk-36XNMIHA.js → chunk-DXZGPUAF.js} +20 -20
- package/dist/chunk-F46WB5IL.js +5087 -0
- package/dist/chunk-F5QG5SQH.js +5087 -0
- package/dist/{chunk-JGEVQZDR.js → chunk-FLQ5FLHW.js} +13 -16
- package/dist/chunk-H7GP733U.js +5087 -0
- package/dist/{chunk-OZSQLOV6.js → chunk-HHBXWB5U.js} +415 -19
- package/dist/{chunk-D24JY75H.js → chunk-IMXS4N6W.js} +3 -3
- package/dist/{chunk-6PVBV6ZP.js → chunk-JNMDD7JY.js} +3 -3
- package/dist/chunk-JTV5LA47.js +1519 -0
- package/dist/chunk-KV6G7NZX.js +1519 -0
- package/dist/chunk-MU5MEBIK.js +1519 -0
- package/dist/chunk-NLT5MC7X.js +465 -0
- package/dist/{chunk-GTFZZUXX.js → chunk-NVLYIM4J.js} +51 -27
- package/dist/{chunk-6G5SXLXC.js → chunk-NZY2BIZH.js} +63 -93
- package/dist/chunk-O42L6G67.js +1519 -0
- package/dist/chunk-OCNERGGM.js +4891 -0
- package/dist/chunk-OJSNHONE.js +1519 -0
- package/dist/{chunk-2TAZJWJN.js → chunk-OWL3QVH7.js} +18 -0
- package/dist/{chunk-P3HVY2HS.js → chunk-OWTLNV4Q.js} +382 -7
- package/dist/chunk-PCNYEP6T.js +4891 -0
- package/dist/{chunk-YL3Z5KPR.js → chunk-PI4AQ4Z6.js} +438 -15
- package/dist/chunk-PN3EGTCA.js +194 -0
- package/dist/chunk-Q37UKNRC.js +1519 -0
- package/dist/chunk-QXTC6J7H.js +5087 -0
- package/dist/{chunk-SPBQVNDI.js → chunk-RKERL5LZ.js} +25 -21
- package/dist/chunk-RVBK2IOX.js +25652 -0
- package/dist/chunk-SAKODCZ5.js +4891 -0
- package/dist/{chunk-XV4TU65E.js → chunk-SALGFC5L.js} +51 -27
- package/dist/chunk-STGWZ2MS.js +1519 -0
- package/dist/chunk-UY3ZVQDP.js +25652 -0
- package/dist/chunk-V6OSD62M.js +5087 -0
- package/dist/chunk-VP6YAHX4.js +1519 -0
- package/dist/chunk-WDYJOEAI.js +5087 -0
- package/dist/chunk-WEAFQNOS.js +195 -0
- package/dist/chunk-XKUSAZGP.js +5087 -0
- package/dist/chunk-Z6K5FKAB.js +548 -0
- package/dist/chunk-ZGE3XAXY.js +1519 -0
- package/dist/chunk-ZGYVXYQQ.js +3296 -0
- package/dist/cli-agent-7TB2BWS6.js +2370 -0
- package/dist/cli-agent-AKXFFST2.js +2370 -0
- package/dist/cli-agent-DZTKLITB.js +2357 -0
- package/dist/cli-agent-FOF7PFEP.js +2357 -0
- package/dist/cli-agent-H74M2ZYN.js +2357 -0
- package/dist/cli-agent-HORWVPHB.js +2370 -0
- package/dist/cli-agent-HSZT6SKF.js +2423 -0
- package/dist/cli-agent-JLUQ4ZU6.js +2424 -0
- package/dist/cli-agent-MVCDH4HV.js +2370 -0
- package/dist/cli-agent-NZXOEPJ2.js +2357 -0
- package/dist/cli-agent-PADN3QRC.js +2357 -0
- package/dist/cli-agent-QAYEX3BE.js +2441 -0
- package/dist/cli-agent-QT64DT5J.js +2370 -0
- package/dist/cli-agent-TFL2M6UK.js +2424 -0
- package/dist/cli-agent-UIKXATTD.js +2357 -0
- package/dist/cli-agent-UJN6FYTO.js +2370 -0
- package/dist/cli-agent-VIQAYVY4.js +2357 -0
- package/dist/cli-agent-WNWFVOFM.js +2370 -0
- package/dist/cli-agent-XBQX67VJ.js +2423 -0
- package/dist/cli-agent-ZLSC6FF4.js +2357 -0
- package/dist/cli-serve-2IL5DTEY.js +153 -0
- package/dist/cli-serve-47N5UKKW.js +153 -0
- package/dist/cli-serve-4XGZFUV2.js +140 -0
- package/dist/cli-serve-6OT3UEAN.js +140 -0
- package/dist/cli-serve-7L6EY5UH.js +153 -0
- package/dist/cli-serve-BDGOOOKQ.js +260 -0
- package/dist/cli-serve-BFNIW2LF.js +153 -0
- package/dist/cli-serve-C7MN6U5Q.js +153 -0
- package/dist/cli-serve-CR3OY3IM.js +153 -0
- package/dist/cli-serve-DAJFRWQ7.js +153 -0
- package/dist/cli-serve-FW6FHFW4.js +153 -0
- package/dist/cli-serve-GEEOQS77.js +153 -0
- package/dist/cli-serve-H562I3ZK.js +153 -0
- package/dist/cli-serve-HDQZF4C4.js +153 -0
- package/dist/cli-serve-LICAOMEB.js +140 -0
- package/dist/cli-serve-LLGYLWFS.js +153 -0
- package/dist/cli-serve-N3OISDNB.js +153 -0
- package/dist/cli-serve-TIZ27EVR.js +153 -0
- package/dist/cli-serve-TUNI2RCN.js +153 -0
- package/dist/cli-serve-WNOZMAWD.js +153 -0
- package/dist/cli-validate-Z726VJCN.js +150 -0
- package/dist/cli.js +4 -4
- package/dist/connection-manager-KAWEUWUR.js +9 -0
- package/dist/dashboard/app.js +9 -3
- package/dist/dashboard/components/knowledge-link.js +15 -0
- package/dist/dashboard/components/settings-help.js +4 -2
- package/dist/dashboard/docs/agent-deployment.html +33 -1
- package/dist/dashboard/docs/settings-network.html +321 -0
- package/dist/dashboard/docs/settings-security.html +347 -0
- package/dist/dashboard/docs/settings-tool-security.html +176 -0
- package/dist/dashboard/docs/settings.html +36 -16
- package/dist/dashboard/pages/agent-detail/deployment.js +39 -6
- package/dist/dashboard/pages/agent-detail/tools.js +10 -0
- package/dist/dashboard/pages/database-access.js +4 -3
- package/dist/dashboard/pages/settings.js +174 -37
- package/dist/dashboard/pages/task-pipeline.js +400 -843
- package/dist/db-adapter-2T56ORSD.js +7 -0
- package/dist/db-adapter-IRHOUMVC.js +7 -0
- package/dist/index.js +41 -41
- package/dist/microsoft-VREAZ7M2.js +3955 -0
- package/dist/routes-3MMLQTB6.js +90 -0
- package/dist/routes-4ZUIJ4HE.js +90 -0
- package/dist/routes-5MXHKKH4.js +90 -0
- package/dist/routes-64NJFK3B.js +90 -0
- package/dist/routes-6AKQ2LBV.js +90 -0
- package/dist/routes-CRRBUDO4.js +90 -0
- package/dist/routes-DIAF3MC3.js +90 -0
- package/dist/routes-KMUNU6CY.js +90 -0
- package/dist/routes-LRRLXIZR.js +90 -0
- package/dist/routes-N647AJYG.js +90 -0
- package/dist/routes-SSSELAAR.js +90 -0
- package/dist/routes-STERVGKJ.js +90 -0
- package/dist/routes-ZEZZACZP.js +90 -0
- package/dist/runtime-5EQN4GFM.js +45 -0
- package/dist/runtime-5LP7PUD4.js +45 -0
- package/dist/runtime-6BULDBR3.js +45 -0
- package/dist/runtime-6YEENDN3.js +45 -0
- package/dist/runtime-7LQFRG3B.js +45 -0
- package/dist/runtime-AMXJU2MB.js +45 -0
- package/dist/runtime-D6WSE7FG.js +45 -0
- package/dist/runtime-EYVN7NFJ.js +45 -0
- package/dist/runtime-F6RPWQVW.js +45 -0
- package/dist/runtime-FYMJURFC.js +45 -0
- package/dist/runtime-JRNBL4O4.js +45 -0
- package/dist/runtime-OM2NIBMI.js +45 -0
- package/dist/runtime-QWPVD7CY.js +45 -0
- package/dist/runtime-YLIIPTE4.js +45 -0
- package/dist/runtime-YU6P22CG.js +45 -0
- package/dist/screen-unlock-4RPZBHOI.js +118 -0
- package/dist/server-AMCSXINC.js +28 -0
- package/dist/server-CU6LVQS4.js +28 -0
- package/dist/server-DFYGH2CV.js +28 -0
- package/dist/server-EELWOC3X.js +28 -0
- package/dist/server-EN5E2OWQ.js +28 -0
- package/dist/server-GW2HYJYI.js +28 -0
- package/dist/server-J25NCRWJ.js +28 -0
- package/dist/server-JDGNOTFV.js +28 -0
- package/dist/server-NE5HD5DJ.js +28 -0
- package/dist/server-NQOT7W77.js +28 -0
- package/dist/server-PWE5PQTR.js +28 -0
- package/dist/server-Q2Q32H2B.js +28 -0
- package/dist/server-Q77ME7TL.js +28 -0
- package/dist/server-WLLH4WST.js +28 -0
- package/dist/server-WTUJ2O3F.js +28 -0
- package/dist/server-X4CJTHHF.js +28 -0
- package/dist/server-XK3ILCJC.js +28 -0
- package/dist/server-ZRD3NDJE.js +28 -0
- package/dist/setup-44VBAO4J.js +20 -0
- package/dist/setup-4ONNQBWB.js +20 -0
- package/dist/setup-4OSBXSCL.js +20 -0
- package/dist/setup-4QFGRBLZ.js +20 -0
- package/dist/setup-6766SGAR.js +20 -0
- package/dist/setup-AYY24DKM.js +20 -0
- package/dist/setup-B34N4HPU.js +20 -0
- package/dist/setup-E2YLC2EY.js +20 -0
- package/dist/setup-ER6NXTY5.js +20 -0
- package/dist/setup-H2AGCBW5.js +20 -0
- package/dist/setup-ICOZRKCX.js +20 -0
- package/dist/setup-JFTJH7UF.js +20 -0
- package/dist/setup-PRFNI6YW.js +20 -0
- package/dist/setup-RAHBMYHE.js +20 -0
- package/dist/setup-TXPR5UQX.js +20 -0
- package/dist/setup-XCJMELVU.js +20 -0
- package/dist/setup-XIYEIFVK.js +20 -0
- package/dist/setup-Z4PZSHBI.js +20 -0
- package/dist/skills-FR7I5V7H.js +16 -0
- package/dist/skills-HCVBA6PK.js +16 -0
- package/dist/system-prompts-TM7OA32C.js +913 -0
- package/dist/task-queue-O7IVZYUO.js +9 -0
- package/dist/transport-encryption-2T7PIXKG.js +25 -0
- package/logs/cloudflared-error.log +61 -0
- package/logs/cloudflared-out.log +0 -0
- package/logs/enterprise-error.log +0 -0
- package/logs/enterprise-out.log +3 -0
- package/logs/fola-error.log +0 -0
- package/logs/fola-out.log +0 -0
- package/logs/john-error.log +8 -0
- package/logs/john-out.log +0 -0
- package/package.json +31 -3
- package/src/agent-tools/tool-resolver.ts +50 -61
- package/src/agent-tools/tools/enterprise-database.ts +5 -5
- package/src/agent-tools/tools/local/dependency-manager.ts +2 -2
- package/src/agent-tools/tools/microsoft/graph-api.ts +137 -26
- package/src/agent-tools/tools/microsoft/outlook-mail.ts +392 -100
- package/src/agent-tools/tools/microsoft/teams.ts +267 -48
- package/src/auth/routes.ts +4 -4
- package/src/cli-agent.ts +108 -8
- package/src/cli-serve.ts +140 -0
- package/src/dashboard/app.js +9 -3
- package/src/dashboard/components/knowledge-link.js +15 -0
- package/src/dashboard/components/settings-help.js +4 -2
- package/src/dashboard/docs/agent-deployment.html +33 -1
- package/src/dashboard/docs/settings-network.html +321 -0
- package/src/dashboard/docs/settings-security.html +347 -0
- package/src/dashboard/docs/settings-tool-security.html +176 -0
- package/src/dashboard/docs/settings.html +36 -16
- package/src/dashboard/pages/agent-detail/deployment.js +39 -6
- package/src/dashboard/pages/agent-detail/tools.js +10 -0
- package/src/dashboard/pages/database-access.js +4 -3
- package/src/dashboard/pages/settings.js +174 -37
- package/src/dashboard/pages/task-pipeline.js +400 -843
- package/src/database-access/agent-tools.ts +78 -63
- package/src/database-access/connection-manager.ts +13 -2
- package/src/database-access/routes.ts +13 -1
- package/src/db/adapter.ts +1 -0
- package/src/engine/agent-memory.ts +2 -1
- package/src/engine/agent-notify.ts +50 -0
- package/src/engine/agent-routes.ts +257 -4
- package/src/engine/db-adapter.ts +16 -0
- package/src/engine/lifecycle.ts +4 -0
- package/src/engine/routes.ts +4 -3
- package/src/engine/screen-unlock.ts +136 -0
- package/src/engine/skills/database-access.ts +78 -0
- package/src/engine/skills/index.ts +3 -2
- package/src/engine/skills.ts +2 -0
- package/src/engine/task-queue-routes.ts +18 -0
- package/src/engine/task-queue.ts +15 -2
- package/src/middleware/transport-encryption.ts +1 -4
- package/src/runtime/agent-loop.ts +4 -0
- package/src/runtime/index.ts +15 -6
- package/src/server.ts +14 -1
- package/src/system-prompts/google/index.ts +1 -2
- package/src/system-prompts/index.ts +1 -1
- package/src/system-prompts/microsoft/contacts.ts +34 -0
- package/src/system-prompts/microsoft/excel.ts +52 -0
- package/src/system-prompts/microsoft/index.ts +31 -0
- package/src/system-prompts/microsoft/onedrive.ts +41 -0
- package/src/system-prompts/microsoft/onenote.ts +36 -0
- package/src/system-prompts/microsoft/outlook-calendar.ts +37 -0
- package/src/system-prompts/microsoft/outlook-mail.ts +46 -0
- package/src/system-prompts/microsoft/planner.ts +37 -0
- package/src/system-prompts/microsoft/powerbi.ts +38 -0
- package/src/system-prompts/microsoft/powerpoint.ts +35 -0
- package/src/system-prompts/microsoft/sharepoint.ts +44 -0
- package/src/system-prompts/microsoft/teams.ts +49 -0
- package/src/system-prompts/microsoft/todo.ts +37 -0
- package/src/types/hono-env.ts +4 -0
- package/.github/CODEOWNERS +0 -23
- package/.github/workflows/publish-community-skills.yml +0 -121
- package/.github/workflows/validate-community-skills.yml +0 -172
- package/agriculture_southwest_nigeria_research.txt +0 -10
- package/boa_credit_cards_research.txt +0 -10
- package/customer_support_research_feb2026.txt +0 -10
- package/dist/agent-tools-LRA7PPXG.js +0 -13922
- package/dist/agent-tools-VAU5DOQB.js +0 -13910
- package/dist/agent-tools-VWV7OWXU.js +0 -13922
- package/dist/chunk-2Z7MWTCX.js +0 -4977
- package/dist/chunk-3T4XU3VV.js +0 -5010
- package/dist/chunk-445QM4NX.js +0 -5061
- package/dist/chunk-5TW3Y7DJ.js +0 -1519
- package/dist/chunk-6I7VY3LT.js +0 -5060
- package/dist/chunk-6W5EK3UP.js +0 -4977
- package/dist/chunk-AQMSHJQT.js +0 -5069
- package/dist/chunk-ASSQW7HX.js +0 -5051
- package/dist/chunk-CIN27FGC.js +0 -5037
- package/dist/chunk-CMXY3NUB.js +0 -4977
- package/dist/chunk-DRLMRUDP.js +0 -5052
- package/dist/chunk-EHI7Z446.js +0 -1519
- package/dist/chunk-FEAILFAQ.js +0 -1519
- package/dist/chunk-GA3PYBZL.js +0 -1519
- package/dist/chunk-GWX63G5J.js +0 -1519
- package/dist/chunk-HHMZ4UY6.js +0 -1519
- package/dist/chunk-HVQMNF7E.js +0 -4921
- package/dist/chunk-HXM7F3YN.js +0 -1519
- package/dist/chunk-K6NGOUXG.js +0 -5060
- package/dist/chunk-KPG5WINJ.js +0 -4977
- package/dist/chunk-LBCUBYDL.js +0 -1519
- package/dist/chunk-LIRQSWLR.js +0 -5014
- package/dist/chunk-LRCKO5KE.js +0 -1519
- package/dist/chunk-M7XL3DJD.js +0 -5069
- package/dist/chunk-MHJULEIQ.js +0 -1519
- package/dist/chunk-MJGGW6MC.js +0 -106
- package/dist/chunk-MMYBDHDB.js +0 -4921
- package/dist/chunk-MQT5FXKD.js +0 -1519
- package/dist/chunk-OIMPEQF5.js +0 -4977
- package/dist/chunk-OOU7JUYE.js +0 -542
- package/dist/chunk-OW4GLBHP.js +0 -1519
- package/dist/chunk-Q4K4MMLU.js +0 -4977
- package/dist/chunk-RUK4CRPF.js +0 -1519
- package/dist/chunk-T7H65XQY.js +0 -1519
- package/dist/chunk-TQVFWG57.js +0 -5064
- package/dist/chunk-UEPK3IMC.js +0 -1519
- package/dist/chunk-VUWTXJH6.js +0 -1519
- package/dist/chunk-WCPGGSAD.js +0 -1519
- package/dist/chunk-WO63NZOJ.js +0 -1519
- package/dist/chunk-YPJDRVUM.js +0 -5064
- package/dist/chunk-ZROMH5DL.js +0 -4921
- package/src/dashboard/docs/_template.txt +0 -92
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Microsoft Outlook Mail Tools
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Comprehensive Outlook/Exchange mail management via Microsoft Graph API.
|
|
5
|
+
* 20 tools covering inbox, send, reply, forward, drafts, folders, attachments,
|
|
6
|
+
* search, threads, rules, auto-reply, signatures, and categories.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import type { AnyAgentTool, ToolCreationOptions } from '../../types.js';
|
|
@@ -10,21 +11,61 @@ import { jsonResult, errorResult } from '../../common.js';
|
|
|
10
11
|
import type { MicrosoftToolsConfig } from './index.js';
|
|
11
12
|
import { graph } from './graph-api.js';
|
|
12
13
|
|
|
14
|
+
function mapMessage(m: any, full = false): any {
|
|
15
|
+
const result: any = {
|
|
16
|
+
id: m.id,
|
|
17
|
+
subject: m.subject,
|
|
18
|
+
from: m.from?.emailAddress?.address,
|
|
19
|
+
fromName: m.from?.emailAddress?.name,
|
|
20
|
+
to: m.toRecipients?.map((r: any) => r.emailAddress?.address),
|
|
21
|
+
date: m.receivedDateTime,
|
|
22
|
+
isRead: m.isRead,
|
|
23
|
+
hasAttachments: m.hasAttachments,
|
|
24
|
+
importance: m.importance,
|
|
25
|
+
conversationId: m.conversationId,
|
|
26
|
+
};
|
|
27
|
+
if (!full) {
|
|
28
|
+
result.preview = m.bodyPreview;
|
|
29
|
+
result.flagged = m.flag?.flagStatus === 'flagged';
|
|
30
|
+
result.cc = m.ccRecipients?.map((r: any) => r.emailAddress?.address);
|
|
31
|
+
} else {
|
|
32
|
+
result.to = m.toRecipients?.map((r: any) => ({ email: r.emailAddress?.address, name: r.emailAddress?.name }));
|
|
33
|
+
result.cc = m.ccRecipients?.map((r: any) => ({ email: r.emailAddress?.address, name: r.emailAddress?.name }));
|
|
34
|
+
result.bcc = m.bccRecipients?.map((r: any) => ({ email: r.emailAddress?.address, name: r.emailAddress?.name }));
|
|
35
|
+
result.replyTo = m.replyTo?.map((r: any) => r.emailAddress?.address);
|
|
36
|
+
result.sentDate = m.sentDateTime;
|
|
37
|
+
result.body = m.body?.content;
|
|
38
|
+
result.bodyType = m.body?.contentType;
|
|
39
|
+
result.internetMessageId = m.internetMessageId;
|
|
40
|
+
result.categories = m.categories;
|
|
41
|
+
result.flagged = m.flag?.flagStatus === 'flagged';
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const LIST_SELECT = 'id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead,hasAttachments,importance,bodyPreview,flag,conversationId,categories';
|
|
47
|
+
const FULL_SELECT = 'id,subject,from,toRecipients,ccRecipients,bccRecipients,replyTo,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,body,flag,conversationId,internetMessageId,parentFolderId,categories';
|
|
48
|
+
|
|
49
|
+
function parseRecipients(str: string) {
|
|
50
|
+
return str.split(',').map((e: string) => ({ emailAddress: { address: e.trim() } }));
|
|
51
|
+
}
|
|
52
|
+
|
|
13
53
|
export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?: ToolCreationOptions): AnyAgentTool[] {
|
|
14
54
|
const tp = config.tokenProvider;
|
|
15
55
|
|
|
16
56
|
return [
|
|
17
57
|
{
|
|
18
58
|
name: 'outlook_mail_list',
|
|
19
|
-
description: 'List messages from Outlook mailbox. Returns recent emails from inbox or specified folder.',
|
|
59
|
+
description: 'List messages from Outlook mailbox. Returns recent emails from inbox or specified folder. Supports OData filtering and search.',
|
|
20
60
|
category: 'utility' as const,
|
|
21
61
|
parameters: {
|
|
22
62
|
type: 'object' as const,
|
|
23
63
|
properties: {
|
|
24
|
-
folder: { type: 'string', description: 'Folder: inbox, sentitems, drafts, deleteditems, junkemail, or folder ID (default: inbox)' },
|
|
64
|
+
folder: { type: 'string', description: 'Folder: inbox, sentitems, drafts, deleteditems, junkemail, archive, or folder ID (default: inbox)' },
|
|
25
65
|
maxResults: { type: 'number', description: 'Max messages to return (default: 20, max: 50)' },
|
|
26
|
-
filter: { type: 'string', description: 'OData $filter
|
|
27
|
-
search: { type: 'string', description: 'Search query (searches subject, body, sender)' },
|
|
66
|
+
filter: { type: 'string', description: 'OData $filter (e.g., "isRead eq false", "from/emailAddress/address eq \'user@example.com\'", "hasAttachments eq true", "importance eq \'high\'")' },
|
|
67
|
+
search: { type: 'string', description: 'Search query (searches subject, body, sender — natural language or KQL)' },
|
|
68
|
+
orderBy: { type: 'string', description: 'Sort order (default: "receivedDateTime desc"). Options: receivedDateTime, from/emailAddress/address, subject, importance' },
|
|
28
69
|
},
|
|
29
70
|
required: [],
|
|
30
71
|
},
|
|
@@ -35,56 +76,43 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
35
76
|
const top = Math.min(params.maxResults || 20, 50);
|
|
36
77
|
const query: Record<string, string> = {
|
|
37
78
|
'$top': String(top),
|
|
38
|
-
'$orderby': 'receivedDateTime desc',
|
|
39
|
-
'$select':
|
|
79
|
+
'$orderby': params.orderBy || 'receivedDateTime desc',
|
|
80
|
+
'$select': LIST_SELECT,
|
|
40
81
|
};
|
|
41
82
|
if (params.filter) query['$filter'] = params.filter;
|
|
42
83
|
if (params.search) query['$search'] = `"${params.search}"`;
|
|
43
|
-
|
|
44
84
|
const data = await graph(token, `/me/mailFolders/${folder}/messages`, { query });
|
|
45
|
-
const messages = (data.value || []).map((m: any) => (
|
|
46
|
-
|
|
47
|
-
subject: m.subject,
|
|
48
|
-
from: m.from?.emailAddress?.address,
|
|
49
|
-
fromName: m.from?.emailAddress?.name,
|
|
50
|
-
to: m.toRecipients?.map((r: any) => r.emailAddress?.address),
|
|
51
|
-
cc: m.ccRecipients?.map((r: any) => r.emailAddress?.address),
|
|
52
|
-
date: m.receivedDateTime,
|
|
53
|
-
isRead: m.isRead,
|
|
54
|
-
hasAttachments: m.hasAttachments,
|
|
55
|
-
importance: m.importance,
|
|
56
|
-
preview: m.bodyPreview,
|
|
57
|
-
flagged: m.flag?.flagStatus === 'flagged',
|
|
58
|
-
conversationId: m.conversationId,
|
|
59
|
-
}));
|
|
60
|
-
return jsonResult({ messages, count: messages.length });
|
|
85
|
+
const messages = (data.value || []).map((m: any) => mapMessage(m));
|
|
86
|
+
return jsonResult({ messages, count: messages.length, folder });
|
|
61
87
|
} catch (e: any) { return errorResult(e.message); }
|
|
62
88
|
},
|
|
63
89
|
},
|
|
64
90
|
|
|
65
91
|
{
|
|
66
92
|
name: 'outlook_mail_read',
|
|
67
|
-
description: 'Read a specific email message by ID. Returns full body, headers, and
|
|
93
|
+
description: 'Read a specific email message by ID. Returns full body, headers, attachments list, and categories.',
|
|
68
94
|
category: 'utility' as const,
|
|
69
95
|
parameters: {
|
|
70
96
|
type: 'object' as const,
|
|
71
97
|
properties: {
|
|
72
98
|
messageId: { type: 'string', description: 'Message ID to read' },
|
|
73
99
|
markAsRead: { type: 'boolean', description: 'Mark as read when opening (default: true)' },
|
|
100
|
+
preferText: { type: 'boolean', description: 'Request plain text body instead of HTML (default: false)' },
|
|
74
101
|
},
|
|
75
102
|
required: ['messageId'],
|
|
76
103
|
},
|
|
77
104
|
async execute(_id: string, params: any) {
|
|
78
105
|
try {
|
|
79
106
|
const token = await tp.getAccessToken();
|
|
107
|
+
const headers: Record<string, string> = {};
|
|
108
|
+
if (params.preferText) headers['Prefer'] = 'outlook.body-content-type="text"';
|
|
80
109
|
const msg = await graph(token, `/me/messages/${params.messageId}`, {
|
|
81
|
-
query: { '$select':
|
|
110
|
+
query: { '$select': FULL_SELECT },
|
|
111
|
+
headers,
|
|
82
112
|
});
|
|
83
|
-
// Mark as read
|
|
84
113
|
if (params.markAsRead !== false && !msg.isRead) {
|
|
85
114
|
graph(token, `/me/messages/${params.messageId}`, { method: 'PATCH', body: { isRead: true } }).catch(() => {});
|
|
86
115
|
}
|
|
87
|
-
// Get attachments if any
|
|
88
116
|
let attachments: any[] = [];
|
|
89
117
|
if (msg.hasAttachments) {
|
|
90
118
|
const att = await graph(token, `/me/messages/${params.messageId}/attachments`, {
|
|
@@ -95,32 +123,53 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
95
123
|
size: a.size, isInline: a.isInline,
|
|
96
124
|
}));
|
|
97
125
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
const result = mapMessage(msg, true);
|
|
127
|
+
result.attachments = attachments;
|
|
128
|
+
result.attachmentCount = attachments.length;
|
|
129
|
+
return jsonResult(result);
|
|
130
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
{
|
|
135
|
+
name: 'outlook_mail_thread',
|
|
136
|
+
description: 'Get all messages in a conversation thread. Groups related emails by conversationId for context.',
|
|
137
|
+
category: 'utility' as const,
|
|
138
|
+
parameters: {
|
|
139
|
+
type: 'object' as const,
|
|
140
|
+
properties: {
|
|
141
|
+
conversationId: { type: 'string', description: 'Conversation ID (from any message in the thread)' },
|
|
142
|
+
messageId: { type: 'string', description: 'Message ID — will auto-find its conversationId' },
|
|
143
|
+
maxResults: { type: 'number', description: 'Max messages in thread (default: 25)' },
|
|
144
|
+
},
|
|
145
|
+
required: [],
|
|
146
|
+
},
|
|
147
|
+
async execute(_id: string, params: any) {
|
|
148
|
+
try {
|
|
149
|
+
const token = await tp.getAccessToken();
|
|
150
|
+
let convId = params.conversationId;
|
|
151
|
+
if (!convId && params.messageId) {
|
|
152
|
+
const msg = await graph(token, `/me/messages/${params.messageId}`, { query: { '$select': 'conversationId' } });
|
|
153
|
+
convId = msg.conversationId;
|
|
154
|
+
}
|
|
155
|
+
if (!convId) throw new Error('Provide conversationId or messageId');
|
|
156
|
+
const data = await graph(token, '/me/messages', {
|
|
157
|
+
query: {
|
|
158
|
+
'$filter': `conversationId eq '${convId}'`,
|
|
159
|
+
'$orderby': 'receivedDateTime asc',
|
|
160
|
+
'$top': String(params.maxResults || 25),
|
|
161
|
+
'$select': FULL_SELECT,
|
|
162
|
+
}
|
|
116
163
|
});
|
|
164
|
+
const messages = (data.value || []).map((m: any) => mapMessage(m, true));
|
|
165
|
+
return jsonResult({ conversationId: convId, messages, count: messages.length });
|
|
117
166
|
} catch (e: any) { return errorResult(e.message); }
|
|
118
167
|
},
|
|
119
168
|
},
|
|
120
169
|
|
|
121
170
|
{
|
|
122
171
|
name: 'outlook_mail_send',
|
|
123
|
-
description: 'Send an email via Outlook. Supports to, cc, bcc, HTML body, importance, and reply-to.',
|
|
172
|
+
description: 'Send an email via Outlook. Supports to, cc, bcc, HTML body, attachments (base64), importance, and reply-to.',
|
|
124
173
|
category: 'utility' as const,
|
|
125
174
|
parameters: {
|
|
126
175
|
type: 'object' as const,
|
|
@@ -131,28 +180,36 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
131
180
|
cc: { type: 'string', description: 'CC recipients, comma-separated' },
|
|
132
181
|
bcc: { type: 'string', description: 'BCC recipients, comma-separated' },
|
|
133
182
|
importance: { type: 'string', description: 'low, normal, or high (default: normal)' },
|
|
134
|
-
isHtml: { type: 'boolean', description: 'Whether body is HTML (default:
|
|
183
|
+
isHtml: { type: 'boolean', description: 'Whether body is HTML (default: auto-detect)' },
|
|
135
184
|
replyTo: { type: 'string', description: 'Reply-to address' },
|
|
136
185
|
saveToSent: { type: 'boolean', description: 'Save to Sent Items (default: true)' },
|
|
186
|
+
attachments: { type: 'array', description: 'Array of {name, contentType, contentBytes} — contentBytes is base64' },
|
|
187
|
+
categories: { type: 'array', items: { type: 'string' }, description: 'Category labels to apply' },
|
|
137
188
|
},
|
|
138
189
|
required: ['to', 'subject', 'body'],
|
|
139
190
|
},
|
|
140
191
|
async execute(_id: string, params: any) {
|
|
141
192
|
try {
|
|
142
193
|
const token = await tp.getAccessToken();
|
|
143
|
-
const
|
|
144
|
-
emailAddress: { address: e.trim() }
|
|
145
|
-
}));
|
|
194
|
+
const isHtml = params.isHtml ?? (/<[a-z][\s\S]*>/i.test(params.body));
|
|
146
195
|
const message: any = {
|
|
147
196
|
subject: params.subject,
|
|
148
|
-
body: { contentType:
|
|
149
|
-
toRecipients,
|
|
197
|
+
body: { contentType: isHtml ? 'HTML' : 'Text', content: params.body },
|
|
198
|
+
toRecipients: parseRecipients(params.to),
|
|
150
199
|
};
|
|
151
|
-
if (params.cc) message.ccRecipients = params.cc
|
|
152
|
-
if (params.bcc) message.bccRecipients = params.bcc
|
|
200
|
+
if (params.cc) message.ccRecipients = parseRecipients(params.cc);
|
|
201
|
+
if (params.bcc) message.bccRecipients = parseRecipients(params.bcc);
|
|
153
202
|
if (params.importance) message.importance = params.importance;
|
|
154
203
|
if (params.replyTo) message.replyTo = [{ emailAddress: { address: params.replyTo } }];
|
|
155
|
-
|
|
204
|
+
if (params.categories) message.categories = params.categories;
|
|
205
|
+
if (params.attachments?.length) {
|
|
206
|
+
message.attachments = params.attachments.map((a: any) => ({
|
|
207
|
+
'@odata.type': '#microsoft.graph.fileAttachment',
|
|
208
|
+
name: a.name,
|
|
209
|
+
contentType: a.contentType || 'application/octet-stream',
|
|
210
|
+
contentBytes: a.contentBytes,
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
156
213
|
await graph(token, '/me/sendMail', {
|
|
157
214
|
method: 'POST',
|
|
158
215
|
body: { message, saveToSentItems: params.saveToSent !== false },
|
|
@@ -164,7 +221,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
164
221
|
|
|
165
222
|
{
|
|
166
223
|
name: 'outlook_mail_reply',
|
|
167
|
-
description: 'Reply to an email
|
|
224
|
+
description: 'Reply to an email. Can reply to sender only or reply-all. Supports HTML and attachments.',
|
|
168
225
|
category: 'utility' as const,
|
|
169
226
|
parameters: {
|
|
170
227
|
type: 'object' as const,
|
|
@@ -173,6 +230,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
173
230
|
body: { type: 'string', description: 'Reply body text' },
|
|
174
231
|
replyAll: { type: 'boolean', description: 'Reply to all recipients (default: false)' },
|
|
175
232
|
isHtml: { type: 'boolean', description: 'Whether body is HTML (default: false)' },
|
|
233
|
+
attachments: { type: 'array', description: 'Array of {name, contentType, contentBytes}' },
|
|
176
234
|
},
|
|
177
235
|
required: ['messageId', 'body'],
|
|
178
236
|
},
|
|
@@ -180,10 +238,33 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
180
238
|
try {
|
|
181
239
|
const token = await tp.getAccessToken();
|
|
182
240
|
const action = params.replyAll ? 'replyAll' : 'reply';
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
241
|
+
const body: any = { comment: params.body };
|
|
242
|
+
if (params.attachments?.length) {
|
|
243
|
+
// Need to create reply as draft, add attachments, then send
|
|
244
|
+
const draft = await graph(token, `/me/messages/${params.messageId}/createReply`, { method: 'POST' });
|
|
245
|
+
// Update body
|
|
246
|
+
await graph(token, `/me/messages/${draft.id}`, {
|
|
247
|
+
method: 'PATCH',
|
|
248
|
+
body: {
|
|
249
|
+
body: { contentType: params.isHtml ? 'HTML' : 'Text', content: params.body },
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
// Add attachments
|
|
253
|
+
for (const a of params.attachments) {
|
|
254
|
+
await graph(token, `/me/messages/${draft.id}/attachments`, {
|
|
255
|
+
method: 'POST',
|
|
256
|
+
body: {
|
|
257
|
+
'@odata.type': '#microsoft.graph.fileAttachment',
|
|
258
|
+
name: a.name,
|
|
259
|
+
contentType: a.contentType || 'application/octet-stream',
|
|
260
|
+
contentBytes: a.contentBytes,
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
await graph(token, `/me/messages/${draft.id}/send`, { method: 'POST' });
|
|
265
|
+
return jsonResult({ replied: true, messageId: params.messageId, replyAll: !!params.replyAll, withAttachments: true });
|
|
266
|
+
}
|
|
267
|
+
await graph(token, `/me/messages/${params.messageId}/${action}`, { method: 'POST', body });
|
|
187
268
|
return jsonResult({ replied: true, messageId: params.messageId, replyAll: !!params.replyAll });
|
|
188
269
|
} catch (e: any) { return errorResult(e.message); }
|
|
189
270
|
},
|
|
@@ -191,24 +272,23 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
191
272
|
|
|
192
273
|
{
|
|
193
274
|
name: 'outlook_mail_forward',
|
|
194
|
-
description: 'Forward an email
|
|
275
|
+
description: 'Forward an email to another recipient with an optional comment.',
|
|
195
276
|
category: 'utility' as const,
|
|
196
277
|
parameters: {
|
|
197
278
|
type: 'object' as const,
|
|
198
279
|
properties: {
|
|
199
280
|
messageId: { type: 'string', description: 'Message ID to forward' },
|
|
200
281
|
to: { type: 'string', description: 'Forward recipient email(s), comma-separated' },
|
|
201
|
-
comment: { type: 'string', description: 'Optional comment
|
|
282
|
+
comment: { type: 'string', description: 'Optional comment above the forwarded message' },
|
|
202
283
|
},
|
|
203
284
|
required: ['messageId', 'to'],
|
|
204
285
|
},
|
|
205
286
|
async execute(_id: string, params: any) {
|
|
206
287
|
try {
|
|
207
288
|
const token = await tp.getAccessToken();
|
|
208
|
-
const toRecipients = params.to.split(',').map((e: string) => ({ emailAddress: { address: e.trim() } }));
|
|
209
289
|
await graph(token, `/me/messages/${params.messageId}/forward`, {
|
|
210
290
|
method: 'POST',
|
|
211
|
-
body: { comment: params.comment || '', toRecipients },
|
|
291
|
+
body: { comment: params.comment || '', toRecipients: parseRecipients(params.to) },
|
|
212
292
|
});
|
|
213
293
|
return jsonResult({ forwarded: true, messageId: params.messageId, to: params.to });
|
|
214
294
|
} catch (e: any) { return errorResult(e.message); }
|
|
@@ -223,14 +303,13 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
223
303
|
type: 'object' as const,
|
|
224
304
|
properties: {
|
|
225
305
|
messageId: { type: 'string', description: 'Message ID to move' },
|
|
226
|
-
folder: { type: 'string', description: 'Destination
|
|
306
|
+
folder: { type: 'string', description: 'Destination: inbox, archive, deleteditems, junkemail, sentitems, drafts, or folder ID' },
|
|
227
307
|
},
|
|
228
308
|
required: ['messageId', 'folder'],
|
|
229
309
|
},
|
|
230
310
|
async execute(_id: string, params: any) {
|
|
231
311
|
try {
|
|
232
312
|
const token = await tp.getAccessToken();
|
|
233
|
-
// Resolve well-known folder names
|
|
234
313
|
const folderMap: Record<string, string> = {
|
|
235
314
|
inbox: 'inbox', archive: 'archive', trash: 'deleteditems',
|
|
236
315
|
deleteditems: 'deleteditems', junk: 'junkemail', junkemail: 'junkemail',
|
|
@@ -238,8 +317,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
238
317
|
};
|
|
239
318
|
const destId = folderMap[params.folder.toLowerCase()] || params.folder;
|
|
240
319
|
const result = await graph(token, `/me/messages/${params.messageId}/move`, {
|
|
241
|
-
method: 'POST',
|
|
242
|
-
body: { destinationId: destId },
|
|
320
|
+
method: 'POST', body: { destinationId: destId },
|
|
243
321
|
});
|
|
244
322
|
return jsonResult({ moved: true, newId: result.id, folder: params.folder });
|
|
245
323
|
} catch (e: any) { return errorResult(e.message); }
|
|
@@ -268,7 +346,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
268
346
|
|
|
269
347
|
{
|
|
270
348
|
name: 'outlook_mail_update',
|
|
271
|
-
description: 'Update message properties:
|
|
349
|
+
description: 'Update message properties: read/unread, flag, importance, categories.',
|
|
272
350
|
category: 'utility' as const,
|
|
273
351
|
parameters: {
|
|
274
352
|
type: 'object' as const,
|
|
@@ -277,7 +355,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
277
355
|
isRead: { type: 'boolean', description: 'Mark as read or unread' },
|
|
278
356
|
importance: { type: 'string', description: 'low, normal, or high' },
|
|
279
357
|
flag: { type: 'string', description: 'notFlagged, flagged, or complete' },
|
|
280
|
-
categories: { type: 'array', items: { type: 'string' }, description: 'Category labels to
|
|
358
|
+
categories: { type: 'array', items: { type: 'string' }, description: 'Category labels to set (replaces existing)' },
|
|
281
359
|
},
|
|
282
360
|
required: ['messageId'],
|
|
283
361
|
},
|
|
@@ -297,38 +375,30 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
297
375
|
|
|
298
376
|
{
|
|
299
377
|
name: 'outlook_mail_search',
|
|
300
|
-
description: 'Search emails across all folders
|
|
378
|
+
description: 'Search emails across all folders. Supports natural language and KQL syntax.',
|
|
301
379
|
category: 'utility' as const,
|
|
302
380
|
parameters: {
|
|
303
381
|
type: 'object' as const,
|
|
304
382
|
properties: {
|
|
305
|
-
query: { type: 'string', description: 'Search query (natural language or KQL: "from:user@example.com subject:report")' },
|
|
306
|
-
maxResults: { type: 'number', description: 'Max results (default:
|
|
383
|
+
query: { type: 'string', description: 'Search query (natural language or KQL: "from:user@example.com subject:report has:attachment")' },
|
|
384
|
+
maxResults: { type: 'number', description: 'Max results (default: 15, max: 25)' },
|
|
385
|
+
folder: { type: 'string', description: 'Limit search to specific folder (default: all folders)' },
|
|
307
386
|
},
|
|
308
387
|
required: ['query'],
|
|
309
388
|
},
|
|
310
389
|
async execute(_id: string, params: any) {
|
|
311
390
|
try {
|
|
312
391
|
const token = await tp.getAccessToken();
|
|
313
|
-
const top = Math.min(params.maxResults ||
|
|
314
|
-
|
|
315
|
-
const data = await graph(token,
|
|
392
|
+
const top = Math.min(params.maxResults || 15, 25);
|
|
393
|
+
const basePath = params.folder ? `/me/mailFolders/${params.folder}/messages` : '/me/messages';
|
|
394
|
+
const data = await graph(token, basePath, {
|
|
316
395
|
query: {
|
|
317
396
|
'$search': `"${params.query}"`,
|
|
318
397
|
'$top': String(top),
|
|
319
|
-
'$select':
|
|
398
|
+
'$select': LIST_SELECT,
|
|
320
399
|
}
|
|
321
400
|
});
|
|
322
|
-
const messages = (data.value || []).map((m: any) => (
|
|
323
|
-
id: m.id,
|
|
324
|
-
subject: m.subject,
|
|
325
|
-
from: m.from?.emailAddress?.address,
|
|
326
|
-
fromName: m.from?.emailAddress?.name,
|
|
327
|
-
date: m.receivedDateTime,
|
|
328
|
-
preview: m.bodyPreview,
|
|
329
|
-
isRead: m.isRead,
|
|
330
|
-
hasAttachments: m.hasAttachments,
|
|
331
|
-
}));
|
|
401
|
+
const messages = (data.value || []).map((m: any) => mapMessage(m));
|
|
332
402
|
return jsonResult({ messages, count: messages.length, query: params.query });
|
|
333
403
|
} catch (e: any) { return errorResult(e.message); }
|
|
334
404
|
},
|
|
@@ -336,7 +406,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
336
406
|
|
|
337
407
|
{
|
|
338
408
|
name: 'outlook_mail_draft',
|
|
339
|
-
description: 'Create a draft email
|
|
409
|
+
description: 'Create a draft email. Can be edited and sent later with outlook_mail_send_draft.',
|
|
340
410
|
category: 'utility' as const,
|
|
341
411
|
parameters: {
|
|
342
412
|
type: 'object' as const,
|
|
@@ -346,6 +416,7 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
346
416
|
body: { type: 'string', description: 'Email body' },
|
|
347
417
|
cc: { type: 'string', description: 'CC recipients' },
|
|
348
418
|
isHtml: { type: 'boolean', description: 'Whether body is HTML' },
|
|
419
|
+
importance: { type: 'string', description: 'low, normal, or high' },
|
|
349
420
|
},
|
|
350
421
|
required: ['to', 'subject', 'body'],
|
|
351
422
|
},
|
|
@@ -355,9 +426,10 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
355
426
|
const message: any = {
|
|
356
427
|
subject: params.subject,
|
|
357
428
|
body: { contentType: params.isHtml ? 'HTML' : 'Text', content: params.body },
|
|
358
|
-
toRecipients: params.to
|
|
429
|
+
toRecipients: parseRecipients(params.to),
|
|
359
430
|
};
|
|
360
|
-
if (params.cc) message.ccRecipients = params.cc
|
|
431
|
+
if (params.cc) message.ccRecipients = parseRecipients(params.cc);
|
|
432
|
+
if (params.importance) message.importance = params.importance;
|
|
361
433
|
const draft = await graph(token, '/me/messages', { method: 'POST', body: message });
|
|
362
434
|
return jsonResult({ draftId: draft.id, subject: params.subject, status: 'draft_created' });
|
|
363
435
|
} catch (e: any) { return errorResult(e.message); }
|
|
@@ -386,27 +458,67 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
386
458
|
|
|
387
459
|
{
|
|
388
460
|
name: 'outlook_mail_folders',
|
|
389
|
-
description: 'List mail folders
|
|
461
|
+
description: 'List all mail folders including nested child folders.',
|
|
390
462
|
category: 'utility' as const,
|
|
391
|
-
parameters: {
|
|
392
|
-
|
|
463
|
+
parameters: {
|
|
464
|
+
type: 'object' as const,
|
|
465
|
+
properties: {
|
|
466
|
+
parentFolderId: { type: 'string', description: 'Parent folder ID to list children (omit for top-level)' },
|
|
467
|
+
includeHidden: { type: 'boolean', description: 'Include hidden folders (default: false)' },
|
|
468
|
+
},
|
|
469
|
+
required: [],
|
|
470
|
+
},
|
|
471
|
+
async execute(_id: string, params: any) {
|
|
393
472
|
try {
|
|
394
473
|
const token = await tp.getAccessToken();
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
474
|
+
const path = params.parentFolderId
|
|
475
|
+
? `/me/mailFolders/${params.parentFolderId}/childFolders`
|
|
476
|
+
: '/me/mailFolders';
|
|
477
|
+
const query: Record<string, string> = {
|
|
478
|
+
'$top': '100',
|
|
479
|
+
'$select': 'id,displayName,totalItemCount,unreadItemCount,parentFolderId,isHidden,childFolderCount',
|
|
480
|
+
};
|
|
481
|
+
if (!params.includeHidden) query['$filter'] = 'isHidden eq false';
|
|
482
|
+
const data = await graph(token, path, { query });
|
|
398
483
|
const folders = (data.value || []).map((f: any) => ({
|
|
399
484
|
id: f.id, name: f.displayName,
|
|
400
485
|
totalItems: f.totalItemCount, unreadItems: f.unreadItemCount,
|
|
486
|
+
childFolders: f.childFolderCount, isHidden: f.isHidden,
|
|
401
487
|
}));
|
|
402
488
|
return jsonResult({ folders, count: folders.length });
|
|
403
489
|
} catch (e: any) { return errorResult(e.message); }
|
|
404
490
|
},
|
|
405
491
|
},
|
|
406
492
|
|
|
493
|
+
{
|
|
494
|
+
name: 'outlook_mail_create_folder',
|
|
495
|
+
description: 'Create a new mail folder.',
|
|
496
|
+
category: 'utility' as const,
|
|
497
|
+
parameters: {
|
|
498
|
+
type: 'object' as const,
|
|
499
|
+
properties: {
|
|
500
|
+
name: { type: 'string', description: 'Folder name' },
|
|
501
|
+
parentFolderId: { type: 'string', description: 'Parent folder ID (omit for top-level)' },
|
|
502
|
+
},
|
|
503
|
+
required: ['name'],
|
|
504
|
+
},
|
|
505
|
+
async execute(_id: string, params: any) {
|
|
506
|
+
try {
|
|
507
|
+
const token = await tp.getAccessToken();
|
|
508
|
+
const path = params.parentFolderId
|
|
509
|
+
? `/me/mailFolders/${params.parentFolderId}/childFolders`
|
|
510
|
+
: '/me/mailFolders';
|
|
511
|
+
const folder = await graph(token, path, {
|
|
512
|
+
method: 'POST', body: { displayName: params.name },
|
|
513
|
+
});
|
|
514
|
+
return jsonResult({ id: folder.id, name: folder.displayName });
|
|
515
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
|
|
407
519
|
{
|
|
408
520
|
name: 'outlook_mail_attachment_download',
|
|
409
|
-
description: 'Download an attachment from an email. Returns
|
|
521
|
+
description: 'Download an attachment from an email. Returns content as base64.',
|
|
410
522
|
category: 'utility' as const,
|
|
411
523
|
parameters: {
|
|
412
524
|
type: 'object' as const,
|
|
@@ -422,7 +534,187 @@ export function createOutlookMailTools(config: MicrosoftToolsConfig, _options?:
|
|
|
422
534
|
const att = await graph(token, `/me/messages/${params.messageId}/attachments/${params.attachmentId}`);
|
|
423
535
|
return jsonResult({
|
|
424
536
|
name: att.name, contentType: att.contentType, size: att.size,
|
|
425
|
-
content: att.contentBytes,
|
|
537
|
+
content: att.contentBytes,
|
|
538
|
+
});
|
|
539
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
{
|
|
544
|
+
name: 'outlook_mail_auto_reply',
|
|
545
|
+
description: 'Configure automatic replies (out-of-office / vacation responder).',
|
|
546
|
+
category: 'utility' as const,
|
|
547
|
+
parameters: {
|
|
548
|
+
type: 'object' as const,
|
|
549
|
+
properties: {
|
|
550
|
+
status: { type: 'string', description: 'disabled, alwaysEnabled, or scheduled' },
|
|
551
|
+
internalMessage: { type: 'string', description: 'Auto-reply message for internal senders (HTML)' },
|
|
552
|
+
externalMessage: { type: 'string', description: 'Auto-reply message for external senders (HTML)' },
|
|
553
|
+
externalAudience: { type: 'string', description: 'none, contactsOnly, or all (default: all)' },
|
|
554
|
+
startDate: { type: 'string', description: 'Start date (ISO 8601, required if scheduled)' },
|
|
555
|
+
endDate: { type: 'string', description: 'End date (ISO 8601, required if scheduled)' },
|
|
556
|
+
},
|
|
557
|
+
required: ['status'],
|
|
558
|
+
},
|
|
559
|
+
async execute(_id: string, params: any) {
|
|
560
|
+
try {
|
|
561
|
+
const token = await tp.getAccessToken();
|
|
562
|
+
if (params.status === 'disabled') {
|
|
563
|
+
await graph(token, '/me/mailboxSettings', {
|
|
564
|
+
method: 'PATCH',
|
|
565
|
+
body: { automaticRepliesSetting: { status: 'disabled' } },
|
|
566
|
+
});
|
|
567
|
+
return jsonResult({ autoReply: 'disabled' });
|
|
568
|
+
}
|
|
569
|
+
const setting: any = { status: params.status };
|
|
570
|
+
if (params.internalMessage) setting.internalReplyMessage = params.internalMessage;
|
|
571
|
+
if (params.externalMessage) setting.externalReplyMessage = params.externalMessage;
|
|
572
|
+
if (params.externalAudience) setting.externalAudience = params.externalAudience;
|
|
573
|
+
if (params.status === 'scheduled') {
|
|
574
|
+
setting.scheduledStartDateTime = { dateTime: params.startDate, timeZone: 'UTC' };
|
|
575
|
+
setting.scheduledEndDateTime = { dateTime: params.endDate, timeZone: 'UTC' };
|
|
576
|
+
}
|
|
577
|
+
await graph(token, '/me/mailboxSettings', {
|
|
578
|
+
method: 'PATCH',
|
|
579
|
+
body: { automaticRepliesSetting: setting },
|
|
580
|
+
});
|
|
581
|
+
return jsonResult({ autoReply: params.status, configured: true });
|
|
582
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
583
|
+
},
|
|
584
|
+
},
|
|
585
|
+
|
|
586
|
+
{
|
|
587
|
+
name: 'outlook_mail_get_auto_reply',
|
|
588
|
+
description: 'Get current automatic reply (out-of-office) settings.',
|
|
589
|
+
category: 'utility' as const,
|
|
590
|
+
parameters: { type: 'object' as const, properties: {}, required: [] },
|
|
591
|
+
async execute(_id: string) {
|
|
592
|
+
try {
|
|
593
|
+
const token = await tp.getAccessToken();
|
|
594
|
+
const settings = await graph(token, '/me/mailboxSettings/automaticRepliesSetting');
|
|
595
|
+
return jsonResult({
|
|
596
|
+
status: settings.status,
|
|
597
|
+
internalMessage: settings.internalReplyMessage,
|
|
598
|
+
externalMessage: settings.externalReplyMessage,
|
|
599
|
+
externalAudience: settings.externalAudience,
|
|
600
|
+
startDate: settings.scheduledStartDateTime?.dateTime,
|
|
601
|
+
endDate: settings.scheduledEndDateTime?.dateTime,
|
|
602
|
+
});
|
|
603
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
|
|
607
|
+
{
|
|
608
|
+
name: 'outlook_mail_rules',
|
|
609
|
+
description: 'List, create, or delete inbox rules (message rules). Rules auto-process incoming mail.',
|
|
610
|
+
category: 'utility' as const,
|
|
611
|
+
parameters: {
|
|
612
|
+
type: 'object' as const,
|
|
613
|
+
properties: {
|
|
614
|
+
action: { type: 'string', description: 'list, create, or delete' },
|
|
615
|
+
ruleId: { type: 'string', description: 'Rule ID (for delete)' },
|
|
616
|
+
displayName: { type: 'string', description: 'Rule name (for create)' },
|
|
617
|
+
conditions: { type: 'object', description: 'Match conditions object — e.g., {fromAddresses:[{emailAddress:{address:"user@example.com"}}], subjectContains:["invoice"]}' },
|
|
618
|
+
actions: { type: 'object', description: 'Actions when matched — e.g., {moveToFolder:"archive", markAsRead:true, stopProcessingRules:true}' },
|
|
619
|
+
isEnabled: { type: 'boolean', description: 'Enable/disable rule (default: true)' },
|
|
620
|
+
},
|
|
621
|
+
required: ['action'],
|
|
622
|
+
},
|
|
623
|
+
async execute(_id: string, params: any) {
|
|
624
|
+
try {
|
|
625
|
+
const token = await tp.getAccessToken();
|
|
626
|
+
if (params.action === 'list') {
|
|
627
|
+
const data = await graph(token, '/me/mailFolders/inbox/messageRules');
|
|
628
|
+
const rules = (data.value || []).map((r: any) => ({
|
|
629
|
+
id: r.id, name: r.displayName, isEnabled: r.isEnabled,
|
|
630
|
+
sequence: r.sequence, conditions: r.conditions, actions: r.actions,
|
|
631
|
+
}));
|
|
632
|
+
return jsonResult({ rules, count: rules.length });
|
|
633
|
+
}
|
|
634
|
+
if (params.action === 'delete') {
|
|
635
|
+
await graph(token, `/me/mailFolders/inbox/messageRules/${params.ruleId}`, { method: 'DELETE' });
|
|
636
|
+
return jsonResult({ deleted: true, ruleId: params.ruleId });
|
|
637
|
+
}
|
|
638
|
+
if (params.action === 'create') {
|
|
639
|
+
const rule = await graph(token, '/me/mailFolders/inbox/messageRules', {
|
|
640
|
+
method: 'POST',
|
|
641
|
+
body: {
|
|
642
|
+
displayName: params.displayName || 'Agent Rule',
|
|
643
|
+
isEnabled: params.isEnabled !== false,
|
|
644
|
+
conditions: params.conditions || {},
|
|
645
|
+
actions: params.actions || {},
|
|
646
|
+
},
|
|
647
|
+
});
|
|
648
|
+
return jsonResult({ id: rule.id, name: rule.displayName, created: true });
|
|
649
|
+
}
|
|
650
|
+
throw new Error('action must be list, create, or delete');
|
|
651
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
|
|
655
|
+
{
|
|
656
|
+
name: 'outlook_mail_categories',
|
|
657
|
+
description: 'Manage Outlook categories (color-coded labels). List, create, or delete.',
|
|
658
|
+
category: 'utility' as const,
|
|
659
|
+
parameters: {
|
|
660
|
+
type: 'object' as const,
|
|
661
|
+
properties: {
|
|
662
|
+
action: { type: 'string', description: 'list, create, or delete' },
|
|
663
|
+
name: { type: 'string', description: 'Category name (for create)' },
|
|
664
|
+
color: { type: 'string', description: 'Color preset: None, Red, Orange, Brown, Yellow, Green, Teal, Olive, Blue, Purple, Cranberry, Steel, DarkSteel, Gray, DarkGray, Black (for create)' },
|
|
665
|
+
categoryId: { type: 'string', description: 'Category ID (for delete)' },
|
|
666
|
+
},
|
|
667
|
+
required: ['action'],
|
|
668
|
+
},
|
|
669
|
+
async execute(_id: string, params: any) {
|
|
670
|
+
try {
|
|
671
|
+
const token = await tp.getAccessToken();
|
|
672
|
+
if (params.action === 'list') {
|
|
673
|
+
const data = await graph(token, '/me/outlook/masterCategories');
|
|
674
|
+
const cats = (data.value || []).map((c: any) => ({
|
|
675
|
+
id: c.id, name: c.displayName, color: c.color,
|
|
676
|
+
}));
|
|
677
|
+
return jsonResult({ categories: cats, count: cats.length });
|
|
678
|
+
}
|
|
679
|
+
if (params.action === 'create') {
|
|
680
|
+
const cat = await graph(token, '/me/outlook/masterCategories', {
|
|
681
|
+
method: 'POST',
|
|
682
|
+
body: { displayName: params.name, color: params.color || 'None' },
|
|
683
|
+
});
|
|
684
|
+
return jsonResult({ id: cat.id, name: cat.displayName, color: cat.color });
|
|
685
|
+
}
|
|
686
|
+
if (params.action === 'delete') {
|
|
687
|
+
await graph(token, `/me/outlook/masterCategories/${params.categoryId}`, { method: 'DELETE' });
|
|
688
|
+
return jsonResult({ deleted: true });
|
|
689
|
+
}
|
|
690
|
+
throw new Error('action must be list, create, or delete');
|
|
691
|
+
} catch (e: any) { return errorResult(e.message); }
|
|
692
|
+
},
|
|
693
|
+
},
|
|
694
|
+
|
|
695
|
+
{
|
|
696
|
+
name: 'outlook_mail_profile',
|
|
697
|
+
description: 'Get the mailbox user profile — email address, display name, timezone, language, and mailbox settings.',
|
|
698
|
+
category: 'utility' as const,
|
|
699
|
+
parameters: { type: 'object' as const, properties: {}, required: [] },
|
|
700
|
+
async execute(_id: string) {
|
|
701
|
+
try {
|
|
702
|
+
const token = await tp.getAccessToken();
|
|
703
|
+
const [user, settings] = await Promise.all([
|
|
704
|
+
graph(token, '/me', { query: { '$select': 'displayName,mail,userPrincipalName,jobTitle,department,officeLocation' } }),
|
|
705
|
+
graph(token, '/me/mailboxSettings'),
|
|
706
|
+
]);
|
|
707
|
+
return jsonResult({
|
|
708
|
+
email: user.mail || user.userPrincipalName,
|
|
709
|
+
name: user.displayName,
|
|
710
|
+
jobTitle: user.jobTitle,
|
|
711
|
+
department: user.department,
|
|
712
|
+
office: user.officeLocation,
|
|
713
|
+
timeZone: settings.timeZone,
|
|
714
|
+
language: settings.language?.locale,
|
|
715
|
+
dateFormat: settings.dateFormat,
|
|
716
|
+
timeFormat: settings.timeFormat,
|
|
717
|
+
delegateMeetingRequests: settings.delegateMeetingMessageDeliveryOptions,
|
|
426
718
|
});
|
|
427
719
|
} catch (e: any) { return errorResult(e.message); }
|
|
428
720
|
},
|