@diskd-ai/email-mcp 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/LICENSE +155 -0
  2. package/README.md +820 -0
  3. package/dist/cli/account-commands.d.ts +10 -0
  4. package/dist/cli/account-commands.d.ts.map +1 -0
  5. package/dist/cli/account-commands.js +703 -0
  6. package/dist/cli/account-commands.js.map +1 -0
  7. package/dist/cli/config-commands.d.ts +9 -0
  8. package/dist/cli/config-commands.d.ts.map +1 -0
  9. package/dist/cli/config-commands.js +156 -0
  10. package/dist/cli/config-commands.js.map +1 -0
  11. package/dist/cli/guard.d.ts +11 -0
  12. package/dist/cli/guard.d.ts.map +1 -0
  13. package/dist/cli/guard.js +18 -0
  14. package/dist/cli/guard.js.map +1 -0
  15. package/dist/cli/install-commands.d.ts +12 -0
  16. package/dist/cli/install-commands.d.ts.map +1 -0
  17. package/dist/cli/install-commands.js +320 -0
  18. package/dist/cli/install-commands.js.map +1 -0
  19. package/dist/cli/notify.d.ts +8 -0
  20. package/dist/cli/notify.d.ts.map +1 -0
  21. package/dist/cli/notify.js +143 -0
  22. package/dist/cli/notify.js.map +1 -0
  23. package/dist/cli/providers.d.ts +13 -0
  24. package/dist/cli/providers.d.ts.map +1 -0
  25. package/dist/cli/providers.js +180 -0
  26. package/dist/cli/providers.js.map +1 -0
  27. package/dist/cli/scheduler.d.ts +8 -0
  28. package/dist/cli/scheduler.d.ts.map +1 -0
  29. package/dist/cli/scheduler.js +268 -0
  30. package/dist/cli/scheduler.js.map +1 -0
  31. package/dist/cli/setup.d.ts +12 -0
  32. package/dist/cli/setup.d.ts.map +1 -0
  33. package/dist/cli/setup.js +15 -0
  34. package/dist/cli/setup.js.map +1 -0
  35. package/dist/cli/test.d.ts +7 -0
  36. package/dist/cli/test.d.ts.map +1 -0
  37. package/dist/cli/test.js +67 -0
  38. package/dist/cli/test.js.map +1 -0
  39. package/dist/config/loader.d.ts +34 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +339 -0
  42. package/dist/config/loader.js.map +1 -0
  43. package/dist/config/schema.d.ts +351 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +165 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/config/xdg.d.ts +27 -0
  48. package/dist/config/xdg.d.ts.map +1 -0
  49. package/dist/config/xdg.js +30 -0
  50. package/dist/config/xdg.js.map +1 -0
  51. package/dist/connections/manager.d.ts +42 -0
  52. package/dist/connections/manager.d.ts.map +1 -0
  53. package/dist/connections/manager.js +266 -0
  54. package/dist/connections/manager.js.map +1 -0
  55. package/dist/connections/types.d.ts +13 -0
  56. package/dist/connections/types.d.ts.map +1 -0
  57. package/dist/connections/types.js +2 -0
  58. package/dist/connections/types.js.map +1 -0
  59. package/dist/logging.d.ts +46 -0
  60. package/dist/logging.d.ts.map +1 -0
  61. package/dist/logging.js +63 -0
  62. package/dist/logging.js.map +1 -0
  63. package/dist/main.d.ts +13 -0
  64. package/dist/main.d.ts.map +1 -0
  65. package/dist/main.js +206 -0
  66. package/dist/main.js.map +1 -0
  67. package/dist/prompts/actions.prompt.d.ts +9 -0
  68. package/dist/prompts/actions.prompt.d.ts.map +1 -0
  69. package/dist/prompts/actions.prompt.js +64 -0
  70. package/dist/prompts/actions.prompt.js.map +1 -0
  71. package/dist/prompts/calendar.prompt.d.ts +9 -0
  72. package/dist/prompts/calendar.prompt.d.ts.map +1 -0
  73. package/dist/prompts/calendar.prompt.js +55 -0
  74. package/dist/prompts/calendar.prompt.js.map +1 -0
  75. package/dist/prompts/cleanup.prompt.d.ts +9 -0
  76. package/dist/prompts/cleanup.prompt.d.ts.map +1 -0
  77. package/dist/prompts/cleanup.prompt.js +78 -0
  78. package/dist/prompts/cleanup.prompt.js.map +1 -0
  79. package/dist/prompts/compose.prompt.d.ts +8 -0
  80. package/dist/prompts/compose.prompt.d.ts.map +1 -0
  81. package/dist/prompts/compose.prompt.js +116 -0
  82. package/dist/prompts/compose.prompt.js.map +1 -0
  83. package/dist/prompts/register.d.ts +8 -0
  84. package/dist/prompts/register.d.ts.map +1 -0
  85. package/dist/prompts/register.js +20 -0
  86. package/dist/prompts/register.js.map +1 -0
  87. package/dist/prompts/thread.prompt.d.ts +9 -0
  88. package/dist/prompts/thread.prompt.d.ts.map +1 -0
  89. package/dist/prompts/thread.prompt.js +58 -0
  90. package/dist/prompts/thread.prompt.js.map +1 -0
  91. package/dist/prompts/triage.prompt.d.ts +9 -0
  92. package/dist/prompts/triage.prompt.d.ts.map +1 -0
  93. package/dist/prompts/triage.prompt.js +64 -0
  94. package/dist/prompts/triage.prompt.js.map +1 -0
  95. package/dist/resources/accounts.resource.d.ts +9 -0
  96. package/dist/resources/accounts.resource.d.ts.map +1 -0
  97. package/dist/resources/accounts.resource.js +26 -0
  98. package/dist/resources/accounts.resource.js.map +1 -0
  99. package/dist/resources/mailboxes.resource.d.ts +10 -0
  100. package/dist/resources/mailboxes.resource.d.ts.map +1 -0
  101. package/dist/resources/mailboxes.resource.js +33 -0
  102. package/dist/resources/mailboxes.resource.js.map +1 -0
  103. package/dist/resources/register.d.ts +12 -0
  104. package/dist/resources/register.d.ts.map +1 -0
  105. package/dist/resources/register.js +20 -0
  106. package/dist/resources/register.js.map +1 -0
  107. package/dist/resources/scheduled.resource.d.ts +9 -0
  108. package/dist/resources/scheduled.resource.d.ts.map +1 -0
  109. package/dist/resources/scheduled.resource.js +31 -0
  110. package/dist/resources/scheduled.resource.js.map +1 -0
  111. package/dist/resources/stats.resource.d.ts +10 -0
  112. package/dist/resources/stats.resource.d.ts.map +1 -0
  113. package/dist/resources/stats.resource.js +45 -0
  114. package/dist/resources/stats.resource.js.map +1 -0
  115. package/dist/resources/templates.resource.d.ts +9 -0
  116. package/dist/resources/templates.resource.d.ts.map +1 -0
  117. package/dist/resources/templates.resource.js +34 -0
  118. package/dist/resources/templates.resource.js.map +1 -0
  119. package/dist/resources/unread.resource.d.ts +11 -0
  120. package/dist/resources/unread.resource.d.ts.map +1 -0
  121. package/dist/resources/unread.resource.js +46 -0
  122. package/dist/resources/unread.resource.js.map +1 -0
  123. package/dist/safety/audit.d.ts +17 -0
  124. package/dist/safety/audit.d.ts.map +1 -0
  125. package/dist/safety/audit.js +50 -0
  126. package/dist/safety/audit.js.map +1 -0
  127. package/dist/safety/rate-limiter.d.ts +22 -0
  128. package/dist/safety/rate-limiter.d.ts.map +1 -0
  129. package/dist/safety/rate-limiter.js +52 -0
  130. package/dist/safety/rate-limiter.js.map +1 -0
  131. package/dist/safety/validation.d.ts +44 -0
  132. package/dist/safety/validation.d.ts.map +1 -0
  133. package/dist/safety/validation.js +113 -0
  134. package/dist/safety/validation.js.map +1 -0
  135. package/dist/server.d.ts +10 -0
  136. package/dist/server.d.ts.map +1 -0
  137. package/dist/server.js +25 -0
  138. package/dist/server.js.map +1 -0
  139. package/dist/services/calendar.service.d.ts +22 -0
  140. package/dist/services/calendar.service.d.ts.map +1 -0
  141. package/dist/services/calendar.service.js +115 -0
  142. package/dist/services/calendar.service.js.map +1 -0
  143. package/dist/services/event-bus.d.ts +28 -0
  144. package/dist/services/event-bus.d.ts.map +1 -0
  145. package/dist/services/event-bus.js +16 -0
  146. package/dist/services/event-bus.js.map +1 -0
  147. package/dist/services/hooks.service.d.ts +77 -0
  148. package/dist/services/hooks.service.d.ts.map +1 -0
  149. package/dist/services/hooks.service.js +498 -0
  150. package/dist/services/hooks.service.js.map +1 -0
  151. package/dist/services/imap.service.d.ts +133 -0
  152. package/dist/services/imap.service.d.ts.map +1 -0
  153. package/dist/services/imap.service.js +1393 -0
  154. package/dist/services/imap.service.js.map +1 -0
  155. package/dist/services/label-strategy.d.ts +20 -0
  156. package/dist/services/label-strategy.d.ts.map +1 -0
  157. package/dist/services/label-strategy.js +237 -0
  158. package/dist/services/label-strategy.js.map +1 -0
  159. package/dist/services/local-calendar.service.d.ts +126 -0
  160. package/dist/services/local-calendar.service.d.ts.map +1 -0
  161. package/dist/services/local-calendar.service.js +428 -0
  162. package/dist/services/local-calendar.service.js.map +1 -0
  163. package/dist/services/notifier.service.d.ts +69 -0
  164. package/dist/services/notifier.service.d.ts.map +1 -0
  165. package/dist/services/notifier.service.js +319 -0
  166. package/dist/services/notifier.service.js.map +1 -0
  167. package/dist/services/oauth.service.d.ts +47 -0
  168. package/dist/services/oauth.service.d.ts.map +1 -0
  169. package/dist/services/oauth.service.js +140 -0
  170. package/dist/services/oauth.service.js.map +1 -0
  171. package/dist/services/presets.d.ts +36 -0
  172. package/dist/services/presets.d.ts.map +1 -0
  173. package/dist/services/presets.js +173 -0
  174. package/dist/services/presets.js.map +1 -0
  175. package/dist/services/reminders.service.d.ts +63 -0
  176. package/dist/services/reminders.service.d.ts.map +1 -0
  177. package/dist/services/reminders.service.js +281 -0
  178. package/dist/services/reminders.service.js.map +1 -0
  179. package/dist/services/scheduler.service.d.ts +42 -0
  180. package/dist/services/scheduler.service.d.ts.map +1 -0
  181. package/dist/services/scheduler.service.js +260 -0
  182. package/dist/services/scheduler.service.js.map +1 -0
  183. package/dist/services/smtp.service.d.ts +40 -0
  184. package/dist/services/smtp.service.d.ts.map +1 -0
  185. package/dist/services/smtp.service.js +151 -0
  186. package/dist/services/smtp.service.js.map +1 -0
  187. package/dist/services/template.service.d.ts +33 -0
  188. package/dist/services/template.service.d.ts.map +1 -0
  189. package/dist/services/template.service.js +123 -0
  190. package/dist/services/template.service.js.map +1 -0
  191. package/dist/services/watcher.service.d.ts +36 -0
  192. package/dist/services/watcher.service.d.ts.map +1 -0
  193. package/dist/services/watcher.service.js +241 -0
  194. package/dist/services/watcher.service.js.map +1 -0
  195. package/dist/tools/accounts.tool.d.ts +7 -0
  196. package/dist/tools/accounts.tool.d.ts.map +1 -0
  197. package/dist/tools/accounts.tool.js +29 -0
  198. package/dist/tools/accounts.tool.js.map +1 -0
  199. package/dist/tools/analytics.tool.d.ts +9 -0
  200. package/dist/tools/analytics.tool.d.ts.map +1 -0
  201. package/dist/tools/analytics.tool.js +27 -0
  202. package/dist/tools/analytics.tool.js.map +1 -0
  203. package/dist/tools/attachments.tool.d.ts +7 -0
  204. package/dist/tools/attachments.tool.d.ts.map +1 -0
  205. package/dist/tools/attachments.tool.js +45 -0
  206. package/dist/tools/attachments.tool.js.map +1 -0
  207. package/dist/tools/bulk.tool.d.ts +7 -0
  208. package/dist/tools/bulk.tool.d.ts.map +1 -0
  209. package/dist/tools/bulk.tool.js +75 -0
  210. package/dist/tools/bulk.tool.js.map +1 -0
  211. package/dist/tools/calendar.tool.d.ts +19 -0
  212. package/dist/tools/calendar.tool.d.ts.map +1 -0
  213. package/dist/tools/calendar.tool.js +538 -0
  214. package/dist/tools/calendar.tool.js.map +1 -0
  215. package/dist/tools/contacts.tool.d.ts +7 -0
  216. package/dist/tools/contacts.tool.d.ts.map +1 -0
  217. package/dist/tools/contacts.tool.js +44 -0
  218. package/dist/tools/contacts.tool.js.map +1 -0
  219. package/dist/tools/drafts.tool.d.ts +8 -0
  220. package/dist/tools/drafts.tool.d.ts.map +1 -0
  221. package/dist/tools/drafts.tool.js +92 -0
  222. package/dist/tools/drafts.tool.js.map +1 -0
  223. package/dist/tools/emails.tool.d.ts +7 -0
  224. package/dist/tools/emails.tool.d.ts.map +1 -0
  225. package/dist/tools/emails.tool.js +400 -0
  226. package/dist/tools/emails.tool.js.map +1 -0
  227. package/dist/tools/folders.tool.d.ts +7 -0
  228. package/dist/tools/folders.tool.d.ts.map +1 -0
  229. package/dist/tools/folders.tool.js +111 -0
  230. package/dist/tools/folders.tool.js.map +1 -0
  231. package/dist/tools/health.tool.d.ts +10 -0
  232. package/dist/tools/health.tool.d.ts.map +1 -0
  233. package/dist/tools/health.tool.js +78 -0
  234. package/dist/tools/health.tool.js.map +1 -0
  235. package/dist/tools/label.tool.d.ts +11 -0
  236. package/dist/tools/label.tool.d.ts.map +1 -0
  237. package/dist/tools/label.tool.js +165 -0
  238. package/dist/tools/label.tool.js.map +1 -0
  239. package/dist/tools/locate.tool.d.ts +11 -0
  240. package/dist/tools/locate.tool.d.ts.map +1 -0
  241. package/dist/tools/locate.tool.js +59 -0
  242. package/dist/tools/locate.tool.js.map +1 -0
  243. package/dist/tools/mailboxes.tool.d.ts +7 -0
  244. package/dist/tools/mailboxes.tool.d.ts.map +1 -0
  245. package/dist/tools/mailboxes.tool.js +38 -0
  246. package/dist/tools/mailboxes.tool.js.map +1 -0
  247. package/dist/tools/manage.tool.d.ts +7 -0
  248. package/dist/tools/manage.tool.d.ts.map +1 -0
  249. package/dist/tools/manage.tool.js +125 -0
  250. package/dist/tools/manage.tool.js.map +1 -0
  251. package/dist/tools/register.d.ts +20 -0
  252. package/dist/tools/register.d.ts.map +1 -0
  253. package/dist/tools/register.js +53 -0
  254. package/dist/tools/register.js.map +1 -0
  255. package/dist/tools/scheduler.tool.d.ts +9 -0
  256. package/dist/tools/scheduler.tool.d.ts.map +1 -0
  257. package/dist/tools/scheduler.tool.js +104 -0
  258. package/dist/tools/scheduler.tool.js.map +1 -0
  259. package/dist/tools/send.tool.d.ts +7 -0
  260. package/dist/tools/send.tool.d.ts.map +1 -0
  261. package/dist/tools/send.tool.js +123 -0
  262. package/dist/tools/send.tool.js.map +1 -0
  263. package/dist/tools/templates.tool.d.ts +12 -0
  264. package/dist/tools/templates.tool.d.ts.map +1 -0
  265. package/dist/tools/templates.tool.js +140 -0
  266. package/dist/tools/templates.tool.js.map +1 -0
  267. package/dist/tools/thread.tool.d.ts +10 -0
  268. package/dist/tools/thread.tool.d.ts.map +1 -0
  269. package/dist/tools/thread.tool.js +146 -0
  270. package/dist/tools/thread.tool.js.map +1 -0
  271. package/dist/tools/watcher.tool.d.ts +9 -0
  272. package/dist/tools/watcher.tool.d.ts.map +1 -0
  273. package/dist/tools/watcher.tool.js +282 -0
  274. package/dist/tools/watcher.tool.js.map +1 -0
  275. package/dist/types/index.d.ts +271 -0
  276. package/dist/types/index.d.ts.map +1 -0
  277. package/dist/types/index.js +5 -0
  278. package/dist/types/index.js.map +1 -0
  279. package/dist/utils/calendar-notes.d.ts +31 -0
  280. package/dist/utils/calendar-notes.d.ts.map +1 -0
  281. package/dist/utils/calendar-notes.js +99 -0
  282. package/dist/utils/calendar-notes.js.map +1 -0
  283. package/dist/utils/calendar-state.d.ts +27 -0
  284. package/dist/utils/calendar-state.d.ts.map +1 -0
  285. package/dist/utils/calendar-state.js +85 -0
  286. package/dist/utils/calendar-state.js.map +1 -0
  287. package/dist/utils/conference-details.d.ts +12 -0
  288. package/dist/utils/conference-details.d.ts.map +1 -0
  289. package/dist/utils/conference-details.js +71 -0
  290. package/dist/utils/conference-details.js.map +1 -0
  291. package/dist/utils/meeting-url.d.ts +10 -0
  292. package/dist/utils/meeting-url.d.ts.map +1 -0
  293. package/dist/utils/meeting-url.js +30 -0
  294. package/dist/utils/meeting-url.js.map +1 -0
  295. package/package.json +108 -0
@@ -0,0 +1,538 @@
1
+ /**
2
+ * MCP Tools: calendar operations
3
+ *
4
+ * - extract_calendar — parse ICS/iCalendar from email
5
+ * - add_to_calendar — add email event to local calendar (with confirmation dialog + dedup)
6
+ * - check_calendar_permissions — check OS calendar/reminders access
7
+ * - list_calendars — list available local calendars
8
+ * - list_events — search/list local calendar events
9
+ * - list_reminders — search/list reminders from Reminders.app
10
+ * - create_reminder — create a reminder in macOS Reminders.app from email
11
+ * - analyze_email_for_scheduling — detect events + reminders in email; AI decides what to create
12
+ */
13
+ import { join } from 'node:path';
14
+ import { z } from 'zod';
15
+ import { CALENDAR_ATTACHMENTS_DIR } from '../config/xdg.js';
16
+ import { buildCalendarNotes } from '../utils/calendar-notes.js';
17
+ import { extractConferenceDetails } from '../utils/conference-details.js';
18
+ import { extractMeetingUrl } from '../utils/meeting-url.js';
19
+ // Keywords that suggest an action item / reminder rather than a calendar event
20
+ const REMINDER_KEYWORDS = /\b(deadline|due by|respond by|reply by|action required|follow.?up|please review|please send|please confirm|submit by|complete by|return by|RSVP by|by (monday|tuesday|wednesday|thursday|friday|saturday|sunday)|by (jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec))\b/i;
21
+ export default function registerCalendarTools(server, imapService, calendarService, localCalendarService, remindersService) {
22
+ // ---------------------------------------------------------------------------
23
+ // extract_calendar
24
+ // ---------------------------------------------------------------------------
25
+ server.tool('extract_calendar', 'Extract calendar events (ICS/iCalendar) from an email. Returns structured event data including time, location, attendees, and status.', {
26
+ account: z.string().describe('Account name'),
27
+ email_id: z.string().describe('Email UID'),
28
+ mailbox: z.string().default('INBOX').describe('Mailbox path (default: INBOX)'),
29
+ }, { readOnlyHint: true, destructiveHint: false }, async ({ account, email_id: emailId, mailbox }) => {
30
+ const email = await imapService.getEmail(account, emailId, mailbox);
31
+ const icsContents = await imapService.getCalendarParts(account, mailbox, emailId);
32
+ if (icsContents.length === 0) {
33
+ return {
34
+ content: [
35
+ {
36
+ type: 'text',
37
+ text: JSON.stringify({
38
+ email_subject: email.subject,
39
+ events: [],
40
+ count: 0,
41
+ message: 'No calendar/ICS content found in this email',
42
+ }, null, 2),
43
+ },
44
+ ],
45
+ };
46
+ }
47
+ const events = calendarService.extractFromParts(icsContents);
48
+ return {
49
+ content: [
50
+ {
51
+ type: 'text',
52
+ text: JSON.stringify({ email_subject: email.subject, events, count: events.length }, null, 2),
53
+ },
54
+ ],
55
+ };
56
+ });
57
+ // ---------------------------------------------------------------------------
58
+ // add_to_calendar
59
+ // ---------------------------------------------------------------------------
60
+ server.tool('add_to_calendar', [
61
+ 'Add an email event to the local calendar (macOS Calendar.app / Linux via xdg-open).',
62
+ 'Automatically extracts event data from the email: ICS attachments, meeting URL (Zoom/Teams/Meet),',
63
+ 'conference dial-in / ID / passcode, attendees, and email body excerpt.',
64
+ 'All relevant email attachments (PDFs, docs, etc.) are saved locally and linked in the event notes.',
65
+ 'A native confirmation dialog is shown on macOS before the event is written.',
66
+ 'Returns one of: added | cancelled | timed_out | no_display.',
67
+ ].join(' '), {
68
+ account: z.string().describe('Account name'),
69
+ email_id: z.string().describe('Email UID'),
70
+ mailbox: z.string().default('INBOX').describe('Mailbox path (default: INBOX)'),
71
+ calendar_name: z
72
+ .string()
73
+ .optional()
74
+ .describe('Target calendar name (empty = default calendar)'),
75
+ alarm_minutes: z
76
+ .number()
77
+ .int()
78
+ .min(0)
79
+ .max(1440)
80
+ .default(15)
81
+ .describe('Minutes before event to show an alert (default: 15)'),
82
+ save_attachments: z
83
+ .boolean()
84
+ .default(true)
85
+ .describe('Save non-ICS email attachments locally and link them in the event notes'),
86
+ confirm: z
87
+ .boolean()
88
+ .default(true)
89
+ .describe('Show native confirmation dialog before adding (default: true)'),
90
+ }, { readOnlyHint: false, destructiveHint: false }, async ({ account, email_id: emailId, mailbox, calendar_name: calendarName, alarm_minutes: alarmMinutes, save_attachments: saveAttachments, confirm, }) => {
91
+ // 1. Fetch full email
92
+ const email = await imapService.getEmail(account, emailId, mailbox);
93
+ const bodyText = email.bodyText ?? '';
94
+ const bodyHtml = email.bodyHtml ?? '';
95
+ const combinedText = `${bodyText}\n${bodyHtml}`;
96
+ // 2. Try to get event data from ICS attachment
97
+ let eventStart = new Date(email.date);
98
+ let eventEnd = new Date(eventStart.getTime() + 60 * 60 * 1000);
99
+ let eventLocation;
100
+ let eventOrganizer;
101
+ let eventAttendees = [];
102
+ let icsUid;
103
+ const icsContents = await imapService.getCalendarParts(account, mailbox, emailId);
104
+ if (icsContents.length > 0) {
105
+ const events = calendarService.extractFromParts(icsContents);
106
+ if (events.length > 0) {
107
+ const ev = events[0];
108
+ eventStart = new Date(ev.start);
109
+ eventEnd = new Date(ev.end);
110
+ eventLocation = ev.location;
111
+ icsUid = ev.uid;
112
+ if (ev.organizer) {
113
+ eventOrganizer = ev.organizer.name
114
+ ? `${ev.organizer.name} <${ev.organizer.address}>`
115
+ : ev.organizer.address;
116
+ }
117
+ eventAttendees = ev.attendees.map((a) => {
118
+ if (a.name)
119
+ return `${a.name} <${a.address}>`;
120
+ return a.address;
121
+ });
122
+ }
123
+ }
124
+ // 3. Extract meeting URL and conference details
125
+ const meetingUrl = extractMeetingUrl(combinedText);
126
+ const conference = extractConferenceDetails(bodyText !== '' ? bodyText : bodyHtml);
127
+ // 4. Save attachments (before dialog so filenames are shown)
128
+ let savedAttachments = [];
129
+ if (saveAttachments && email.attachments.length > 0) {
130
+ const destDir = join(CALENDAR_ATTACHMENTS_DIR, `${account}-${emailId}`.replace(/[^a-zA-Z0-9-_]/g, '_'));
131
+ savedAttachments = await imapService.saveEmailAttachments(account, emailId, mailbox, destDir);
132
+ }
133
+ // 5. Build rich notes
134
+ const notes = buildCalendarNotes({
135
+ emailFrom: email.from.name
136
+ ? `${email.from.name} <${email.from.address}>`
137
+ : email.from.address,
138
+ emailSubject: email.subject,
139
+ emailDate: new Date(email.date).toLocaleString('en', {
140
+ weekday: 'short',
141
+ day: 'numeric',
142
+ month: 'short',
143
+ year: 'numeric',
144
+ hour: '2-digit',
145
+ minute: '2-digit',
146
+ }),
147
+ organizer: eventOrganizer,
148
+ attendees: eventAttendees,
149
+ meetingUrl: meetingUrl?.url,
150
+ meetingUrlLabel: meetingUrl?.label,
151
+ dialIn: conference?.dialIn,
152
+ meetingId: conference?.meetingId,
153
+ passcode: conference?.passcode,
154
+ conferenceProvider: conference?.provider,
155
+ bodyExcerpt: bodyText || bodyHtml,
156
+ savedAttachments,
157
+ });
158
+ // 6. Add to calendar (shows dialog if confirm=true, dedup check is automatic)
159
+ const result = await localCalendarService.addEvent({
160
+ title: email.subject,
161
+ start: eventStart,
162
+ end: eventEnd,
163
+ location: eventLocation,
164
+ notes,
165
+ url: meetingUrl?.url,
166
+ urlLabel: meetingUrl?.label,
167
+ alarmMinutes,
168
+ attendeeCount: eventAttendees.length,
169
+ savedAttachments,
170
+ dialIn: conference?.dialIn,
171
+ meetingId: conference?.meetingId,
172
+ passcode: conference?.passcode,
173
+ conferenceProvider: conference?.provider,
174
+ icsUid,
175
+ }, calendarName, { confirm });
176
+ // 7. Build response
177
+ const details = {
178
+ status: result.status,
179
+ message: result.message,
180
+ };
181
+ if (result.status === 'duplicate') {
182
+ details.duplicate = result.duplicate;
183
+ details.hint = 'Event already exists. Use skipDuplicateCheck or update the existing event.';
184
+ }
185
+ if (result.status === 'added') {
186
+ details.event = {
187
+ title: email.subject,
188
+ start: eventStart.toISOString(),
189
+ end: eventEnd.toISOString(),
190
+ location: eventLocation,
191
+ calendar: result.calendarName,
192
+ meetingUrl: meetingUrl?.url,
193
+ dialIn: conference?.dialIn,
194
+ meetingId: conference?.meetingId,
195
+ attachmentsSaved: savedAttachments.length,
196
+ attachments: savedAttachments.map((a) => ({
197
+ filename: a.filename,
198
+ size: a.size,
199
+ localPath: a.localPath,
200
+ })),
201
+ };
202
+ }
203
+ return {
204
+ content: [{ type: 'text', text: JSON.stringify(details, null, 2) }],
205
+ };
206
+ });
207
+ // ---------------------------------------------------------------------------
208
+ // check_calendar_permissions
209
+ // ---------------------------------------------------------------------------
210
+ server.tool('check_calendar_permissions', [
211
+ 'Check whether the local calendar is accessible.',
212
+ 'On macOS, verifies Calendar.app access (requires Privacy & Security → Calendars permission).',
213
+ 'Returns granted status and step-by-step setup instructions if access is denied.',
214
+ ].join(' '), {}, { readOnlyHint: true, destructiveHint: false }, async () => {
215
+ const [calResult, remResult] = await Promise.all([
216
+ localCalendarService.checkPermissions(),
217
+ remindersService.checkPermissions(),
218
+ ]);
219
+ const lines = [
220
+ '--- Calendar.app ---',
221
+ `Platform: ${calResult.platform}`,
222
+ `Access granted: ${calResult.granted ? '✅ Yes' : '❌ No'}`,
223
+ ];
224
+ if (!calResult.granted && calResult.instructions.length > 0) {
225
+ lines.push('', 'Setup instructions:');
226
+ calResult.instructions.forEach((line, i) => {
227
+ lines.push(` ${i === 0 ? '' : `${i}. `}${line}`);
228
+ });
229
+ }
230
+ lines.push('', '--- Reminders.app ---');
231
+ lines.push(`Access granted: ${remResult.granted ? '✅ Yes' : '❌ No'}`);
232
+ if (!remResult.granted && remResult.instructions.length > 0) {
233
+ lines.push('', 'Setup instructions:');
234
+ remResult.instructions.forEach((line, i) => {
235
+ lines.push(` ${i === 0 ? '' : `${i}. `}${line}`);
236
+ });
237
+ }
238
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
239
+ });
240
+ // ---------------------------------------------------------------------------
241
+ // list_calendars
242
+ // ---------------------------------------------------------------------------
243
+ server.tool('list_calendars', [
244
+ 'List all available local calendars (macOS Calendar.app / Linux default).',
245
+ 'Use the returned calendar names with add_to_calendar to target a specific calendar.',
246
+ ].join(' '), {}, { readOnlyHint: true, destructiveHint: false }, async () => {
247
+ const calendars = await localCalendarService.listCalendars();
248
+ if (calendars.length === 0) {
249
+ return {
250
+ content: [
251
+ {
252
+ type: 'text',
253
+ text: 'No calendars found. Run check_calendar_permissions to verify access.',
254
+ },
255
+ ],
256
+ };
257
+ }
258
+ const lines = [`Found ${calendars.length} calendar(s):`, ''];
259
+ calendars.forEach((c, i) => {
260
+ lines.push(` ${i + 1}. ${c.name} (id: ${c.id})`);
261
+ });
262
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
263
+ });
264
+ // ---------------------------------------------------------------------------
265
+ // list_events
266
+ // ---------------------------------------------------------------------------
267
+ server.tool('list_events', [
268
+ 'List local calendar events with optional filters.',
269
+ 'Search by title, date range, or calendar name.',
270
+ 'Use to check for existing events before creating new ones, or to verify a recently added event.',
271
+ 'Returns event id, title, start/end time, location, and calendar name.',
272
+ ].join(' '), {
273
+ title: z
274
+ .string()
275
+ .optional()
276
+ .describe('Filter events whose title contains this text (case-insensitive)'),
277
+ from: z
278
+ .string()
279
+ .optional()
280
+ .describe('Show events on or after this date (ISO 8601, e.g. 2026-02-19). Defaults to 7 days ago.'),
281
+ to: z
282
+ .string()
283
+ .optional()
284
+ .describe('Show events on or before this date (ISO 8601, e.g. 2026-02-28). Defaults to 30 days from now.'),
285
+ calendar_name: z.string().optional().describe('Restrict to a specific calendar by name'),
286
+ limit: z
287
+ .number()
288
+ .int()
289
+ .min(1)
290
+ .max(100)
291
+ .default(20)
292
+ .describe('Maximum number of results (default: 20)'),
293
+ }, { readOnlyHint: true, destructiveHint: false }, async ({ title, from, to, calendar_name: calendarName, limit }) => {
294
+ const events = await localCalendarService.listEvents({
295
+ title,
296
+ from,
297
+ to,
298
+ calendarName,
299
+ limit,
300
+ });
301
+ if (events.length === 0) {
302
+ const filterDesc = title ? ` matching "${title}"` : '';
303
+ return {
304
+ content: [
305
+ {
306
+ type: 'text',
307
+ text: `No events found${filterDesc}. Try adjusting the date range or title filter.`,
308
+ },
309
+ ],
310
+ };
311
+ }
312
+ const lines = [`\uD83D\uDCC5 Found ${events.length} event(s):`, ''];
313
+ events.forEach((ev, i) => {
314
+ const loc = ev.location ? ` \uD83D\uDCCD ${ev.location}` : '';
315
+ lines.push(` ${i + 1}. ${ev.title}`, ` \uD83D\uDD50 ${ev.start} \u2013 ${ev.end}`, ` \uD83D\uDCC6 ${ev.calendar}${loc}`, ` ID: ${ev.id}`, '');
316
+ });
317
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
318
+ });
319
+ // ---------------------------------------------------------------------------
320
+ // list_reminders
321
+ // ---------------------------------------------------------------------------
322
+ server.tool('list_reminders', [
323
+ 'List reminders from macOS Reminders.app with optional filters.',
324
+ 'Search by title or list name. By default only shows incomplete reminders.',
325
+ 'Use to check for existing reminders before creating new ones, or to verify a recently added reminder.',
326
+ 'Returns reminder id, title, due date, completion status, priority, and list name.',
327
+ ].join(' '), {
328
+ title: z
329
+ .string()
330
+ .optional()
331
+ .describe('Filter reminders whose title contains this text (case-insensitive)'),
332
+ list_name: z.string().optional().describe('Restrict to a specific Reminders list by name'),
333
+ include_completed: z
334
+ .boolean()
335
+ .default(false)
336
+ .describe('Include completed reminders (default: false)'),
337
+ limit: z
338
+ .number()
339
+ .int()
340
+ .min(1)
341
+ .max(100)
342
+ .default(20)
343
+ .describe('Maximum number of results (default: 20)'),
344
+ }, { readOnlyHint: true, destructiveHint: false }, async ({ title, list_name: listName, include_completed: includeCompleted, limit }) => {
345
+ const reminders = await remindersService.listReminders({
346
+ title,
347
+ listName,
348
+ includeCompleted,
349
+ limit,
350
+ });
351
+ if (reminders.length === 0) {
352
+ const filterDesc = title ? ` matching "${title}"` : '';
353
+ return {
354
+ content: [
355
+ {
356
+ type: 'text',
357
+ text: `No reminders found${filterDesc}. Try adjusting the title filter or set include_completed=true.`,
358
+ },
359
+ ],
360
+ };
361
+ }
362
+ const lines = [`\uD83D\uDD14 Found ${reminders.length} reminder(s):`, ''];
363
+ reminders.forEach((r, i) => {
364
+ const status = r.completed ? '\u2705' : '\u2B1C';
365
+ const due = r.dueDate ? ` \uD83D\uDD50 ${r.dueDate}` : '';
366
+ const priority = r.priority !== 'none' ? ` \u26A0\uFE0F ${r.priority}` : '';
367
+ lines.push(` ${i + 1}. ${status} ${r.title}`, ` \uD83D\uDCCB ${r.list}${due}${priority}`, ` ID: ${r.id}`, '');
368
+ });
369
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
370
+ });
371
+ // ---------------------------------------------------------------------------
372
+ // create_reminder
373
+ // ---------------------------------------------------------------------------
374
+ server.tool('create_reminder', [
375
+ 'Create a reminder in macOS Reminders.app from an email.',
376
+ 'Shows a native confirmation dialog before adding.',
377
+ 'Use for action items, deadlines, and follow-up tasks extracted from emails.',
378
+ 'Use analyze_email_for_scheduling first to let the AI decide if a reminder is appropriate.',
379
+ ].join(' '), {
380
+ account: z.string().describe('Email account name'),
381
+ email_id: z.string().describe('Email ID from list_emails_metadata'),
382
+ mailbox: z.string().default('INBOX').describe('Mailbox containing the email'),
383
+ title: z.string().optional().describe('Reminder title (defaults to email subject)'),
384
+ notes: z
385
+ .string()
386
+ .optional()
387
+ .describe('Reminder body/notes (defaults to auto-built from email)'),
388
+ due_date: z
389
+ .string()
390
+ .optional()
391
+ .describe('ISO 8601 due date (e.g. 2026-02-20T10:00:00). Leave empty for no due date.'),
392
+ priority: z
393
+ .enum(['none', 'low', 'medium', 'high'])
394
+ .default('none')
395
+ .describe('Reminder priority'),
396
+ list_name: z.string().optional().describe('Reminders list name (default list if omitted)'),
397
+ confirm: z
398
+ .boolean()
399
+ .default(true)
400
+ .describe('Show native confirmation dialog before adding (default: true)'),
401
+ }, { readOnlyHint: false, destructiveHint: false }, async ({ account, email_id: emailId, mailbox, title, notes, due_date, priority, list_name, confirm, }) => {
402
+ const email = await imapService.getEmail(account, emailId, mailbox);
403
+ const bodyText = email.bodyText ?? '';
404
+ const bodyHtml = email.bodyHtml ?? '';
405
+ const reminderTitle = title ?? email.subject;
406
+ const from = email.from.name
407
+ ? `${email.from.name} <${email.from.address}>`
408
+ : email.from.address;
409
+ const snippet = (bodyText !== '' ? bodyText : bodyHtml).substring(0, 400).trim();
410
+ const reminderNotes = notes ??
411
+ [`\uD83D\uDCE7 From: ${from}`, `\uD83D\uDCCC Subject: ${email.subject}`, '', snippet]
412
+ .filter(Boolean)
413
+ .join('\n');
414
+ const result = await remindersService.addReminder({
415
+ title: reminderTitle,
416
+ notes: reminderNotes,
417
+ dueDate: due_date,
418
+ priority,
419
+ listName: list_name,
420
+ }, { confirm });
421
+ return {
422
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
423
+ };
424
+ });
425
+ // ---------------------------------------------------------------------------
426
+ // analyze_email_for_scheduling
427
+ // ---------------------------------------------------------------------------
428
+ server.tool('analyze_email_for_scheduling', [
429
+ 'Analyze an email to detect calendar events and/or reminder-worthy content.',
430
+ 'Returns structured analysis so the AI can decide whether to call add_to_calendar,',
431
+ 'create_reminder, both, or neither.',
432
+ 'Use this as the first step before creating any scheduling resource.',
433
+ ].join(' '), {
434
+ account: z.string().describe('Email account name'),
435
+ email_id: z.string().describe('Email ID from list_emails_metadata'),
436
+ mailbox: z.string().default('INBOX').describe('Mailbox containing the email'),
437
+ }, { readOnlyHint: true, destructiveHint: false }, async ({ account, email_id: emailId, mailbox }) => {
438
+ const email = await imapService.getEmail(account, emailId, mailbox);
439
+ const bodyText = email.bodyText ?? '';
440
+ const bodyHtml = email.bodyHtml ?? '';
441
+ const combined = `${bodyText}\n${bodyHtml}`;
442
+ // Check for ICS event
443
+ const icsContents = await imapService.getCalendarParts(account, mailbox, emailId);
444
+ let detectedEvent = null;
445
+ if (icsContents.length > 0) {
446
+ const events = calendarService.extractFromParts(icsContents);
447
+ if (events.length > 0) {
448
+ const ev = events[0];
449
+ detectedEvent = {
450
+ source: 'ics_attachment',
451
+ confidence: 'high',
452
+ title: ev.summary,
453
+ start: ev.start,
454
+ end: ev.end,
455
+ location: ev.location,
456
+ uid: ev.uid,
457
+ organizer: ev.organizer?.address,
458
+ attendees: ev.attendees.map((a) => a.address),
459
+ };
460
+ }
461
+ }
462
+ // Meeting URL detection
463
+ const meetingUrl = extractMeetingUrl(combined);
464
+ if (!detectedEvent && meetingUrl) {
465
+ detectedEvent = {
466
+ source: 'meeting_url',
467
+ confidence: 'medium',
468
+ title: email.subject,
469
+ start: email.date,
470
+ end: new Date(new Date(email.date).getTime() + 60 * 60 * 1000).toISOString(),
471
+ meetingUrl: meetingUrl.url,
472
+ provider: meetingUrl.label,
473
+ };
474
+ }
475
+ // Conference details
476
+ const conference = extractConferenceDetails(bodyText !== '' ? bodyText : bodyHtml);
477
+ // Reminder signal detection
478
+ const reminderMatch = REMINDER_KEYWORDS.exec(combined);
479
+ const detectedReminder = reminderMatch
480
+ ? {
481
+ confidence: 'medium',
482
+ keyword: reminderMatch[0],
483
+ title: email.subject,
484
+ suggestedNotes: `From: ${email.from.address}\n\n${(bodyText !== '' ? bodyText : bodyHtml).substring(0, 300)}`,
485
+ }
486
+ : null;
487
+ // Check if already processed by hooks
488
+ const { isCalendarProcessed, listCalendarProcessed } = await import('../utils/calendar-state.js');
489
+ const alreadyProcessed = await isCalendarProcessed(account, emailId);
490
+ const processedList = alreadyProcessed ? await listCalendarProcessed() : [];
491
+ const processedEntry = processedList.find(({ key }) => key.includes(emailId));
492
+ let recommendation;
493
+ if (detectedEvent && detectedReminder) {
494
+ recommendation = 'both';
495
+ }
496
+ else if (detectedEvent) {
497
+ recommendation = 'event';
498
+ }
499
+ else if (detectedReminder) {
500
+ recommendation = 'reminder';
501
+ }
502
+ else {
503
+ recommendation = 'none';
504
+ }
505
+ const analysis = {
506
+ emailId,
507
+ subject: email.subject,
508
+ from: email.from.address,
509
+ date: email.date,
510
+ attachmentCount: email.attachments.length,
511
+ recommendation,
512
+ alreadyAutoProcessed: alreadyProcessed,
513
+ autoProcessedEntry: processedEntry?.entry ?? null,
514
+ detectedEvent,
515
+ detectedReminder,
516
+ conferenceDetails: conference ?? null,
517
+ availableActions: {
518
+ add_to_calendar: detectedEvent !== null || meetingUrl !== undefined,
519
+ create_reminder: detectedReminder !== null,
520
+ },
521
+ instructions: [
522
+ detectedEvent
523
+ ? `Call add_to_calendar(account="${account}", email_id="${emailId}") to add the event.`
524
+ : null,
525
+ detectedReminder
526
+ ? `Call create_reminder(account="${account}", email_id="${emailId}") to add the reminder.`
527
+ : null,
528
+ alreadyProcessed
529
+ ? '\u26A0\uFE0F This email was already auto-processed once by the hook system. You are explicitly choosing to process it again.'
530
+ : null,
531
+ ].filter(Boolean),
532
+ };
533
+ return {
534
+ content: [{ type: 'text', text: JSON.stringify(analysis, null, 2) }],
535
+ };
536
+ });
537
+ }
538
+ //# sourceMappingURL=calendar.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.tool.js","sourceRoot":"","sources":["../../src/tools/calendar.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAK5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,+EAA+E;AAC/E,MAAM,iBAAiB,GACrB,2QAA2Q,CAAC;AAE9Q,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,MAAiB,EACjB,WAAwB,EACxB,eAAgC,EAChC,oBAA0C,EAC1C,gBAAkC;IAElC,8EAA8E;IAC9E,mBAAmB;IACnB,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,uIAAuI,EACvI;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KAC/E,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;QAChD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAElF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,aAAa,EAAE,KAAK,CAAC,OAAO;4BAC5B,MAAM,EAAE,EAAE;4BACV,KAAK,EAAE,CAAC;4BACR,OAAO,EAAE,6CAA6C;yBACvD,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAE7D,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,EAC9D,IAAI,EACJ,CAAC,CACF;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB;QACE,qFAAqF;QACrF,mGAAmG;QACnG,wEAAwE;QACxE,oGAAoG;QACpG,6EAA6E;QAC7E,6DAA6D;KAC9D,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QAC9E,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,iDAAiD,CAAC;QAC9D,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,IAAI,CAAC;aACT,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,qDAAqD,CAAC;QAClE,gBAAgB,EAAE,CAAC;aAChB,OAAO,EAAE;aACT,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,yEAAyE,CAAC;QACtF,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,+DAA+D,CAAC;KAC7E,EACD,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,EAC/C,KAAK,EAAE,EACL,OAAO,EACP,QAAQ,EAAE,OAAO,EACjB,OAAO,EACP,aAAa,EAAE,YAAY,EAC3B,aAAa,EAAE,YAAY,EAC3B,gBAAgB,EAAE,eAAe,EACjC,OAAO,GACR,EAAE,EAAE;QACH,sBAAsB;QACtB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,GAAG,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAEhD,+CAA+C;QAC/C,IAAI,UAAU,GAAS,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,QAAQ,GAAS,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACrE,IAAI,aAAiC,CAAC;QACtC,IAAI,cAAkC,CAAC;QACvC,IAAI,cAAc,GAAa,EAAE,CAAC;QAClC,IAAI,MAA0B,CAAC;QAE/B,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAClF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAC7D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACrB,UAAU,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;gBAChC,QAAQ,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;gBAC5B,aAAa,GAAG,EAAE,CAAC,QAAQ,CAAC;gBAC5B,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC;gBAChB,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;oBACjB,cAAc,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI;wBAChC,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,EAAE,CAAC,SAAS,CAAC,OAAO,GAAG;wBAClD,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC3B,CAAC;gBACD,cAAc,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACtC,IAAI,CAAC,CAAC,IAAI;wBAAE,OAAO,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,GAAG,CAAC;oBAC9C,OAAO,CAAC,CAAC,OAAO,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,gDAAgD;QAChD,MAAM,UAAU,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,wBAAwB,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAEnF,6DAA6D;QAC7D,IAAI,gBAAgB,GAMd,EAAE,CAAC;QAET,IAAI,eAAe,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,OAAO,GAAG,IAAI,CAClB,wBAAwB,EACxB,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CACxD,CAAC;YACF,gBAAgB,GAAG,MAAM,WAAW,CAAC,oBAAoB,CACvD,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,CACR,CAAC;QACJ,CAAC;QAED,sBAAsB;QACtB,MAAM,KAAK,GAAG,kBAAkB,CAAC;YAC/B,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;gBACxB,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG;gBAC9C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO;YACtB,YAAY,EAAE,KAAK,CAAC,OAAO;YAC3B,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE;gBACnD,OAAO,EAAE,OAAO;gBAChB,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,SAAS;aAClB,CAAC;YACF,SAAS,EAAE,cAAc;YACzB,SAAS,EAAE,cAAc;YACzB,UAAU,EAAE,UAAU,EAAE,GAAG;YAC3B,eAAe,EAAE,UAAU,EAAE,KAAK;YAClC,MAAM,EAAE,UAAU,EAAE,MAAM;YAC1B,SAAS,EAAE,UAAU,EAAE,SAAS;YAChC,QAAQ,EAAE,UAAU,EAAE,QAAQ;YAC9B,kBAAkB,EAAE,UAAU,EAAE,QAAQ;YACxC,WAAW,EAAE,QAAQ,IAAI,QAAQ;YACjC,gBAAgB;SACjB,CAAC,CAAC;QAEH,8EAA8E;QAC9E,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,QAAQ,CAChD;YACE,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,KAAK,EAAE,UAAU;YACjB,GAAG,EAAE,QAAQ;YACb,QAAQ,EAAE,aAAa;YACvB,KAAK;YACL,GAAG,EAAE,UAAU,EAAE,GAAG;YACpB,QAAQ,EAAE,UAAU,EAAE,KAAK;YAC3B,YAAY;YACZ,aAAa,EAAE,cAAc,CAAC,MAAM;YACpC,gBAAgB;YAChB,MAAM,EAAE,UAAU,EAAE,MAAM;YAC1B,SAAS,EAAE,UAAU,EAAE,SAAS;YAChC,QAAQ,EAAE,UAAU,EAAE,QAAQ;YAC9B,kBAAkB,EAAE,UAAU,EAAE,QAAQ;YACxC,MAAM;SACP,EACD,YAAY,EACZ,EAAE,OAAO,EAAE,CACZ,CAAC;QAEF,oBAAoB;QACpB,MAAM,OAAO,GAA4B;YACvC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YACrC,OAAO,CAAC,IAAI,GAAG,4EAA4E,CAAC;QAC9F,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,GAAG;gBACd,KAAK,EAAE,KAAK,CAAC,OAAO;gBACpB,KAAK,EAAE,UAAU,CAAC,WAAW,EAAE;gBAC/B,GAAG,EAAE,QAAQ,CAAC,WAAW,EAAE;gBAC3B,QAAQ,EAAE,aAAa;gBACvB,QAAQ,EAAE,MAAM,CAAC,YAAY;gBAC7B,UAAU,EAAE,UAAU,EAAE,GAAG;gBAC3B,MAAM,EAAE,UAAU,EAAE,MAAM;gBAC1B,SAAS,EAAE,UAAU,EAAE,SAAS;gBAChC,gBAAgB,EAAE,gBAAgB,CAAC,MAAM;gBACzC,WAAW,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxC,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,SAAS,EAAE,CAAC,CAAC,SAAS;iBACvB,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,6BAA6B;IAC7B,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,4BAA4B,EAC5B;QACE,iDAAiD;QACjD,8FAA8F;QAC9F,iFAAiF;KAClF,CAAC,IAAI,CAAC,GAAG,CAAC,EACX,EAAE,EACF,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,IAAI,EAAE;QACT,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC/C,oBAAoB,CAAC,gBAAgB,EAAE;YACvC,gBAAgB,CAAC,gBAAgB,EAAE;SACpC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG;YACZ,sBAAsB;YACtB,aAAa,SAAS,CAAC,QAAQ,EAAE;YACjC,mBAAmB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE;SAC1D,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC;YACtC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;gBACzC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,mBAAmB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC;YACtC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;gBACzC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB;QACE,0EAA0E;QAC1E,qFAAqF;KACtF,CAAC,IAAI,CAAC,GAAG,CAAC,EACX,EAAE,EACF,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,IAAI,EAAE;QACT,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC,aAAa,EAAE,CAAC;QAC7D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,sEAAsE;qBAC7E;iBACF;aACF,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,SAAS,SAAS,CAAC,MAAM,eAAe,EAAE,EAAE,CAAC,CAAC;QAC7D,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,aAAa,EACb;QACE,mDAAmD;QACnD,gDAAgD;QAChD,iGAAiG;QACjG,uEAAuE;KACxE,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;QACE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,iEAAiE,CAAC;QAC9E,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,wFAAwF,CACzF;QACH,EAAE,EAAE,CAAC;aACF,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,+FAA+F,CAChG;QACH,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QACxF,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,yCAAyC,CAAC;KACvD,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;QAChE,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC;YACnD,KAAK;YACL,IAAI;YACJ,EAAE;YACF,YAAY;YACZ,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,kBAAkB,UAAU,iDAAiD;qBACpF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,sBAAsB,MAAM,CAAC,MAAM,YAAY,EAAE,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YACvB,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EACzB,qBAAqB,EAAE,CAAC,KAAK,WAAW,EAAE,CAAC,GAAG,EAAE,EAChD,qBAAqB,EAAE,CAAC,QAAQ,GAAG,GAAG,EAAE,EACxC,YAAY,EAAE,CAAC,EAAE,EAAE,EACnB,EAAE,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB;QACE,gEAAgE;QAChE,2EAA2E;QAC3E,uGAAuG;QACvG,mFAAmF;KACpF,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;QACE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,oEAAoE,CAAC;QACjF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC1F,iBAAiB,EAAE,CAAC;aACjB,OAAO,EAAE;aACT,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CAAC,8CAA8C,CAAC;QAC3D,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,yCAAyC,CAAC;KACvD,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAAE,EAAE;QACnF,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,aAAa,CAAC;YACrD,KAAK;YACL,QAAQ;YACR,gBAAgB;YAChB,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,qBAAqB,UAAU,iEAAiE;qBACvG;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,sBAAsB,SAAS,CAAC,MAAM,eAAe,EAAE,EAAE,CAAC,CAAC;QAC1E,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACzB,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YACjD,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,EAAE,EAClC,qBAAqB,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG,QAAQ,EAAE,EAC9C,YAAY,CAAC,CAAC,EAAE,EAAE,EAClB,EAAE,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1E,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB;QACE,yDAAyD;QACzD,mDAAmD;QACnD,6EAA6E;QAC7E,2FAA2F;KAC5F,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACnE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC7E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACnF,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,yDAAyD,CAAC;QACtE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,4EAA4E,CAAC;QACzF,QAAQ,EAAE,CAAC;aACR,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;aACvC,OAAO,CAAC,MAAM,CAAC;aACf,QAAQ,CAAC,mBAAmB,CAAC;QAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC1F,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,+DAA+D,CAAC;KAC7E,EACD,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,EAC/C,KAAK,EAAE,EACL,OAAO,EACP,QAAQ,EAAE,OAAO,EACjB,OAAO,EACP,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,OAAO,GACR,EAAE,EAAE;QACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QAEtC,MAAM,aAAa,GAAG,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;QAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI;YAC1B,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG;YAC9C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;QACvB,MAAM,OAAO,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACjF,MAAM,aAAa,GACjB,KAAK;YACL,CAAC,sBAAsB,IAAI,EAAE,EAAE,yBAAyB,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC;iBAClF,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhB,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAC/C;YACE,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE,QAAQ;YACjB,QAAQ;YACR,QAAQ,EAAE,SAAS;SACpB,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,+BAA+B;IAC/B,8EAA8E;IAE9E,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B;QACE,4EAA4E;QAC5E,mFAAmF;QACnF,oCAAoC;QACpC,qEAAqE;KACtE,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACnE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;KAC9E,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;QAChD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,GAAG,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAE5C,sBAAsB;QACtB,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAClF,IAAI,aAAa,GAAmC,IAAI,CAAC;QACzD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAC7D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACrB,aAAa,GAAG;oBACd,MAAM,EAAE,gBAAgB;oBACxB,UAAU,EAAE,MAAM;oBAClB,KAAK,EAAE,EAAE,CAAC,OAAO;oBACjB,KAAK,EAAE,EAAE,CAAC,KAAK;oBACf,GAAG,EAAE,EAAE,CAAC,GAAG;oBACX,QAAQ,EAAE,EAAE,CAAC,QAAQ;oBACrB,GAAG,EAAE,EAAE,CAAC,GAAG;oBACX,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO;oBAChC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;iBAC9C,CAAC;YACJ,CAAC;QACH,CAAC;QAED,wBAAwB;QACxB,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,CAAC,aAAa,IAAI,UAAU,EAAE,CAAC;YACjC,aAAa,GAAG;gBACd,MAAM,EAAE,aAAa;gBACrB,UAAU,EAAE,QAAQ;gBACpB,KAAK,EAAE,KAAK,CAAC,OAAO;gBACpB,KAAK,EAAE,KAAK,CAAC,IAAI;gBACjB,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;gBAC5E,UAAU,EAAE,UAAU,CAAC,GAAG;gBAC1B,QAAQ,EAAE,UAAU,CAAC,KAAK;aAC3B,CAAC;QACJ,CAAC;QAED,qBAAqB;QACrB,MAAM,UAAU,GAAG,wBAAwB,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAEnF,4BAA4B;QAC5B,MAAM,aAAa,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,gBAAgB,GAAG,aAAa;YACpC,CAAC,CAAC;gBACE,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;gBACzB,KAAK,EAAE,KAAK,CAAC,OAAO;gBACpB,cAAc,EAAE,SAAS,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;aAC9G;YACH,CAAC,CAAC,IAAI,CAAC;QAET,sCAAsC;QACtC,MAAM,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CACjE,4BAA4B,CAC7B,CAAC;QACF,MAAM,gBAAgB,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,aAAa,GAAG,gBAAgB,CAAC,CAAC,CAAC,MAAM,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9E,IAAI,cAAsB,CAAC;QAC3B,IAAI,aAAa,IAAI,gBAAgB,EAAE,CAAC;YACtC,cAAc,GAAG,MAAM,CAAC;QAC1B,CAAC;aAAM,IAAI,aAAa,EAAE,CAAC;YACzB,cAAc,GAAG,OAAO,CAAC;QAC3B,CAAC;aAAM,IAAI,gBAAgB,EAAE,CAAC;YAC5B,cAAc,GAAG,UAAU,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,MAAM,CAAC;QAC1B,CAAC;QAED,MAAM,QAAQ,GAAG;YACf,OAAO;YACP,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO;YACxB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,eAAe,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM;YACzC,cAAc;YACd,oBAAoB,EAAE,gBAAgB;YACtC,kBAAkB,EAAE,cAAc,EAAE,KAAK,IAAI,IAAI;YACjD,aAAa;YACb,gBAAgB;YAChB,iBAAiB,EAAE,UAAU,IAAI,IAAI;YACrC,gBAAgB,EAAE;gBAChB,eAAe,EAAE,aAAa,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS;gBACnE,eAAe,EAAE,gBAAgB,KAAK,IAAI;aAC3C;YACD,YAAY,EAAE;gBACZ,aAAa;oBACX,CAAC,CAAC,iCAAiC,OAAO,gBAAgB,OAAO,sBAAsB;oBACvF,CAAC,CAAC,IAAI;gBACR,gBAAgB;oBACd,CAAC,CAAC,iCAAiC,OAAO,gBAAgB,OAAO,yBAAyB;oBAC1F,CAAC,CAAC,IAAI;gBACR,gBAAgB;oBACd,CAAC,CAAC,8HAA8H;oBAChI,CAAC,CAAC,IAAI;aACT,CAAC,MAAM,CAAC,OAAO,CAAC;SAClB,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC9E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * MCP tool: extract_contacts
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type ImapService from '../services/imap.service.js';
6
+ export default function registerContactsTools(server: McpServer, imapService: ImapService): void;
7
+ //# sourceMappingURL=contacts.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts.tool.d.ts","sourceRoot":"","sources":["../../src/tools/contacts.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAE3D,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CA4C/F"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * MCP tool: extract_contacts
3
+ */
4
+ import { z } from 'zod';
5
+ export default function registerContactsTools(server, imapService) {
6
+ server.tool('extract_contacts', 'Extract unique contacts from recent email headers. Returns contacts sorted by frequency (most frequent first). Useful for finding frequent correspondents or building an address book.', {
7
+ account: z.string().describe('Account name from list_accounts'),
8
+ mailbox: z.string().optional().describe('Mailbox to scan (default: INBOX)'),
9
+ limit: z
10
+ .number()
11
+ .int()
12
+ .min(1)
13
+ .max(500)
14
+ .default(100)
15
+ .describe('Number of recent emails to scan (default: 100, max: 500)'),
16
+ }, { readOnlyHint: true, destructiveHint: false }, async ({ account, mailbox, limit }) => {
17
+ try {
18
+ const contacts = await imapService.extractContacts(account, {
19
+ mailbox,
20
+ limit,
21
+ });
22
+ return {
23
+ content: [
24
+ {
25
+ type: 'text',
26
+ text: `Found ${contacts.length} unique contacts from ${limit} recent emails:\n\n${JSON.stringify(contacts, null, 2)}`,
27
+ },
28
+ ],
29
+ };
30
+ }
31
+ catch (err) {
32
+ return {
33
+ isError: true,
34
+ content: [
35
+ {
36
+ type: 'text',
37
+ text: `Failed to extract contacts: ${err instanceof Error ? err.message : String(err)}`,
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ });
43
+ }
44
+ //# sourceMappingURL=contacts.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts.tool.js","sourceRoot":"","sources":["../../src/tools/contacts.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,MAAiB,EAAE,WAAwB;IACvF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,wLAAwL,EACxL;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QAC/D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QAC3E,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,GAAG,CAAC;aACZ,QAAQ,CAAC,0DAA0D,CAAC;KACxE,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,EAC9C,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACpC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,OAAO,EAAE;gBAC1D,OAAO;gBACP,KAAK;aACN,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,SAAS,QAAQ,CAAC,MAAM,yBAAyB,KAAK,sBAAsB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;qBACtH;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;qBACxF;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * MCP tools: save_draft, send_draft
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type ImapService from '../services/imap.service.js';
6
+ import type SmtpService from '../services/smtp.service.js';
7
+ export default function registerDraftTools(server: McpServer, imapService: ImapService, smtpService: SmtpService): void;
8
+ //# sourceMappingURL=drafts.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drafts.tool.d.ts","sourceRoot":"","sources":["../../src/tools/drafts.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAE3D,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GACvB,IAAI,CAoGN"}