@agenticmail/enterprise 0.2.1

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 (69) hide show
  1. package/ARCHITECTURE.md +183 -0
  2. package/agenticmail-enterprise.db +0 -0
  3. package/dashboards/README.md +120 -0
  4. package/dashboards/dotnet/Program.cs +261 -0
  5. package/dashboards/express/app.js +146 -0
  6. package/dashboards/go/main.go +513 -0
  7. package/dashboards/html/index.html +535 -0
  8. package/dashboards/java/AgenticMailDashboard.java +376 -0
  9. package/dashboards/php/index.php +414 -0
  10. package/dashboards/python/app.py +273 -0
  11. package/dashboards/ruby/app.rb +195 -0
  12. package/dist/chunk-77IDQJL3.js +7 -0
  13. package/dist/chunk-7RGCCHIT.js +115 -0
  14. package/dist/chunk-DXNKR3TG.js +1355 -0
  15. package/dist/chunk-IQWA44WT.js +970 -0
  16. package/dist/chunk-LCUZGIDH.js +965 -0
  17. package/dist/chunk-N2JVTNNJ.js +2553 -0
  18. package/dist/chunk-O462UJBH.js +363 -0
  19. package/dist/chunk-PNKVD2UK.js +26 -0
  20. package/dist/cli.js +218 -0
  21. package/dist/dashboard/index.html +558 -0
  22. package/dist/db-adapter-DEWEFNIV.js +7 -0
  23. package/dist/dynamodb-CCGL2E77.js +426 -0
  24. package/dist/engine/index.js +1261 -0
  25. package/dist/index.js +522 -0
  26. package/dist/mongodb-ODTXIVPV.js +319 -0
  27. package/dist/mysql-RM3S2FV5.js +521 -0
  28. package/dist/postgres-LN7A6MGQ.js +518 -0
  29. package/dist/routes-2JEPIIKC.js +441 -0
  30. package/dist/routes-74ZLKJKP.js +399 -0
  31. package/dist/server.js +7 -0
  32. package/dist/sqlite-3K5YOZ4K.js +439 -0
  33. package/dist/turso-LDWODSDI.js +442 -0
  34. package/package.json +49 -0
  35. package/src/admin/routes.ts +331 -0
  36. package/src/auth/routes.ts +130 -0
  37. package/src/cli.ts +260 -0
  38. package/src/dashboard/index.html +558 -0
  39. package/src/db/adapter.ts +230 -0
  40. package/src/db/dynamodb.ts +456 -0
  41. package/src/db/factory.ts +51 -0
  42. package/src/db/mongodb.ts +360 -0
  43. package/src/db/mysql.ts +472 -0
  44. package/src/db/postgres.ts +479 -0
  45. package/src/db/sql-schema.ts +123 -0
  46. package/src/db/sqlite.ts +391 -0
  47. package/src/db/turso.ts +411 -0
  48. package/src/deploy/fly.ts +368 -0
  49. package/src/deploy/managed.ts +213 -0
  50. package/src/engine/activity.ts +474 -0
  51. package/src/engine/agent-config.ts +429 -0
  52. package/src/engine/agenticmail-bridge.ts +296 -0
  53. package/src/engine/approvals.ts +278 -0
  54. package/src/engine/db-adapter.ts +682 -0
  55. package/src/engine/db-schema.ts +335 -0
  56. package/src/engine/deployer.ts +595 -0
  57. package/src/engine/index.ts +134 -0
  58. package/src/engine/knowledge.ts +486 -0
  59. package/src/engine/lifecycle.ts +635 -0
  60. package/src/engine/openclaw-hook.ts +371 -0
  61. package/src/engine/routes.ts +528 -0
  62. package/src/engine/skills.ts +473 -0
  63. package/src/engine/tenant.ts +345 -0
  64. package/src/engine/tool-catalog.ts +189 -0
  65. package/src/index.ts +64 -0
  66. package/src/lib/resilience.ts +326 -0
  67. package/src/middleware/index.ts +286 -0
  68. package/src/server.ts +310 -0
  69. package/tsconfig.json +14 -0
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Multi-Tenant Isolation (OPTIONAL)
3
+ *
4
+ * For SaaS deployments: Companies sharing infrastructure need strict separation.
5
+ * For self-hosted / open-source: Single-tenant mode uses a default org with no limits.
6
+ *
7
+ * - Data isolation (each org sees only their data)
8
+ * - Resource quotas (CPU, memory, API calls per org)
9
+ * - Billing boundaries
10
+ * - Network isolation between agents from different orgs
11
+ *
12
+ * When running single-tenant (open-source), call:
13
+ * tenants.createDefaultOrg() → creates one org with self-hosted (unlimited) plan
14
+ */
15
+
16
+ // ─── Types ──────────────────────────────────────────────
17
+
18
+ export interface Organization {
19
+ id: string;
20
+ name: string;
21
+ slug: string; // URL-safe identifier
22
+ plan: OrgPlan;
23
+
24
+ // Limits
25
+ limits: OrgLimits;
26
+
27
+ // Usage (current period)
28
+ usage: OrgUsage;
29
+
30
+ // Auth
31
+ ssoConfig?: SSOConfig;
32
+ allowedDomains: string[]; // Auto-join for these email domains
33
+
34
+ // Billing
35
+ billing?: {
36
+ customerId: string; // Stripe/billing provider ID
37
+ subscriptionId?: string;
38
+ currentPeriodEnd: string;
39
+ };
40
+
41
+ // Settings
42
+ settings: {
43
+ defaultModel: string;
44
+ defaultPermissionProfile: string;
45
+ requireApprovalForDeploy: boolean;
46
+ auditRetentionDays: number;
47
+ dataRegion: string; // Where data is stored
48
+ customDomain?: string; // company.agenticmail.cloud or custom
49
+ };
50
+
51
+ createdAt: string;
52
+ updatedAt: string;
53
+ }
54
+
55
+ export type OrgPlan = 'free' | 'team' | 'enterprise' | 'self-hosted';
56
+
57
+ export interface OrgLimits {
58
+ maxAgents: number; // Free: 3, Team: 25, Enterprise: unlimited
59
+ maxUsers: number; // Free: 5, Team: 50, Enterprise: unlimited
60
+ maxKnowledgeBases: number;
61
+ maxDocumentsPerKB: number;
62
+ maxStorageMb: number;
63
+ tokenBudgetMonthly: number; // 0 = unlimited
64
+ apiCallsPerMinute: number;
65
+ deploymentTargets: string[]; // Which targets are allowed
66
+ features: OrgFeature[];
67
+ }
68
+
69
+ export type OrgFeature =
70
+ | 'custom-skills' // Can create custom skills
71
+ | 'sso' // SAML/OIDC SSO
72
+ | 'audit-export' // Export audit logs
73
+ | 'api-access' // REST API keys
74
+ | 'webhooks' // Webhook integrations
75
+ | 'custom-domain' // Custom domain
76
+ | 'priority-support'
77
+ | 'sla' // SLA guarantees
78
+ | 'data-residency' // Choose data region
79
+ | 'ip-allowlist' // IP-based access control
80
+ | 'approval-workflows'
81
+ | 'knowledge-base'
82
+ | 'multi-deploy' // Deploy to multiple targets
83
+ | 'white-label'; // Remove AgenticMail branding
84
+
85
+ export interface OrgUsage {
86
+ agents: number;
87
+ users: number;
88
+ tokensThisMonth: number;
89
+ costThisMonth: number;
90
+ storageMb: number;
91
+ apiCallsToday: number;
92
+ deploymentsThisMonth: number;
93
+ lastUpdated: string;
94
+ }
95
+
96
+ export interface SSOConfig {
97
+ provider: 'saml' | 'oidc';
98
+ issuerUrl: string;
99
+ clientId?: string;
100
+ clientSecret?: string;
101
+ certificate?: string;
102
+ metadataUrl?: string;
103
+ allowedGroups?: string[]; // Only these IdP groups can access
104
+ roleMapping?: Record<string, string>; // IdP group → org role
105
+ }
106
+
107
+ // ─── Plan Definitions ───────────────────────────────────
108
+
109
+ export const PLAN_LIMITS: Record<OrgPlan, OrgLimits> = {
110
+ free: {
111
+ maxAgents: 3,
112
+ maxUsers: 5,
113
+ maxKnowledgeBases: 1,
114
+ maxDocumentsPerKB: 10,
115
+ maxStorageMb: 100,
116
+ tokenBudgetMonthly: 1_000_000,
117
+ apiCallsPerMinute: 30,
118
+ deploymentTargets: ['docker', 'local'],
119
+ features: ['knowledge-base'],
120
+ },
121
+ team: {
122
+ maxAgents: 25,
123
+ maxUsers: 50,
124
+ maxKnowledgeBases: 10,
125
+ maxDocumentsPerKB: 100,
126
+ maxStorageMb: 5_000,
127
+ tokenBudgetMonthly: 10_000_000,
128
+ apiCallsPerMinute: 120,
129
+ deploymentTargets: ['docker', 'vps', 'fly', 'railway', 'local'],
130
+ features: ['knowledge-base', 'api-access', 'webhooks', 'approval-workflows', 'sso', 'audit-export', 'custom-skills'],
131
+ },
132
+ enterprise: {
133
+ maxAgents: 999_999,
134
+ maxUsers: 999_999,
135
+ maxKnowledgeBases: 999,
136
+ maxDocumentsPerKB: 10_000,
137
+ maxStorageMb: 100_000,
138
+ tokenBudgetMonthly: 0, // Unlimited
139
+ apiCallsPerMinute: 600,
140
+ deploymentTargets: ['docker', 'vps', 'fly', 'railway', 'aws', 'gcp', 'azure', 'local'],
141
+ features: ['knowledge-base', 'api-access', 'webhooks', 'approval-workflows', 'sso', 'audit-export', 'custom-skills', 'custom-domain', 'priority-support', 'sla', 'data-residency', 'ip-allowlist', 'multi-deploy', 'white-label'],
142
+ },
143
+ 'self-hosted': {
144
+ maxAgents: 999_999,
145
+ maxUsers: 999_999,
146
+ maxKnowledgeBases: 999,
147
+ maxDocumentsPerKB: 10_000,
148
+ maxStorageMb: 999_999,
149
+ tokenBudgetMonthly: 0,
150
+ apiCallsPerMinute: 999,
151
+ deploymentTargets: ['docker', 'vps', 'fly', 'railway', 'aws', 'gcp', 'azure', 'local'],
152
+ features: ['knowledge-base', 'api-access', 'webhooks', 'approval-workflows', 'sso', 'audit-export', 'custom-skills', 'custom-domain', 'data-residency', 'ip-allowlist', 'multi-deploy', 'white-label'],
153
+ },
154
+ };
155
+
156
+ // ─── Tenant Manager ─────────────────────────────────────
157
+
158
+ export class TenantManager {
159
+ private orgs = new Map<string, Organization>();
160
+
161
+ /**
162
+ * Create a new organization
163
+ */
164
+ createOrg(opts: {
165
+ name: string;
166
+ slug: string;
167
+ plan: OrgPlan;
168
+ adminEmail: string;
169
+ settings?: Partial<Organization['settings']>;
170
+ }): Organization {
171
+ if (this.orgs.has(opts.slug)) {
172
+ throw new Error(`Organization slug "${opts.slug}" already exists`);
173
+ }
174
+
175
+ const limits = { ...PLAN_LIMITS[opts.plan] };
176
+
177
+ const org: Organization = {
178
+ id: crypto.randomUUID(),
179
+ name: opts.name,
180
+ slug: opts.slug,
181
+ plan: opts.plan,
182
+ limits,
183
+ usage: {
184
+ agents: 0, users: 1, tokensThisMonth: 0, costThisMonth: 0,
185
+ storageMb: 0, apiCallsToday: 0, deploymentsThisMonth: 0,
186
+ lastUpdated: new Date().toISOString(),
187
+ },
188
+ allowedDomains: [],
189
+ settings: {
190
+ defaultModel: 'anthropic/claude-sonnet-4-20250514',
191
+ defaultPermissionProfile: 'Customer Support Agent',
192
+ requireApprovalForDeploy: true,
193
+ auditRetentionDays: opts.plan === 'free' ? 30 : opts.plan === 'team' ? 90 : 365,
194
+ dataRegion: 'us-east-1',
195
+ ...opts.settings,
196
+ },
197
+ createdAt: new Date().toISOString(),
198
+ updatedAt: new Date().toISOString(),
199
+ };
200
+
201
+ this.orgs.set(org.id, org);
202
+ return org;
203
+ }
204
+
205
+ /**
206
+ * Check if an org can perform an action (within limits)
207
+ */
208
+ checkLimit(orgId: string, resource: keyof OrgLimits, currentCount?: number): {
209
+ allowed: boolean;
210
+ limit: number;
211
+ current: number;
212
+ remaining: number;
213
+ } {
214
+ const org = this.orgs.get(orgId);
215
+ if (!org) throw new Error(`Organization ${orgId} not found`);
216
+
217
+ const limit = org.limits[resource];
218
+ if (typeof limit !== 'number') return { allowed: true, limit: 0, current: 0, remaining: 0 };
219
+
220
+ let current = currentCount ?? 0;
221
+ if (!currentCount) {
222
+ // Infer current from usage
223
+ switch (resource) {
224
+ case 'maxAgents': current = org.usage.agents; break;
225
+ case 'maxUsers': current = org.usage.users; break;
226
+ case 'tokenBudgetMonthly': current = org.usage.tokensThisMonth; break;
227
+ case 'maxStorageMb': current = org.usage.storageMb; break;
228
+ }
229
+ }
230
+
231
+ const remaining = Math.max(0, (limit as number) - current);
232
+ return {
233
+ allowed: limit === 0 || current < (limit as number), // 0 = unlimited
234
+ limit: limit as number,
235
+ current,
236
+ remaining,
237
+ };
238
+ }
239
+
240
+ /**
241
+ * Check if an org has a specific feature
242
+ */
243
+ hasFeature(orgId: string, feature: OrgFeature): boolean {
244
+ const org = this.orgs.get(orgId);
245
+ if (!org) return false;
246
+ return org.limits.features.includes(feature);
247
+ }
248
+
249
+ /**
250
+ * Check if a deployment target is allowed for this org's plan
251
+ */
252
+ canDeployTo(orgId: string, target: string): boolean {
253
+ const org = this.orgs.get(orgId);
254
+ if (!org) return false;
255
+ return org.limits.deploymentTargets.includes(target);
256
+ }
257
+
258
+ /**
259
+ * Record usage (tokens, API calls, etc.)
260
+ */
261
+ recordUsage(orgId: string, update: Partial<OrgUsage>) {
262
+ const org = this.orgs.get(orgId);
263
+ if (!org) return;
264
+
265
+ if (update.tokensThisMonth) org.usage.tokensThisMonth += update.tokensThisMonth;
266
+ if (update.costThisMonth) org.usage.costThisMonth += update.costThisMonth;
267
+ if (update.apiCallsToday) org.usage.apiCallsToday += update.apiCallsToday;
268
+ if (update.storageMb) org.usage.storageMb = update.storageMb;
269
+ if (update.deploymentsThisMonth) org.usage.deploymentsThisMonth += update.deploymentsThisMonth;
270
+ org.usage.lastUpdated = new Date().toISOString();
271
+ }
272
+
273
+ /**
274
+ * Upgrade/downgrade org plan
275
+ */
276
+ changePlan(orgId: string, newPlan: OrgPlan): Organization {
277
+ const org = this.orgs.get(orgId);
278
+ if (!org) throw new Error(`Organization ${orgId} not found`);
279
+
280
+ org.plan = newPlan;
281
+ org.limits = { ...PLAN_LIMITS[newPlan] };
282
+ org.updatedAt = new Date().toISOString();
283
+
284
+ // Adjust retention based on plan
285
+ org.settings.auditRetentionDays = newPlan === 'free' ? 30 : newPlan === 'team' ? 90 : 365;
286
+
287
+ return org;
288
+ }
289
+
290
+ getOrg(id: string): Organization | undefined {
291
+ return this.orgs.get(id);
292
+ }
293
+
294
+ getOrgBySlug(slug: string): Organization | undefined {
295
+ return Array.from(this.orgs.values()).find(o => o.slug === slug);
296
+ }
297
+
298
+ listOrgs(): Organization[] {
299
+ return Array.from(this.orgs.values());
300
+ }
301
+
302
+ /**
303
+ * Single-tenant mode: create default org with unlimited (self-hosted) plan.
304
+ * For open-source / self-hosted deployments that don't need multi-tenancy.
305
+ */
306
+ createDefaultOrg(name: string = 'Default'): Organization {
307
+ const existing = this.getOrgBySlug('default');
308
+ if (existing) return existing;
309
+ return this.createOrg({
310
+ name,
311
+ slug: 'default',
312
+ plan: 'self-hosted',
313
+ adminEmail: 'admin@localhost',
314
+ settings: { requireApprovalForDeploy: false },
315
+ });
316
+ }
317
+
318
+ /**
319
+ * Is this a single-tenant deployment?
320
+ */
321
+ isSingleTenant(): boolean {
322
+ const orgs = this.listOrgs();
323
+ return orgs.length === 1 && orgs[0].slug === 'default';
324
+ }
325
+
326
+ /**
327
+ * Reset daily counters for all orgs
328
+ */
329
+ resetDailyCounters() {
330
+ for (const org of this.orgs.values()) {
331
+ org.usage.apiCallsToday = 0;
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Reset monthly counters for all orgs
337
+ */
338
+ resetMonthlyCounters() {
339
+ for (const org of this.orgs.values()) {
340
+ org.usage.tokensThisMonth = 0;
341
+ org.usage.costThisMonth = 0;
342
+ org.usage.deploymentsThisMonth = 0;
343
+ }
344
+ }
345
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Tool Catalog — Exact mapping of real OpenClaw + AgenticMail tools
3
+ *
4
+ * Every tool ID here matches the ACTUAL registered tool name in OpenClaw.
5
+ * Sourced from:
6
+ * - OpenClaw core tools (read, write, edit, exec, web_search, etc.)
7
+ * - AgenticMail plugin tools (agenticmail_send, agenticmail_reply, etc.)
8
+ * - OpenClaw plugin system (browser, canvas, nodes, cron, etc.)
9
+ *
10
+ * This is the single source of truth for the permission engine.
11
+ */
12
+
13
+ import type { ToolDefinition, SkillCategory, RiskLevel, SideEffect } from './skills.js';
14
+
15
+ // ─── Core OpenClaw Tools ────────────────────────────────
16
+
17
+ export const OPENCLAW_CORE_TOOLS: ToolDefinition[] = [
18
+ // File system
19
+ { id: 'read', name: 'Read File', description: 'Read file contents (text and images)', category: 'read', risk: 'low', skillId: 'files', sideEffects: [] },
20
+ { id: 'write', name: 'Write File', description: 'Create or overwrite files', category: 'write', risk: 'medium', skillId: 'files', sideEffects: ['modifies-files'] },
21
+ { id: 'edit', name: 'Edit File', description: 'Make precise edits to files', category: 'write', risk: 'medium', skillId: 'files', sideEffects: ['modifies-files'] },
22
+
23
+ // Execution
24
+ { id: 'exec', name: 'Shell Command', description: 'Execute shell commands', category: 'execute', risk: 'critical', skillId: 'exec', sideEffects: ['runs-code', 'modifies-files', 'network-request'] },
25
+ { id: 'process', name: 'Process Manager', description: 'Manage running exec sessions', category: 'execute', risk: 'high', skillId: 'exec', sideEffects: ['runs-code'] },
26
+
27
+ // Web
28
+ { id: 'web_search', name: 'Web Search', description: 'Search the web via Brave Search API', category: 'read', risk: 'low', skillId: 'web-search', sideEffects: ['network-request'] },
29
+ { id: 'web_fetch', name: 'Web Fetch', description: 'Fetch and extract content from URLs', category: 'read', risk: 'low', skillId: 'web-fetch', sideEffects: ['network-request'] },
30
+
31
+ // Browser
32
+ { id: 'browser', name: 'Browser Control', description: 'Automate web browsers', category: 'execute', risk: 'high', skillId: 'browser', sideEffects: ['network-request', 'runs-code'] },
33
+
34
+ // Canvas
35
+ { id: 'canvas', name: 'Canvas', description: 'Present/eval/snapshot rendered UI', category: 'read', risk: 'low', skillId: 'canvas', sideEffects: [] },
36
+
37
+ // Nodes
38
+ { id: 'nodes', name: 'Node Control', description: 'Control paired devices', category: 'execute', risk: 'high', skillId: 'nodes', sideEffects: ['controls-device'] },
39
+
40
+ // Cron
41
+ { id: 'cron', name: 'Cron Jobs', description: 'Schedule tasks and reminders', category: 'write', risk: 'medium', skillId: 'cron', sideEffects: [] },
42
+
43
+ // Messaging
44
+ { id: 'message', name: 'Send Message', description: 'Send messages via channels', category: 'communicate', risk: 'high', skillId: 'messaging', sideEffects: ['sends-message'] },
45
+
46
+ // Gateway
47
+ { id: 'gateway', name: 'Gateway Control', description: 'Restart, configure, update OpenClaw', category: 'execute', risk: 'critical', skillId: 'gateway', sideEffects: ['runs-code'] },
48
+
49
+ // Sessions / Sub-agents
50
+ { id: 'agents_list', name: 'List Agents', description: 'List agent IDs for spawning', category: 'read', risk: 'low', skillId: 'sessions', sideEffects: [] },
51
+ { id: 'sessions_list', name: 'List Sessions', description: 'List active sessions', category: 'read', risk: 'low', skillId: 'sessions', sideEffects: [] },
52
+ { id: 'sessions_history', name: 'Session History', description: 'Fetch message history', category: 'read', risk: 'low', skillId: 'sessions', sideEffects: [] },
53
+ { id: 'sessions_send', name: 'Send to Session', description: 'Send message to another session', category: 'communicate', risk: 'medium', skillId: 'sessions', sideEffects: ['sends-message'] },
54
+ { id: 'sessions_spawn', name: 'Spawn Sub-Agent', description: 'Spawn a background sub-agent', category: 'execute', risk: 'medium', skillId: 'sessions', sideEffects: [] },
55
+ { id: 'subagents', name: 'Sub-Agent Control', description: 'List, steer, or kill sub-agents', category: 'execute', risk: 'medium', skillId: 'sessions', sideEffects: [] },
56
+ { id: 'session_status', name: 'Session Status', description: 'Show session usage and status', category: 'read', risk: 'low', skillId: 'sessions', sideEffects: [] },
57
+
58
+ // Image
59
+ { id: 'image', name: 'Image Analysis', description: 'Analyze images with vision model', category: 'read', risk: 'low', skillId: 'media', sideEffects: [] },
60
+
61
+ // TTS
62
+ { id: 'tts', name: 'Text-to-Speech', description: 'Convert text to speech audio', category: 'write', risk: 'low', skillId: 'media', sideEffects: [] },
63
+
64
+ // Memory
65
+ { id: 'memory_search', name: 'Memory Search', description: 'Search agent memory files', category: 'read', risk: 'low', skillId: 'memory', sideEffects: [] },
66
+ { id: 'memory_get', name: 'Memory Get', description: 'Read memory file snippets', category: 'read', risk: 'low', skillId: 'memory', sideEffects: [] },
67
+ ];
68
+
69
+ // ─── AgenticMail Tools (all 63) ─────────────────────────
70
+
71
+ export const AGENTICMAIL_TOOLS: ToolDefinition[] = [
72
+ // Core email
73
+ { id: 'agenticmail_inbox', name: 'Inbox', description: 'List recent emails', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
74
+ { id: 'agenticmail_read', name: 'Read Email', description: 'Read a specific email by UID', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
75
+ { id: 'agenticmail_send', name: 'Send Email', description: 'Send an email', category: 'communicate', risk: 'high', skillId: 'agenticmail', sideEffects: ['sends-email'] },
76
+ { id: 'agenticmail_reply', name: 'Reply to Email', description: 'Reply to an email', category: 'communicate', risk: 'high', skillId: 'agenticmail', sideEffects: ['sends-email'] },
77
+ { id: 'agenticmail_forward', name: 'Forward Email', description: 'Forward an email', category: 'communicate', risk: 'high', skillId: 'agenticmail', sideEffects: ['sends-email'] },
78
+ { id: 'agenticmail_search', name: 'Search Email', description: 'Search emails', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
79
+ { id: 'agenticmail_delete', name: 'Delete Email', description: 'Delete an email', category: 'destroy', risk: 'medium', skillId: 'agenticmail', sideEffects: ['deletes-data'] },
80
+ { id: 'agenticmail_move', name: 'Move Email', description: 'Move email to folder', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
81
+ { id: 'agenticmail_mark_read', name: 'Mark Read', description: 'Mark email as read', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
82
+ { id: 'agenticmail_mark_unread', name: 'Mark Unread', description: 'Mark email as unread', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
83
+ { id: 'agenticmail_digest', name: 'Inbox Digest', description: 'Get compact inbox digest', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
84
+ { id: 'agenticmail_list_folder', name: 'List Folder', description: 'List messages in a folder', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
85
+ { id: 'agenticmail_folders', name: 'List Folders', description: 'List all mail folders', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
86
+ { id: 'agenticmail_create_folder', name: 'Create Folder', description: 'Create a mail folder', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
87
+ { id: 'agenticmail_import_relay', name: 'Import Relay', description: 'Import email from Gmail/Outlook', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
88
+
89
+ // Batch operations
90
+ { id: 'agenticmail_batch_read', name: 'Batch Read', description: 'Read multiple emails', category: 'read', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
91
+ { id: 'agenticmail_batch_delete', name: 'Batch Delete', description: 'Delete multiple emails', category: 'destroy', risk: 'medium', skillId: 'agenticmail', sideEffects: ['deletes-data'] },
92
+ { id: 'agenticmail_batch_move', name: 'Batch Move', description: 'Move multiple emails', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
93
+ { id: 'agenticmail_batch_mark_read', name: 'Batch Mark Read', description: 'Mark multiple as read', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
94
+ { id: 'agenticmail_batch_mark_unread', name: 'Batch Mark Unread', description: 'Mark multiple as unread', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
95
+
96
+ // Agent coordination
97
+ { id: 'agenticmail_call_agent', name: 'Call Agent', description: 'Call another agent with a task', category: 'execute', risk: 'medium', skillId: 'agenticmail-coordination', sideEffects: [] },
98
+ { id: 'agenticmail_message_agent', name: 'Message Agent', description: 'Send message to another agent', category: 'communicate', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: ['sends-message'] },
99
+ { id: 'agenticmail_list_agents', name: 'List Agents', description: 'List available agents', category: 'read', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
100
+ { id: 'agenticmail_check_messages', name: 'Check Messages', description: 'Check for unread messages', category: 'read', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
101
+ { id: 'agenticmail_check_tasks', name: 'Check Tasks', description: 'Check pending tasks', category: 'read', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
102
+ { id: 'agenticmail_claim_task', name: 'Claim Task', description: 'Claim a pending task', category: 'write', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
103
+ { id: 'agenticmail_complete_task', name: 'Complete Task', description: 'Complete a claimed task', category: 'write', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
104
+ { id: 'agenticmail_submit_result', name: 'Submit Result', description: 'Submit task result', category: 'write', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
105
+ { id: 'agenticmail_wait_for_email', name: 'Wait for Email', description: 'Wait for new email (SSE)', category: 'read', risk: 'low', skillId: 'agenticmail-coordination', sideEffects: [] },
106
+
107
+ // Account management
108
+ { id: 'agenticmail_create_account', name: 'Create Account', description: 'Create agent email account', category: 'write', risk: 'high', skillId: 'agenticmail-admin', sideEffects: [] },
109
+ { id: 'agenticmail_delete_agent', name: 'Delete Agent', description: 'Delete agent account', category: 'destroy', risk: 'critical', skillId: 'agenticmail-admin', sideEffects: ['deletes-data'] },
110
+ { id: 'agenticmail_cleanup', name: 'Cleanup Agents', description: 'Remove inactive agents', category: 'destroy', risk: 'high', skillId: 'agenticmail-admin', sideEffects: ['deletes-data'] },
111
+ { id: 'agenticmail_deletion_reports', name: 'Deletion Reports', description: 'List deletion reports', category: 'read', risk: 'low', skillId: 'agenticmail-admin', sideEffects: [] },
112
+ { id: 'agenticmail_whoami', name: 'Who Am I', description: 'Get agent account info', category: 'read', risk: 'low', skillId: 'agenticmail-admin', sideEffects: [] },
113
+ { id: 'agenticmail_update_metadata', name: 'Update Metadata', description: 'Update agent metadata', category: 'write', risk: 'low', skillId: 'agenticmail-admin', sideEffects: [] },
114
+ { id: 'agenticmail_status', name: 'Server Status', description: 'Check server health', category: 'read', risk: 'low', skillId: 'agenticmail-admin', sideEffects: [] },
115
+ { id: 'agenticmail_pending_emails', name: 'Pending Emails', description: 'Check blocked outbound emails', category: 'read', risk: 'low', skillId: 'agenticmail-admin', sideEffects: [] },
116
+
117
+ // Organization
118
+ { id: 'agenticmail_contacts', name: 'Contacts', description: 'Manage contacts', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
119
+ { id: 'agenticmail_tags', name: 'Tags', description: 'Manage email tags/labels', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
120
+ { id: 'agenticmail_signatures', name: 'Signatures', description: 'Manage email signatures', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
121
+ { id: 'agenticmail_templates', name: 'Templates', description: 'Manage email templates', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
122
+ { id: 'agenticmail_template_send', name: 'Send Template', description: 'Send email from template', category: 'communicate', risk: 'high', skillId: 'agenticmail', sideEffects: ['sends-email'] },
123
+ { id: 'agenticmail_rules', name: 'Email Rules', description: 'Manage auto-processing rules', category: 'write', risk: 'medium', skillId: 'agenticmail', sideEffects: [] },
124
+ { id: 'agenticmail_spam', name: 'Spam Management', description: 'Manage spam folder', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
125
+ { id: 'agenticmail_drafts', name: 'Drafts', description: 'Manage email drafts', category: 'write', risk: 'low', skillId: 'agenticmail', sideEffects: [] },
126
+ { id: 'agenticmail_schedule', name: 'Schedule Email', description: 'Schedule emails for later', category: 'communicate', risk: 'medium', skillId: 'agenticmail', sideEffects: ['sends-email'] },
127
+
128
+ // Setup (admin only)
129
+ { id: 'agenticmail_setup_relay', name: 'Setup Relay', description: 'Configure Gmail/Outlook relay', category: 'write', risk: 'critical', skillId: 'agenticmail-setup', sideEffects: [] },
130
+ { id: 'agenticmail_setup_domain', name: 'Setup Domain', description: 'Configure custom domain', category: 'write', risk: 'critical', skillId: 'agenticmail-setup', sideEffects: [] },
131
+ { id: 'agenticmail_setup_guide', name: 'Setup Guide', description: 'Email setup comparison', category: 'read', risk: 'low', skillId: 'agenticmail-setup', sideEffects: [] },
132
+ { id: 'agenticmail_setup_gmail_alias', name: 'Gmail Alias', description: 'Add Gmail send-as alias', category: 'read', risk: 'low', skillId: 'agenticmail-setup', sideEffects: [] },
133
+ { id: 'agenticmail_setup_payment', name: 'Setup Payment', description: 'Add Cloudflare payment', category: 'read', risk: 'low', skillId: 'agenticmail-setup', sideEffects: [] },
134
+ { id: 'agenticmail_purchase_domain', name: 'Purchase Domain', description: 'Search available domains', category: 'read', risk: 'low', skillId: 'agenticmail-setup', sideEffects: [] },
135
+ { id: 'agenticmail_test_email', name: 'Test Email', description: 'Send test email', category: 'communicate', risk: 'low', skillId: 'agenticmail-setup', sideEffects: ['sends-email'] },
136
+ { id: 'agenticmail_gateway_status', name: 'Gateway Status', description: 'Check email gateway', category: 'read', risk: 'low', skillId: 'agenticmail-setup', sideEffects: [] },
137
+
138
+ // SMS
139
+ { id: 'agenticmail_sms_send', name: 'Send SMS', description: 'Send SMS via Google Voice', category: 'communicate', risk: 'high', skillId: 'agenticmail-sms', sideEffects: ['sends-sms'] },
140
+ { id: 'agenticmail_sms_messages', name: 'SMS Messages', description: 'List SMS messages', category: 'read', risk: 'low', skillId: 'agenticmail-sms', sideEffects: [] },
141
+ { id: 'agenticmail_sms_check_code', name: 'Check SMS Code', description: 'Check for verification codes', category: 'read', risk: 'low', skillId: 'agenticmail-sms', sideEffects: [] },
142
+ { id: 'agenticmail_sms_read_voice', name: 'Read Voice SMS', description: 'Read SMS from Google Voice', category: 'read', risk: 'low', skillId: 'agenticmail-sms', sideEffects: [] },
143
+ { id: 'agenticmail_sms_record', name: 'Record SMS', description: 'Save SMS to database', category: 'write', risk: 'low', skillId: 'agenticmail-sms', sideEffects: [] },
144
+ { id: 'agenticmail_sms_parse_email', name: 'Parse SMS Email', description: 'Parse SMS from forwarded email', category: 'read', risk: 'low', skillId: 'agenticmail-sms', sideEffects: [] },
145
+ { id: 'agenticmail_sms_setup', name: 'SMS Setup', description: 'Configure Google Voice SMS', category: 'write', risk: 'medium', skillId: 'agenticmail-sms', sideEffects: [] },
146
+ { id: 'agenticmail_sms_config', name: 'SMS Config', description: 'Get SMS configuration', category: 'read', risk: 'low', skillId: 'agenticmail-sms', sideEffects: [] },
147
+ ];
148
+
149
+ /**
150
+ * Complete tool catalog — all tools from OpenClaw + AgenticMail
151
+ */
152
+ export const ALL_TOOLS: ToolDefinition[] = [...OPENCLAW_CORE_TOOLS, ...AGENTICMAIL_TOOLS];
153
+
154
+ /**
155
+ * Tool ID → ToolDefinition lookup
156
+ */
157
+ export const TOOL_INDEX: Map<string, ToolDefinition> = new Map(ALL_TOOLS.map(t => [t.id, t]));
158
+
159
+ /**
160
+ * Skill ID → Tool IDs mapping
161
+ */
162
+ export function getToolsBySkill(): Map<string, string[]> {
163
+ const map = new Map<string, string[]>();
164
+ for (const tool of ALL_TOOLS) {
165
+ const list = map.get(tool.skillId) || [];
166
+ list.push(tool.id);
167
+ map.set(tool.skillId, list);
168
+ }
169
+ return map;
170
+ }
171
+
172
+ /**
173
+ * Generate OpenClaw-compatible tools.allow / tools.deny config
174
+ */
175
+ export function generateOpenClawToolPolicy(allowedToolIds: string[], blockedToolIds: string[]): {
176
+ 'tools.allow'?: string[];
177
+ 'tools.deny'?: string[];
178
+ } {
179
+ const config: any = {};
180
+ // OpenClaw uses tools.allow as allowlist and tools.deny as denylist
181
+ // If allowlist is set, only those tools are available
182
+ // If denylist is set, all tools except those are available
183
+ if (blockedToolIds.length > 0 && allowedToolIds.length === 0) {
184
+ config['tools.deny'] = blockedToolIds;
185
+ } else if (allowedToolIds.length > 0) {
186
+ config['tools.allow'] = allowedToolIds;
187
+ }
188
+ return config;
189
+ }
package/src/index.ts ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * AgenticMail Enterprise
3
+ *
4
+ * Cloud-hosted AI agent identity, email, auth & compliance for organizations.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { createAdapter, createServer } from '@agenticmail/enterprise';
9
+ *
10
+ * const db = await createAdapter({ type: 'postgres', connectionString: '...' });
11
+ * await db.migrate();
12
+ *
13
+ * const server = createServer({ port: 3000, db, jwtSecret: '...' });
14
+ * await server.start();
15
+ * ```
16
+ */
17
+
18
+ // Database
19
+ export { DatabaseAdapter } from './db/adapter.js';
20
+ export type {
21
+ DatabaseConfig, DatabaseType,
22
+ Agent, AgentInput, User, UserInput,
23
+ AuditEvent, AuditFilters, ApiKey, ApiKeyInput,
24
+ EmailRule, RetentionPolicy, CompanySettings,
25
+ } from './db/adapter.js';
26
+ export { createAdapter, getSupportedDatabases } from './db/factory.js';
27
+
28
+ // Server
29
+ export { createServer } from './server.js';
30
+ export type { ServerConfig, ServerInstance } from './server.js';
31
+
32
+ // Deploy
33
+ export { deployToCloud, generateDockerCompose, generateFlyToml } from './deploy/managed.js';
34
+
35
+ // Routes (for custom server setups)
36
+ export { createAdminRoutes } from './admin/routes.js';
37
+ export { createAuthRoutes } from './auth/routes.js';
38
+
39
+ // Middleware (for extending the server)
40
+ export {
41
+ requestIdMiddleware,
42
+ requestLogger,
43
+ rateLimiter,
44
+ securityHeaders,
45
+ errorHandler,
46
+ auditLogger,
47
+ requireRole,
48
+ validate,
49
+ ValidationError,
50
+ } from './middleware/index.js';
51
+
52
+ // Engine (managed agent deployment platform)
53
+ export * from './engine/index.js';
54
+
55
+ // Resilience (for custom integrations)
56
+ export {
57
+ withRetry,
58
+ CircuitBreaker,
59
+ RateLimiter,
60
+ KeyedRateLimiter,
61
+ HealthMonitor,
62
+ CircuitOpenError,
63
+ } from './lib/resilience.js';
64
+ export type { RetryOptions, CircuitBreakerOptions, RateLimiterOptions, HealthCheckOptions } from './lib/resilience.js';