@agenticmail/enterprise 0.5.50 → 0.5.51

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.
@@ -0,0 +1,785 @@
1
+ /**
2
+ * AgenticMail Agent Tools — Enterprise Adapter
3
+ *
4
+ * Wraps the self-contained agenticmail-core tool handlers into
5
+ * the enterprise AgentTool format so they integrate with the
6
+ * enterprise tool system (middleware, audit, security, etc.).
7
+ *
8
+ * The core tools.ts was written for OpenClaw's registerTool() API.
9
+ * This adapter intercepts those registrations and produces AgentTool[].
10
+ */
11
+
12
+ import type { AnyAgentTool, ToolCreationOptions, ToolParameterSchema } from '../types.js';
13
+ import { jsonResult, errorResult } from '../common.js';
14
+
15
+ /** AgenticMail API connection config */
16
+ export interface AgenticMailConnectionConfig {
17
+ /** AgenticMail API base URL (e.g. http://localhost:3141) */
18
+ apiUrl: string;
19
+ /** Agent API key */
20
+ apiKey: string;
21
+ /** Master key for admin operations (optional) */
22
+ masterKey?: string;
23
+ /** Display name for the agent */
24
+ ownerName?: string;
25
+ }
26
+
27
+ /**
28
+ * Create all AgenticMail tools as enterprise AgentTool objects.
29
+ *
30
+ * These tools make HTTP calls to the AgenticMail API server.
31
+ * They need a running AgenticMail instance to function.
32
+ *
33
+ * @param connection - AgenticMail API connection config
34
+ * @param options - Standard enterprise tool creation options
35
+ */
36
+ export function createAgenticMailTools(
37
+ connection: AgenticMailConnectionConfig,
38
+ options?: ToolCreationOptions,
39
+ ): AnyAgentTool[] {
40
+ const tools: AnyAgentTool[] = [];
41
+
42
+ // ─── HTTP helper (same as agenticmail-core/tools.ts apiRequest) ────
43
+
44
+ async function apiRequest(
45
+ method: string,
46
+ path: string,
47
+ body?: unknown,
48
+ useMasterKey = false,
49
+ timeoutMs = 30_000,
50
+ ): Promise<any> {
51
+ const key = useMasterKey && connection.masterKey
52
+ ? connection.masterKey
53
+ : connection.apiKey;
54
+ if (!key) {
55
+ throw new Error(
56
+ useMasterKey
57
+ ? 'Master key is required for this operation but was not configured'
58
+ : 'API key is not configured',
59
+ );
60
+ }
61
+
62
+ const headers: Record<string, string> = { Authorization: `Bearer ${key}` };
63
+ if (body !== undefined) headers['Content-Type'] = 'application/json';
64
+
65
+ const response = await fetch(`${connection.apiUrl}/api/agenticmail${path}`, {
66
+ method,
67
+ headers,
68
+ body: body ? JSON.stringify(body) : undefined,
69
+ signal: AbortSignal.timeout(timeoutMs),
70
+ });
71
+
72
+ if (!response.ok) {
73
+ let text: string;
74
+ try {
75
+ text = await response.text();
76
+ } catch {
77
+ text = '(could not read response body)';
78
+ }
79
+ throw new Error(`AgenticMail API error ${response.status}: ${text}`);
80
+ }
81
+
82
+ const contentType = response.headers.get('content-type');
83
+ if (contentType?.includes('application/json')) {
84
+ try {
85
+ return await response.json();
86
+ } catch {
87
+ throw new Error(`API returned invalid JSON from ${path}`);
88
+ }
89
+ }
90
+ return null;
91
+ }
92
+
93
+ // ─── Helper: define an agenticmail tool ────────────────────────────
94
+
95
+ function defTool(
96
+ name: string,
97
+ label: string,
98
+ description: string,
99
+ params: ToolParameterSchema,
100
+ risk: 'low' | 'medium' | 'high' | 'critical',
101
+ handler: (args: Record<string, unknown>) => Promise<any>,
102
+ ): void {
103
+ tools.push({
104
+ name,
105
+ label,
106
+ description,
107
+ category: 'utility',
108
+ risk,
109
+ parameters: params,
110
+ execute: async (_toolCallId, args) => {
111
+ try {
112
+ const result = await handler(args as Record<string, unknown>);
113
+ return jsonResult(result);
114
+ } catch (err: any) {
115
+ return errorResult(err.message || String(err));
116
+ }
117
+ },
118
+ });
119
+ }
120
+
121
+ // Helper for simple params
122
+ function p(props: Record<string, any>, required?: string[]): ToolParameterSchema {
123
+ return { type: 'object', properties: props, required };
124
+ }
125
+
126
+ // ─── Email Core ───────────────────────────────────────────────────
127
+
128
+ defTool('agenticmail_send', 'Send Email',
129
+ 'Send an email from the agent mailbox. Outbound guard scans for PII/credentials.',
130
+ p({
131
+ to: { type: 'string', description: 'Recipient email' },
132
+ subject: { type: 'string', description: 'Email subject' },
133
+ text: { type: 'string', description: 'Plain text body' },
134
+ html: { type: 'string', description: 'HTML body' },
135
+ cc: { type: 'string', description: 'CC recipients' },
136
+ }, ['to', 'subject']),
137
+ 'high',
138
+ async (args) => apiRequest('POST', '/mail/send', args),
139
+ );
140
+
141
+ defTool('agenticmail_reply', 'Reply to Email',
142
+ 'Reply to an email by UID.',
143
+ p({
144
+ uid: { type: 'number', description: 'Email UID to reply to' },
145
+ text: { type: 'string', description: 'Reply text' },
146
+ replyAll: { type: 'boolean', description: 'Reply to all recipients' },
147
+ }, ['uid', 'text']),
148
+ 'high',
149
+ async (args) => apiRequest('POST', `/mail/${args.uid}/reply`, { text: args.text, replyAll: args.replyAll }),
150
+ );
151
+
152
+ defTool('agenticmail_forward', 'Forward Email',
153
+ 'Forward an email to another recipient.',
154
+ p({
155
+ uid: { type: 'number', description: 'Email UID to forward' },
156
+ to: { type: 'string', description: 'Recipient to forward to' },
157
+ text: { type: 'string', description: 'Additional message' },
158
+ }, ['uid', 'to']),
159
+ 'high',
160
+ async (args) => apiRequest('POST', `/mail/${args.uid}/forward`, { to: args.to, text: args.text }),
161
+ );
162
+
163
+ defTool('agenticmail_inbox', 'List Inbox',
164
+ 'List recent emails in the inbox.',
165
+ p({
166
+ limit: { type: 'number', description: 'Max messages (default 20)' },
167
+ offset: { type: 'number', description: 'Skip messages (default 0)' },
168
+ }),
169
+ 'low',
170
+ async (args) => {
171
+ const qs = new URLSearchParams();
172
+ if (args.limit) qs.set('limit', String(args.limit));
173
+ if (args.offset) qs.set('offset', String(args.offset));
174
+ const q = qs.toString();
175
+ return apiRequest('GET', `/mail/inbox${q ? '?' + q : ''}`);
176
+ },
177
+ );
178
+
179
+ defTool('agenticmail_read', 'Read Email',
180
+ 'Read a specific email by UID.',
181
+ p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
182
+ 'low',
183
+ async (args) => apiRequest('GET', `/mail/${args.uid}`),
184
+ );
185
+
186
+ defTool('agenticmail_search', 'Search Emails',
187
+ 'Search emails by criteria.',
188
+ p({
189
+ from: { type: 'string', description: 'Sender address' },
190
+ to: { type: 'string', description: 'Recipient address' },
191
+ subject: { type: 'string', description: 'Subject keyword' },
192
+ text: { type: 'string', description: 'Body text' },
193
+ since: { type: 'string', description: 'Since date (ISO 8601)' },
194
+ before: { type: 'string', description: 'Before date (ISO 8601)' },
195
+ seen: { type: 'boolean', description: 'Filter by read/unread' },
196
+ searchRelay: { type: 'boolean', description: 'Also search connected Gmail/Outlook' },
197
+ }),
198
+ 'low',
199
+ async (args) => apiRequest('POST', '/mail/search', args),
200
+ );
201
+
202
+ defTool('agenticmail_digest', 'Inbox Digest',
203
+ 'Compact inbox digest with subject, sender, date, and preview.',
204
+ p({
205
+ limit: { type: 'number', description: 'Max messages (default 20)' },
206
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
207
+ previewLength: { type: 'number', description: 'Preview text length (default 200)' },
208
+ }),
209
+ 'low',
210
+ async (args) => apiRequest('POST', '/mail/digest', args),
211
+ );
212
+
213
+ defTool('agenticmail_delete', 'Delete Email',
214
+ 'Delete an email by UID.',
215
+ p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
216
+ 'medium',
217
+ async (args) => apiRequest('DELETE', `/mail/${args.uid}`),
218
+ );
219
+
220
+ defTool('agenticmail_move', 'Move Email',
221
+ 'Move an email to another folder.',
222
+ p({
223
+ uid: { type: 'number', description: 'Email UID' },
224
+ to: { type: 'string', description: 'Destination folder' },
225
+ from: { type: 'string', description: 'Source folder (default INBOX)' },
226
+ }, ['uid', 'to']),
227
+ 'low',
228
+ async (args) => apiRequest('POST', `/mail/${args.uid}/move`, { to: args.to, from: args.from }),
229
+ );
230
+
231
+ defTool('agenticmail_mark_read', 'Mark Read',
232
+ 'Mark an email as read.',
233
+ p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
234
+ 'low',
235
+ async (args) => apiRequest('POST', `/mail/${args.uid}/read`),
236
+ );
237
+
238
+ defTool('agenticmail_mark_unread', 'Mark Unread',
239
+ 'Mark an email as unread.',
240
+ p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
241
+ 'low',
242
+ async (args) => apiRequest('POST', `/mail/${args.uid}/unread`),
243
+ );
244
+
245
+ defTool('agenticmail_folders', 'List Folders',
246
+ 'List all mail folders.',
247
+ p({}),
248
+ 'low',
249
+ async () => apiRequest('GET', '/mail/folders'),
250
+ );
251
+
252
+ defTool('agenticmail_list_folder', 'List Folder',
253
+ 'List messages in a specific folder.',
254
+ p({
255
+ folder: { type: 'string', description: 'Folder path (e.g. Sent, Trash)' },
256
+ limit: { type: 'number', description: 'Max messages (default 20)' },
257
+ offset: { type: 'number', description: 'Skip messages (default 0)' },
258
+ }, ['folder']),
259
+ 'low',
260
+ async (args) => {
261
+ const qs = new URLSearchParams();
262
+ qs.set('folder', String(args.folder));
263
+ if (args.limit) qs.set('limit', String(args.limit));
264
+ if (args.offset) qs.set('offset', String(args.offset));
265
+ return apiRequest('GET', `/mail/list?${qs}`);
266
+ },
267
+ );
268
+
269
+ defTool('agenticmail_create_folder', 'Create Folder',
270
+ 'Create a new mail folder.',
271
+ p({ name: { type: 'string', description: 'Folder name' } }, ['name']),
272
+ 'low',
273
+ async (args) => apiRequest('POST', '/mail/folders', { name: args.name }),
274
+ );
275
+
276
+ // ─── Batch Operations ──────────────────────────────────────────────
277
+
278
+ defTool('agenticmail_batch_read', 'Batch Read',
279
+ 'Read multiple emails at once by UIDs.',
280
+ p({
281
+ uids: { type: 'array', description: 'Array of UIDs to read' },
282
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
283
+ }, ['uids']),
284
+ 'low',
285
+ async (args) => apiRequest('POST', '/mail/batch/read', args),
286
+ );
287
+
288
+ defTool('agenticmail_batch_delete', 'Batch Delete',
289
+ 'Delete multiple emails by UIDs.',
290
+ p({
291
+ uids: { type: 'array', description: 'UIDs to delete' },
292
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
293
+ }, ['uids']),
294
+ 'medium',
295
+ async (args) => apiRequest('POST', '/mail/batch/delete', args),
296
+ );
297
+
298
+ defTool('agenticmail_batch_move', 'Batch Move',
299
+ 'Move multiple emails to another folder.',
300
+ p({
301
+ uids: { type: 'array', description: 'UIDs to move' },
302
+ to: { type: 'string', description: 'Destination folder' },
303
+ from: { type: 'string', description: 'Source folder (default INBOX)' },
304
+ }, ['uids', 'to']),
305
+ 'low',
306
+ async (args) => apiRequest('POST', '/mail/batch/move', args),
307
+ );
308
+
309
+ defTool('agenticmail_batch_mark_read', 'Batch Mark Read',
310
+ 'Mark multiple emails as read.',
311
+ p({
312
+ uids: { type: 'array', description: 'UIDs to mark as read' },
313
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
314
+ }, ['uids']),
315
+ 'low',
316
+ async (args) => apiRequest('POST', '/mail/batch/mark-read', args),
317
+ );
318
+
319
+ defTool('agenticmail_batch_mark_unread', 'Batch Mark Unread',
320
+ 'Mark multiple emails as unread.',
321
+ p({
322
+ uids: { type: 'array', description: 'UIDs to mark as unread' },
323
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
324
+ }, ['uids']),
325
+ 'low',
326
+ async (args) => apiRequest('POST', '/mail/batch/mark-unread', args),
327
+ );
328
+
329
+ // ─── Agent Communication ──────────────────────────────────────────
330
+
331
+ defTool('agenticmail_list_agents', 'List Agents',
332
+ 'List all AI agents in the system.',
333
+ p({}),
334
+ 'low',
335
+ async () => apiRequest('GET', '/agents'),
336
+ );
337
+
338
+ defTool('agenticmail_message_agent', 'Message Agent',
339
+ 'Send a message to another AI agent by name.',
340
+ p({
341
+ agent: { type: 'string', description: 'Recipient agent name' },
342
+ subject: { type: 'string', description: 'Message subject' },
343
+ text: { type: 'string', description: 'Message body' },
344
+ priority: { type: 'string', description: 'Priority: normal, high, urgent' },
345
+ }, ['agent', 'subject', 'text']),
346
+ 'medium',
347
+ async (args) => apiRequest('POST', '/agents/message', args),
348
+ );
349
+
350
+ defTool('agenticmail_call_agent', 'Call Agent',
351
+ 'Call another agent with a task. Supports sync and async modes.',
352
+ p({
353
+ target: { type: 'string', description: 'Agent name to call' },
354
+ task: { type: 'string', description: 'Task description' },
355
+ mode: { type: 'string', description: 'light, standard, or full' },
356
+ async: { type: 'boolean', description: 'Fire-and-forget (default false)' },
357
+ timeout: { type: 'number', description: 'Max seconds to wait (sync only)' },
358
+ }, ['target', 'task']),
359
+ 'medium',
360
+ async (args) => apiRequest('POST', '/agents/call', args, false, 600_000),
361
+ );
362
+
363
+ defTool('agenticmail_check_messages', 'Check Messages',
364
+ 'Check for new unread messages from other agents or external senders.',
365
+ p({}),
366
+ 'low',
367
+ async () => apiRequest('GET', '/agents/messages'),
368
+ );
369
+
370
+ defTool('agenticmail_check_tasks', 'Check Tasks',
371
+ 'Check for pending tasks assigned to you.',
372
+ p({
373
+ direction: { type: 'string', description: 'incoming or outgoing (default incoming)' },
374
+ assignee: { type: 'string', description: 'Check tasks for a specific agent' },
375
+ }),
376
+ 'low',
377
+ async (args) => apiRequest('POST', '/tasks/check', args),
378
+ );
379
+
380
+ defTool('agenticmail_claim_task', 'Claim Task',
381
+ 'Claim a pending task.',
382
+ p({ id: { type: 'string', description: 'Task ID' } }, ['id']),
383
+ 'low',
384
+ async (args) => apiRequest('POST', `/tasks/${args.id}/claim`),
385
+ );
386
+
387
+ defTool('agenticmail_submit_result', 'Submit Task Result',
388
+ 'Submit result for a claimed task.',
389
+ p({
390
+ id: { type: 'string', description: 'Task ID' },
391
+ result: { type: 'object', description: 'Task result data' },
392
+ }, ['id']),
393
+ 'low',
394
+ async (args) => apiRequest('POST', `/tasks/${args.id}/result`, { result: args.result }),
395
+ );
396
+
397
+ defTool('agenticmail_complete_task', 'Complete Task',
398
+ 'Claim and submit result in one call.',
399
+ p({
400
+ id: { type: 'string', description: 'Task ID' },
401
+ result: { type: 'object', description: 'Task result data' },
402
+ }, ['id']),
403
+ 'low',
404
+ async (args) => apiRequest('POST', `/tasks/${args.id}/complete`, { result: args.result }),
405
+ );
406
+
407
+ defTool('agenticmail_wait_for_email', 'Wait for Email',
408
+ 'Wait for a new email or task notification (push-based, SSE).',
409
+ p({ timeout: { type: 'number', description: 'Max seconds to wait (default 120)' } }),
410
+ 'low',
411
+ async (args) => apiRequest('GET', `/mail/wait?timeout=${args.timeout || 120}`, undefined, false, 310_000),
412
+ );
413
+
414
+ // ─── Account Management ───────────────────────────────────────────
415
+
416
+ defTool('agenticmail_whoami', 'Who Am I',
417
+ 'Get current agent account info.',
418
+ p({}),
419
+ 'low',
420
+ async () => apiRequest('GET', '/accounts/me'),
421
+ );
422
+
423
+ defTool('agenticmail_update_metadata', 'Update Metadata',
424
+ 'Update current agent metadata.',
425
+ p({ metadata: { type: 'object', description: 'Key-value pairs to set' } }, ['metadata']),
426
+ 'low',
427
+ async (args) => apiRequest('PATCH', '/accounts/me/metadata', { metadata: args.metadata }),
428
+ );
429
+
430
+ defTool('agenticmail_contacts', 'Manage Contacts',
431
+ 'List, add, or delete contacts.',
432
+ p({
433
+ action: { type: 'string', description: 'list, add, or delete' },
434
+ name: { type: 'string', description: 'Contact name (for add)' },
435
+ email: { type: 'string', description: 'Contact email (for add)' },
436
+ id: { type: 'string', description: 'Contact ID (for delete)' },
437
+ }, ['action']),
438
+ 'low',
439
+ async (args) => apiRequest('POST', '/contacts', args),
440
+ );
441
+
442
+ // ─── Tags & Labels ────────────────────────────────────────────────
443
+
444
+ defTool('agenticmail_tags', 'Manage Tags',
445
+ 'List, create, delete tags; tag/untag messages.',
446
+ p({
447
+ action: { type: 'string', description: 'list, create, delete, tag_message, untag_message, get_messages, get_message_tags' },
448
+ name: { type: 'string', description: 'Tag name (for create)' },
449
+ color: { type: 'string', description: 'Tag color hex (for create)' },
450
+ id: { type: 'string', description: 'Tag ID' },
451
+ uid: { type: 'number', description: 'Message UID' },
452
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
453
+ }, ['action']),
454
+ 'low',
455
+ async (args) => apiRequest('POST', '/tags', args),
456
+ );
457
+
458
+ // ─── Drafts ────────────────────────────────────────────────────────
459
+
460
+ defTool('agenticmail_drafts', 'Manage Drafts',
461
+ 'List, create, update, delete, or send drafts.',
462
+ p({
463
+ action: { type: 'string', description: 'list, create, update, delete, send' },
464
+ id: { type: 'string', description: 'Draft ID (for update/delete/send)' },
465
+ to: { type: 'string', description: 'Recipient (for create/update)' },
466
+ subject: { type: 'string', description: 'Subject (for create/update)' },
467
+ text: { type: 'string', description: 'Body text (for create/update)' },
468
+ }, ['action']),
469
+ 'medium',
470
+ async (args) => apiRequest('POST', '/drafts', args),
471
+ );
472
+
473
+ // ─── Templates ─────────────────────────────────────────────────────
474
+
475
+ defTool('agenticmail_templates', 'Manage Templates',
476
+ 'List, create, or delete email templates.',
477
+ p({
478
+ action: { type: 'string', description: 'list, create, or delete' },
479
+ id: { type: 'string', description: 'Template ID (for delete)' },
480
+ name: { type: 'string', description: 'Template name (for create)' },
481
+ subject: { type: 'string', description: 'Template subject (for create)' },
482
+ text: { type: 'string', description: 'Template body (for create)' },
483
+ }, ['action']),
484
+ 'low',
485
+ async (args) => apiRequest('POST', '/templates', args),
486
+ );
487
+
488
+ defTool('agenticmail_template_send', 'Send Template',
489
+ 'Send email using a saved template with variable substitution.',
490
+ p({
491
+ id: { type: 'string', description: 'Template ID' },
492
+ to: { type: 'string', description: 'Recipient email' },
493
+ variables: { type: 'object', description: 'Variables to substitute' },
494
+ cc: { type: 'string', description: 'CC recipients' },
495
+ }, ['id', 'to']),
496
+ 'high',
497
+ async (args) => apiRequest('POST', '/templates/send', args),
498
+ );
499
+
500
+ // ─── Signatures ────────────────────────────────────────────────────
501
+
502
+ defTool('agenticmail_signatures', 'Manage Signatures',
503
+ 'List, create, or delete email signatures.',
504
+ p({
505
+ action: { type: 'string', description: 'list, create, or delete' },
506
+ id: { type: 'string', description: 'Signature ID (for delete)' },
507
+ name: { type: 'string', description: 'Signature name (for create)' },
508
+ text: { type: 'string', description: 'Signature text (for create)' },
509
+ isDefault: { type: 'boolean', description: 'Set as default (for create)' },
510
+ }, ['action']),
511
+ 'low',
512
+ async (args) => apiRequest('POST', '/signatures', args),
513
+ );
514
+
515
+ // ─── Rules ─────────────────────────────────────────────────────────
516
+
517
+ defTool('agenticmail_rules', 'Manage Rules',
518
+ 'Server-side email rules that auto-process incoming messages.',
519
+ p({
520
+ action: { type: 'string', description: 'list, create, or delete' },
521
+ id: { type: 'string', description: 'Rule ID (for delete)' },
522
+ name: { type: 'string', description: 'Rule name (for create)' },
523
+ conditions: { type: 'object', description: 'Match conditions' },
524
+ actions: { type: 'object', description: 'Actions on match' },
525
+ priority: { type: 'number', description: 'Priority (higher = first)' },
526
+ }, ['action']),
527
+ 'medium',
528
+ async (args) => apiRequest('POST', '/rules', args),
529
+ );
530
+
531
+ // ─── Scheduled Emails ──────────────────────────────────────────────
532
+
533
+ defTool('agenticmail_schedule', 'Scheduled Emails',
534
+ 'Create, list, or cancel scheduled emails.',
535
+ p({
536
+ action: { type: 'string', description: 'create, list, or cancel' },
537
+ id: { type: 'string', description: 'Scheduled email ID (for cancel)' },
538
+ to: { type: 'string', description: 'Recipient (for create)' },
539
+ subject: { type: 'string', description: 'Subject (for create)' },
540
+ text: { type: 'string', description: 'Body (for create)' },
541
+ sendAt: { type: 'string', description: 'When to send (for create)' },
542
+ }, ['action']),
543
+ 'medium',
544
+ async (args) => apiRequest('POST', '/schedule', args),
545
+ );
546
+
547
+ // ─── Spam Management ───────────────────────────────────────────────
548
+
549
+ defTool('agenticmail_spam', 'Spam Management',
550
+ 'List spam, report spam, mark not-spam, or get spam score.',
551
+ p({
552
+ action: { type: 'string', description: 'list, report, not_spam, or score' },
553
+ uid: { type: 'number', description: 'Message UID (for report/not_spam/score)' },
554
+ folder: { type: 'string', description: 'Source folder (for report/score)' },
555
+ limit: { type: 'number', description: 'Max messages (for list)' },
556
+ }, ['action']),
557
+ 'low',
558
+ async (args) => apiRequest('POST', '/spam', args),
559
+ );
560
+
561
+ // ─── Pending Emails ────────────────────────────────────────────────
562
+
563
+ defTool('agenticmail_pending_emails', 'Pending Emails',
564
+ 'Check status of blocked outbound emails.',
565
+ p({
566
+ action: { type: 'string', description: 'list or get' },
567
+ id: { type: 'string', description: 'Pending email ID (for get)' },
568
+ }, ['action']),
569
+ 'low',
570
+ async (args) => apiRequest('POST', '/mail/pending', args),
571
+ );
572
+
573
+ // ─── Storage (Database) ────────────────────────────────────────────
574
+
575
+ defTool('agenticmail_storage', 'Agent Storage',
576
+ 'Full database management — tables, CRUD, aggregations, SQL.',
577
+ p({
578
+ action: { type: 'string', description: 'create_table, query, insert, update, delete_rows, sql, etc.' },
579
+ table: { type: 'string', description: 'Table name' },
580
+ columns: { type: 'array', description: 'Column definitions (for create_table)' },
581
+ rows: { type: 'array', description: 'Row data (for insert/upsert/import)' },
582
+ where: { type: 'object', description: 'Filter conditions' },
583
+ set: { type: 'object', description: 'Update values' },
584
+ sql: { type: 'string', description: 'Raw SQL (for sql action)' },
585
+ orderBy: { type: 'string', description: 'ORDER BY clause' },
586
+ limit: { type: 'number', description: 'Max rows' },
587
+ offset: { type: 'number', description: 'Skip rows' },
588
+ selectColumns: { type: 'array', description: 'Columns to select' },
589
+ operations: { type: 'array', description: 'Aggregate operations' },
590
+ groupBy: { type: 'string', description: 'GROUP BY clause' },
591
+ }, ['action']),
592
+ 'medium',
593
+ async (args) => apiRequest('POST', '/storage', args),
594
+ );
595
+
596
+ // ─── SMS ───────────────────────────────────────────────────────────
597
+
598
+ defTool('agenticmail_sms_setup', 'SMS Setup',
599
+ 'Configure SMS/phone via Google Voice.',
600
+ p({
601
+ phoneNumber: { type: 'string', description: 'Google Voice phone number' },
602
+ forwardingEmail: { type: 'string', description: 'Email for SMS forwarding' },
603
+ }, ['phoneNumber']),
604
+ 'medium',
605
+ async (args) => apiRequest('POST', '/sms/setup', args, true),
606
+ );
607
+
608
+ defTool('agenticmail_sms_send', 'Send SMS',
609
+ 'Send an SMS via Google Voice.',
610
+ p({
611
+ to: { type: 'string', description: 'Recipient phone number' },
612
+ body: { type: 'string', description: 'Message text' },
613
+ }, ['to', 'body']),
614
+ 'high',
615
+ async (args) => apiRequest('POST', '/sms/send', args),
616
+ );
617
+
618
+ defTool('agenticmail_sms_messages', 'SMS Messages',
619
+ 'List SMS messages.',
620
+ p({
621
+ direction: { type: 'string', description: 'inbound, outbound, or both' },
622
+ limit: { type: 'number', description: 'Max messages (default 20)' },
623
+ }),
624
+ 'low',
625
+ async (args) => apiRequest('POST', '/sms/messages', args),
626
+ );
627
+
628
+ defTool('agenticmail_sms_check_code', 'SMS Check Code',
629
+ 'Check for recent verification/OTP codes.',
630
+ p({ minutes: { type: 'number', description: 'How many minutes back (default 10)' } }),
631
+ 'low',
632
+ async (args) => apiRequest('POST', '/sms/check-code', args),
633
+ );
634
+
635
+ defTool('agenticmail_sms_config', 'SMS Config',
636
+ 'Get current SMS/phone configuration.',
637
+ p({}),
638
+ 'low',
639
+ async () => apiRequest('GET', '/sms/config'),
640
+ );
641
+
642
+ defTool('agenticmail_sms_record', 'Record SMS',
643
+ 'Record an SMS message from an external source.',
644
+ p({
645
+ from: { type: 'string', description: 'Sender phone number' },
646
+ body: { type: 'string', description: 'Message text' },
647
+ }, ['from', 'body']),
648
+ 'low',
649
+ async (args) => apiRequest('POST', '/sms/record', args),
650
+ );
651
+
652
+ defTool('agenticmail_sms_parse_email', 'Parse SMS Email',
653
+ 'Parse SMS from a forwarded Google Voice email.',
654
+ p({
655
+ emailBody: { type: 'string', description: 'Email body text' },
656
+ emailFrom: { type: 'string', description: 'Email sender address' },
657
+ }, ['emailBody']),
658
+ 'low',
659
+ async (args) => apiRequest('POST', '/sms/parse-email', args),
660
+ );
661
+
662
+ // ─── Admin Operations (require master key) ────────────────────────
663
+
664
+ defTool('agenticmail_create_account', 'Create Agent Account',
665
+ 'Create a new agent email account.',
666
+ p({
667
+ name: { type: 'string', description: 'Agent name' },
668
+ domain: { type: 'string', description: 'Email domain' },
669
+ role: { type: 'string', description: 'Agent role' },
670
+ }, ['name']),
671
+ 'high',
672
+ async (args) => apiRequest('POST', '/accounts', args, true),
673
+ );
674
+
675
+ defTool('agenticmail_delete_agent', 'Delete Agent',
676
+ 'Delete an agent account permanently.',
677
+ p({
678
+ name: { type: 'string', description: 'Agent name to delete' },
679
+ reason: { type: 'string', description: 'Reason for deletion' },
680
+ }, ['name']),
681
+ 'critical',
682
+ async (args) => apiRequest('DELETE', `/accounts/${encodeURIComponent(String(args.name))}`, { reason: args.reason }, true),
683
+ );
684
+
685
+ defTool('agenticmail_cleanup', 'Cleanup Agents',
686
+ 'List or remove inactive agent accounts.',
687
+ p({
688
+ action: { type: 'string', description: 'list_inactive, cleanup, or set_persistent' },
689
+ hours: { type: 'number', description: 'Inactivity threshold (default 24)' },
690
+ dryRun: { type: 'boolean', description: 'Preview only' },
691
+ agentId: { type: 'string', description: 'Agent ID (for set_persistent)' },
692
+ persistent: { type: 'boolean', description: 'Set persistent flag' },
693
+ }, ['action']),
694
+ 'high',
695
+ async (args) => apiRequest('POST', '/accounts/cleanup', args, true),
696
+ );
697
+
698
+ defTool('agenticmail_status', 'Server Status',
699
+ 'Check AgenticMail server health.',
700
+ p({}),
701
+ 'low',
702
+ async () => apiRequest('GET', '/status'),
703
+ );
704
+
705
+ // ─── Gateway & Setup ──────────────────────────────────────────────
706
+
707
+ defTool('agenticmail_gateway_status', 'Gateway Status',
708
+ 'Check email gateway status (relay, domain, or none).',
709
+ p({}),
710
+ 'low',
711
+ async () => apiRequest('GET', '/gateway/status', undefined, true),
712
+ );
713
+
714
+ defTool('agenticmail_setup_relay', 'Setup Relay',
715
+ 'Configure Gmail/Outlook relay for internet email.',
716
+ p({
717
+ provider: { type: 'string', description: 'gmail, outlook, or custom' },
718
+ email: { type: 'string', description: 'Your real email' },
719
+ password: { type: 'string', description: 'App password' },
720
+ }, ['provider', 'email', 'password']),
721
+ 'critical',
722
+ async (args) => apiRequest('POST', '/gateway/setup-relay', args, true),
723
+ );
724
+
725
+ defTool('agenticmail_setup_domain', 'Setup Domain',
726
+ 'Set up custom domain via Cloudflare for internet email.',
727
+ p({
728
+ cloudflareToken: { type: 'string', description: 'Cloudflare API token' },
729
+ cloudflareAccountId: { type: 'string', description: 'Cloudflare account ID' },
730
+ domain: { type: 'string', description: 'Domain to use' },
731
+ }, ['cloudflareToken', 'cloudflareAccountId']),
732
+ 'critical',
733
+ async (args) => apiRequest('POST', '/gateway/setup-domain', args, true),
734
+ );
735
+
736
+ defTool('agenticmail_import_relay', 'Import Relay Email',
737
+ 'Import an email from connected Gmail/Outlook into local inbox.',
738
+ p({ uid: { type: 'number', description: 'Relay UID to import' } }, ['uid']),
739
+ 'low',
740
+ async (args) => apiRequest('POST', '/mail/import-relay', { uid: args.uid }),
741
+ );
742
+
743
+ defTool('agenticmail_test_email', 'Test Email',
744
+ 'Send a test email to verify configuration.',
745
+ p({ to: { type: 'string', description: 'Test recipient' } }, ['to']),
746
+ 'medium',
747
+ async (args) => apiRequest('POST', '/gateway/test', { to: args.to }, true),
748
+ );
749
+
750
+ defTool('agenticmail_deletion_reports', 'Deletion Reports',
751
+ 'List or get agent deletion reports.',
752
+ p({ id: { type: 'string', description: 'Report ID (omit to list all)' } }),
753
+ 'low',
754
+ async (args) => apiRequest('GET', args.id ? `/accounts/deletion-reports/${args.id}` : '/accounts/deletion-reports', undefined, true),
755
+ );
756
+
757
+ defTool('agenticmail_setup_guide', 'Setup Guide',
758
+ 'Get comparison of email setup modes.',
759
+ p({}),
760
+ 'low',
761
+ async () => apiRequest('GET', '/gateway/setup-guide', undefined, true),
762
+ );
763
+
764
+ defTool('agenticmail_setup_gmail_alias', 'Gmail Alias Setup',
765
+ 'Get instructions for adding agent email as Gmail Send-As alias.',
766
+ p({
767
+ agentEmail: { type: 'string', description: 'Agent email to add as alias' },
768
+ agentDisplayName: { type: 'string', description: 'Display name for alias' },
769
+ }, ['agentEmail']),
770
+ 'low',
771
+ async (args) => apiRequest('POST', '/gateway/gmail-alias', args, true),
772
+ );
773
+
774
+ defTool('agenticmail_purchase_domain', 'Search Domains',
775
+ 'Search for available domains via Cloudflare.',
776
+ p({
777
+ keywords: { type: 'array', description: 'Search keywords' },
778
+ tld: { type: 'string', description: 'Preferred TLD' },
779
+ }, ['keywords']),
780
+ 'low',
781
+ async (args) => apiRequest('POST', '/gateway/search-domains', args, true),
782
+ );
783
+
784
+ return tools;
785
+ }