@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,429 @@
1
+ /**
2
+ * Agent Configuration Builder
3
+ *
4
+ * Generates the full OpenClaw workspace config for a deployed agent:
5
+ * SOUL.md, USER.md, AGENTS.md, HEARTBEAT.md, gateway config, etc.
6
+ * Everything needed to spin up a fully configured agent from the admin dashboard.
7
+ */
8
+
9
+ // ─── Types ──────────────────────────────────────────────
10
+
11
+ export interface AgentConfig {
12
+ id: string;
13
+ name: string;
14
+ displayName: string; // Human-facing name
15
+
16
+ // Identity
17
+ identity: {
18
+ personality: string; // SOUL.md content — who the agent IS
19
+ role: string; // e.g. "Customer Support Lead"
20
+ tone: 'formal' | 'casual' | 'professional' | 'friendly' | 'custom';
21
+ customTone?: string;
22
+ language: string; // Primary language (e.g. "en", "es", "fr")
23
+ avatar?: string; // URL or base64
24
+ };
25
+
26
+ // Model
27
+ model: {
28
+ provider: 'anthropic' | 'openai' | 'google' | 'custom';
29
+ modelId: string; // e.g. "claude-sonnet-4-20250514", "gpt-4o"
30
+ thinkingLevel: 'off' | 'low' | 'medium' | 'high';
31
+ temperature?: number;
32
+ maxTokens?: number;
33
+ fallbackModelId?: string; // Fallback if primary is down
34
+ };
35
+
36
+ // Communication channels
37
+ channels: {
38
+ enabled: ChannelConfig[];
39
+ primaryChannel: string; // Which channel is default
40
+ };
41
+
42
+ // Email
43
+ email: {
44
+ enabled: boolean;
45
+ provider: 'relay' | 'domain' | 'none';
46
+ address?: string; // e.g. "support@acme.com"
47
+ relayConfig?: { email: string; appPassword: string; provider: 'gmail' | 'outlook' };
48
+ domainConfig?: { domain: string; cloudflareToken: string };
49
+ signature?: string;
50
+ autoReply?: { enabled: boolean; message: string; afterHours: boolean };
51
+ };
52
+
53
+ // Workspace
54
+ workspace: {
55
+ persistentMemory: boolean; // Keep memory across restarts
56
+ memoryMaxSizeMb: number;
57
+ workingDirectory: string; // Where the agent's files live
58
+ sharedDirectories: string[]; // Directories shared between agents
59
+ gitEnabled: boolean; // Auto-commit workspace changes
60
+ };
61
+
62
+ // Heartbeat & scheduling
63
+ heartbeat: {
64
+ enabled: boolean;
65
+ intervalMinutes: number;
66
+ checks: string[]; // What to check: ['email', 'calendar', 'tickets']
67
+ };
68
+
69
+ // Context
70
+ context: {
71
+ userInfo?: string; // USER.md content — info about the user/company
72
+ customInstructions?: string; // Additional AGENTS.md instructions
73
+ knowledgeBase?: string[]; // Paths or URLs to reference docs
74
+ };
75
+
76
+ // Permission profile
77
+ permissionProfileId: string;
78
+
79
+ // Deployment
80
+ deployment: {
81
+ target: DeploymentTarget;
82
+ config: DeploymentConfig;
83
+ status: DeploymentStatus;
84
+ };
85
+
86
+ createdAt: string;
87
+ updatedAt: string;
88
+ }
89
+
90
+ export interface ChannelConfig {
91
+ type: 'whatsapp' | 'telegram' | 'discord' | 'slack' | 'email' | 'web' | 'api';
92
+ enabled: boolean;
93
+ config: Record<string, any>; // Channel-specific config (tokens, webhook URLs, etc.)
94
+ }
95
+
96
+ export type DeploymentTarget = 'docker' | 'vps' | 'fly' | 'railway' | 'aws' | 'gcp' | 'azure' | 'local';
97
+
98
+ export interface DeploymentConfig {
99
+ // Docker
100
+ docker?: {
101
+ image: string;
102
+ tag: string;
103
+ ports: number[];
104
+ volumes: string[];
105
+ env: Record<string, string>;
106
+ resources: { cpuLimit: string; memoryLimit: string };
107
+ restart: 'always' | 'unless-stopped' | 'on-failure' | 'no';
108
+ network?: string;
109
+ };
110
+
111
+ // VPS / bare metal
112
+ vps?: {
113
+ host: string;
114
+ port: number;
115
+ user: string;
116
+ authMethod: 'key' | 'password';
117
+ sshKeyPath?: string;
118
+ installPath: string; // Where to install on the VPS
119
+ systemd: boolean; // Use systemd for process management
120
+ sudo: boolean;
121
+ };
122
+
123
+ // Cloud platforms
124
+ cloud?: {
125
+ provider: 'fly' | 'railway' | 'aws' | 'gcp' | 'azure';
126
+ region: string;
127
+ size: string; // Instance size / machine type
128
+ apiToken: string;
129
+ appName?: string; // Auto-generated if not set
130
+ customDomain?: string;
131
+ };
132
+ }
133
+
134
+ export type DeploymentStatus =
135
+ | 'not-deployed'
136
+ | 'provisioning'
137
+ | 'deploying'
138
+ | 'running'
139
+ | 'stopped'
140
+ | 'error'
141
+ | 'updating';
142
+
143
+ // ─── Config Generator ───────────────────────────────────
144
+
145
+ export class AgentConfigGenerator {
146
+
147
+ /**
148
+ * Generate the complete workspace files for an agent
149
+ */
150
+ generateWorkspace(config: AgentConfig): WorkspaceFiles {
151
+ return {
152
+ 'SOUL.md': this.generateSoul(config),
153
+ 'USER.md': this.generateUser(config),
154
+ 'AGENTS.md': this.generateAgents(config),
155
+ 'IDENTITY.md': this.generateIdentity(config),
156
+ 'HEARTBEAT.md': this.generateHeartbeat(config),
157
+ 'TOOLS.md': this.generateTools(config),
158
+ 'MEMORY.md': `# MEMORY.md — ${config.displayName}'s Long-Term Memory\n\n_Created ${new Date().toISOString()}_\n`,
159
+ };
160
+ }
161
+
162
+ /**
163
+ * Generate the OpenClaw gateway config for this agent
164
+ */
165
+ generateGatewayConfig(config: AgentConfig): GatewayConfig {
166
+ const channels: Record<string, any> = {};
167
+
168
+ for (const ch of config.channels.enabled) {
169
+ if (!ch.enabled) continue;
170
+ channels[ch.type] = ch.config;
171
+ }
172
+
173
+ return {
174
+ model: `${config.model.provider}/${config.model.modelId}`,
175
+ thinking: config.model.thinkingLevel,
176
+ temperature: config.model.temperature,
177
+ maxTokens: config.model.maxTokens,
178
+ channels,
179
+ heartbeat: config.heartbeat.enabled ? {
180
+ intervalMinutes: config.heartbeat.intervalMinutes,
181
+ } : undefined,
182
+ workspace: config.workspace.workingDirectory,
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Generate a docker-compose.yml for this agent
188
+ */
189
+ generateDockerCompose(config: AgentConfig): string {
190
+ const dc = config.deployment.config.docker;
191
+ if (!dc) throw new Error('No Docker config');
192
+
193
+ const env = { ...dc.env };
194
+ // Inject standard vars
195
+ env['OPENCLAW_MODEL'] = `${config.model.provider}/${config.model.modelId}`;
196
+ env['OPENCLAW_THINKING'] = config.model.thinkingLevel;
197
+ if (config.email.enabled && config.email.address) {
198
+ env['AGENTICMAIL_EMAIL'] = config.email.address;
199
+ }
200
+
201
+ const envLines = Object.entries(env).map(([k, v]) => ` ${k}: "${v}"`).join('\n');
202
+ const volumes = dc.volumes.map(v => ` - ${v}`).join('\n');
203
+ const ports = dc.ports.map(p => ` - "${p}:${p}"`).join('\n');
204
+
205
+ return `version: "3.8"
206
+
207
+ services:
208
+ ${config.name}:
209
+ image: ${dc.image}:${dc.tag}
210
+ container_name: agenticmail-${config.name}
211
+ restart: ${dc.restart}
212
+ ports:
213
+ ${ports}
214
+ volumes:
215
+ ${volumes}
216
+ environment:
217
+ ${envLines}
218
+ deploy:
219
+ resources:
220
+ limits:
221
+ cpus: "${dc.resources.cpuLimit}"
222
+ memory: ${dc.resources.memoryLimit}
223
+ ${dc.network ? ` networks:\n - ${dc.network}\n\nnetworks:\n ${dc.network}:\n external: true` : ''}
224
+ `;
225
+ }
226
+
227
+ /**
228
+ * Generate a systemd service file for VPS deployment
229
+ */
230
+ generateSystemdUnit(config: AgentConfig): string {
231
+ const vps = config.deployment.config.vps;
232
+ if (!vps) throw new Error('No VPS config');
233
+
234
+ return `[Unit]
235
+ Description=AgenticMail Agent: ${config.displayName}
236
+ After=network.target
237
+
238
+ [Service]
239
+ Type=simple
240
+ User=${vps.user}
241
+ WorkingDirectory=${vps.installPath}
242
+ ExecStart=/usr/bin/env node ${vps.installPath}/node_modules/.bin/openclaw gateway start
243
+ Restart=always
244
+ RestartSec=10
245
+ Environment=NODE_ENV=production
246
+ Environment=OPENCLAW_MODEL=${config.model.provider}/${config.model.modelId}
247
+ Environment=OPENCLAW_THINKING=${config.model.thinkingLevel}
248
+
249
+ # Security hardening
250
+ NoNewPrivileges=true
251
+ ProtectSystem=strict
252
+ ProtectHome=read-only
253
+ ReadWritePaths=${vps.installPath}
254
+ PrivateTmp=true
255
+
256
+ [Install]
257
+ WantedBy=multi-user.target
258
+ `;
259
+ }
260
+
261
+ /**
262
+ * Generate a deployment script for VPS
263
+ */
264
+ generateVPSDeployScript(config: AgentConfig): string {
265
+ const vps = config.deployment.config.vps;
266
+ if (!vps) throw new Error('No VPS config');
267
+
268
+ return `#!/bin/bash
269
+ set -euo pipefail
270
+
271
+ # AgenticMail Agent Deployment Script
272
+ # Agent: ${config.displayName}
273
+ # Target: ${vps.host}
274
+
275
+ echo "🚀 Deploying ${config.displayName} to ${vps.host}..."
276
+
277
+ INSTALL_PATH="${vps.installPath}"
278
+ ${vps.sudo ? 'SUDO="sudo"' : 'SUDO=""'}
279
+
280
+ # 1. Install Node.js if needed
281
+ if ! command -v node &> /dev/null; then
282
+ echo "📦 Installing Node.js..."
283
+ curl -fsSL https://deb.nodesource.com/setup_22.x | $SUDO bash -
284
+ $SUDO apt-get install -y nodejs
285
+ fi
286
+
287
+ # 2. Create workspace
288
+ mkdir -p "$INSTALL_PATH/workspace"
289
+ cd "$INSTALL_PATH"
290
+
291
+ # 3. Install OpenClaw + AgenticMail
292
+ echo "📦 Installing packages..."
293
+ npm init -y 2>/dev/null || true
294
+ npm install openclaw agenticmail @agenticmail/core @agenticmail/openclaw
295
+
296
+ # 4. Write workspace files
297
+ echo "📝 Writing agent configuration..."
298
+ ${Object.entries(this.generateWorkspace(config)).map(([file, content]) =>
299
+ `cat > "$INSTALL_PATH/workspace/${file}" << 'WORKSPACE_EOF'\n${content}\nWORKSPACE_EOF`
300
+ ).join('\n\n')}
301
+
302
+ # 5. Write gateway config
303
+ cat > "$INSTALL_PATH/config.yaml" << 'CONFIG_EOF'
304
+ ${JSON.stringify(this.generateGatewayConfig(config), null, 2)}
305
+ CONFIG_EOF
306
+
307
+ # 6. Install systemd service
308
+ echo "⚙️ Installing systemd service..."
309
+ $SUDO tee /etc/systemd/system/agenticmail-${config.name}.service > /dev/null << 'SERVICE_EOF'
310
+ ${this.generateSystemdUnit(config)}
311
+ SERVICE_EOF
312
+
313
+ $SUDO systemctl daemon-reload
314
+ $SUDO systemctl enable agenticmail-${config.name}
315
+ $SUDO systemctl start agenticmail-${config.name}
316
+
317
+ echo "✅ ${config.displayName} deployed and running!"
318
+ echo " Status: systemctl status agenticmail-${config.name}"
319
+ echo " Logs: journalctl -u agenticmail-${config.name} -f"
320
+ `;
321
+ }
322
+
323
+ // ─── Private Generators ─────────────────────────────
324
+
325
+ private generateSoul(config: AgentConfig): string {
326
+ if (config.identity.personality) return config.identity.personality;
327
+
328
+ const toneMap = {
329
+ formal: 'Be professional and precise. Use proper grammar. Avoid slang or casual language.',
330
+ casual: 'Be relaxed and conversational. Use contractions. Feel free to be informal.',
331
+ professional: 'Be competent and clear. Direct communication without being stiff.',
332
+ friendly: 'Be warm and approachable. Show genuine interest. Use a positive tone.',
333
+ custom: config.identity.customTone || '',
334
+ };
335
+
336
+ return `# SOUL.md — Who You Are
337
+
338
+ ## Role
339
+ You are **${config.displayName}**, a ${config.identity.role}.
340
+
341
+ ## Communication Style
342
+ ${toneMap[config.identity.tone]}
343
+
344
+ ## Language
345
+ Primary language: ${config.identity.language}
346
+
347
+ ## Core Principles
348
+ - Be genuinely helpful, not performatively helpful
349
+ - Be resourceful — try to figure things out before asking
350
+ - Earn trust through competence
351
+ - Keep private information private
352
+
353
+ ## Boundaries
354
+ - Never share confidential company information
355
+ - Ask before taking irreversible actions
356
+ - Stay within your assigned role and permissions
357
+ `;
358
+ }
359
+
360
+ private generateUser(config: AgentConfig): string {
361
+ return config.context?.userInfo || `# USER.md — About Your Organization\n\n_Configure this from the admin dashboard._\n`;
362
+ }
363
+
364
+ private generateAgents(config: AgentConfig): string {
365
+ const customInstructions = config.context?.customInstructions || '';
366
+ return `# AGENTS.md — Your Workspace
367
+
368
+ ## Every Session
369
+ 1. Read SOUL.md — this is who you are
370
+ 2. Read USER.md — this is who you're helping
371
+ 3. Check memory/ for recent context
372
+
373
+ ## Memory
374
+ - Daily notes: memory/YYYY-MM-DD.md
375
+ - Long-term: MEMORY.md
376
+
377
+ ## Safety
378
+ - Don't exfiltrate private data
379
+ - Don't run destructive commands without asking
380
+ - When in doubt, ask
381
+
382
+ ${customInstructions}
383
+ `;
384
+ }
385
+
386
+ private generateIdentity(config: AgentConfig): string {
387
+ return `# IDENTITY.md
388
+
389
+ - **Name:** ${config.displayName}
390
+ - **Role:** ${config.identity.role}
391
+ - **Tone:** ${config.identity.tone}
392
+ `;
393
+ }
394
+
395
+ private generateHeartbeat(config: AgentConfig): string {
396
+ if (!config.heartbeat.enabled) return '# HEARTBEAT.md\n# Heartbeat disabled\n';
397
+
398
+ const checks = config.heartbeat.checks.map(c => `- Check ${c}`).join('\n');
399
+ return `# HEARTBEAT.md
400
+
401
+ ## Periodic Checks
402
+ ${checks}
403
+
404
+ ## Schedule
405
+ Check every ${config.heartbeat.intervalMinutes} minutes during active hours.
406
+ `;
407
+ }
408
+
409
+ private generateTools(config: AgentConfig): string {
410
+ return `# TOOLS.md — Local Notes
411
+
412
+ _Add environment-specific notes here (camera names, SSH hosts, etc.)_
413
+ `;
414
+ }
415
+ }
416
+
417
+ // ─── Output Types ───────────────────────────────────────
418
+
419
+ export type WorkspaceFiles = Record<string, string>;
420
+
421
+ export interface GatewayConfig {
422
+ model: string;
423
+ thinking: string;
424
+ temperature?: number;
425
+ maxTokens?: number;
426
+ channels: Record<string, any>;
427
+ heartbeat?: { intervalMinutes: number };
428
+ workspace: string;
429
+ }