@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.
- package/ARCHITECTURE.md +183 -0
- package/agenticmail-enterprise.db +0 -0
- package/dashboards/README.md +120 -0
- package/dashboards/dotnet/Program.cs +261 -0
- package/dashboards/express/app.js +146 -0
- package/dashboards/go/main.go +513 -0
- package/dashboards/html/index.html +535 -0
- package/dashboards/java/AgenticMailDashboard.java +376 -0
- package/dashboards/php/index.php +414 -0
- package/dashboards/python/app.py +273 -0
- package/dashboards/ruby/app.rb +195 -0
- package/dist/chunk-77IDQJL3.js +7 -0
- package/dist/chunk-7RGCCHIT.js +115 -0
- package/dist/chunk-DXNKR3TG.js +1355 -0
- package/dist/chunk-IQWA44WT.js +970 -0
- package/dist/chunk-LCUZGIDH.js +965 -0
- package/dist/chunk-N2JVTNNJ.js +2553 -0
- package/dist/chunk-O462UJBH.js +363 -0
- package/dist/chunk-PNKVD2UK.js +26 -0
- package/dist/cli.js +218 -0
- package/dist/dashboard/index.html +558 -0
- package/dist/db-adapter-DEWEFNIV.js +7 -0
- package/dist/dynamodb-CCGL2E77.js +426 -0
- package/dist/engine/index.js +1261 -0
- package/dist/index.js +522 -0
- package/dist/mongodb-ODTXIVPV.js +319 -0
- package/dist/mysql-RM3S2FV5.js +521 -0
- package/dist/postgres-LN7A6MGQ.js +518 -0
- package/dist/routes-2JEPIIKC.js +441 -0
- package/dist/routes-74ZLKJKP.js +399 -0
- package/dist/server.js +7 -0
- package/dist/sqlite-3K5YOZ4K.js +439 -0
- package/dist/turso-LDWODSDI.js +442 -0
- package/package.json +49 -0
- package/src/admin/routes.ts +331 -0
- package/src/auth/routes.ts +130 -0
- package/src/cli.ts +260 -0
- package/src/dashboard/index.html +558 -0
- package/src/db/adapter.ts +230 -0
- package/src/db/dynamodb.ts +456 -0
- package/src/db/factory.ts +51 -0
- package/src/db/mongodb.ts +360 -0
- package/src/db/mysql.ts +472 -0
- package/src/db/postgres.ts +479 -0
- package/src/db/sql-schema.ts +123 -0
- package/src/db/sqlite.ts +391 -0
- package/src/db/turso.ts +411 -0
- package/src/deploy/fly.ts +368 -0
- package/src/deploy/managed.ts +213 -0
- package/src/engine/activity.ts +474 -0
- package/src/engine/agent-config.ts +429 -0
- package/src/engine/agenticmail-bridge.ts +296 -0
- package/src/engine/approvals.ts +278 -0
- package/src/engine/db-adapter.ts +682 -0
- package/src/engine/db-schema.ts +335 -0
- package/src/engine/deployer.ts +595 -0
- package/src/engine/index.ts +134 -0
- package/src/engine/knowledge.ts +486 -0
- package/src/engine/lifecycle.ts +635 -0
- package/src/engine/openclaw-hook.ts +371 -0
- package/src/engine/routes.ts +528 -0
- package/src/engine/skills.ts +473 -0
- package/src/engine/tenant.ts +345 -0
- package/src/engine/tool-catalog.ts +189 -0
- package/src/index.ts +64 -0
- package/src/lib/resilience.ts +326 -0
- package/src/middleware/index.ts +286 -0
- package/src/server.ts +310 -0
- 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';
|