@agenticmail/enterprise 0.5.109 → 0.5.111

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,49 @@
1
+ import {
2
+ AgentRuntime,
3
+ EmailChannel,
4
+ FollowUpScheduler,
5
+ SessionManager,
6
+ SubAgentManager,
7
+ ToolRegistry,
8
+ callLLM,
9
+ createAgentRuntime,
10
+ createNoopHooks,
11
+ createRuntimeHooks,
12
+ estimateMessageTokens,
13
+ estimateTokens,
14
+ executeTool,
15
+ runAgentLoop,
16
+ toolsToDefinitions
17
+ } from "./chunk-YRRKUCNF.js";
18
+ import "./chunk-TYW5XTOW.js";
19
+ import "./chunk-AQH4DFYV.js";
20
+ import {
21
+ PROVIDER_REGISTRY,
22
+ listAllProviders,
23
+ resolveApiKeyForProvider,
24
+ resolveProvider
25
+ } from "./chunk-67KZYSLU.js";
26
+ import "./chunk-JLSQOQ5L.js";
27
+ import "./chunk-NRF3YRF7.js";
28
+ import "./chunk-KFQGP6VL.js";
29
+ export {
30
+ AgentRuntime,
31
+ EmailChannel,
32
+ FollowUpScheduler,
33
+ PROVIDER_REGISTRY,
34
+ SessionManager,
35
+ SubAgentManager,
36
+ ToolRegistry,
37
+ callLLM,
38
+ createAgentRuntime,
39
+ createNoopHooks,
40
+ createRuntimeHooks,
41
+ estimateMessageTokens,
42
+ estimateTokens,
43
+ executeTool,
44
+ listAllProviders,
45
+ resolveApiKeyForProvider,
46
+ resolveProvider,
47
+ runAgentLoop,
48
+ toolsToDefinitions
49
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-SAJR7T37.js";
4
+ import "./chunk-3SMTCIR4.js";
5
+ import "./chunk-RO537U6H.js";
6
+ import "./chunk-DRXMYYKN.js";
7
+ import "./chunk-67KZYSLU.js";
8
+ import "./chunk-JLSQOQ5L.js";
9
+ import "./chunk-KFQGP6VL.js";
10
+ export {
11
+ createServer
12
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-WJZ42G5N.js";
10
+ import "./chunk-QDXUZP7Y.js";
11
+ import "./chunk-KFQGP6VL.js";
12
+ export {
13
+ promptCompanyInfo,
14
+ promptDatabase,
15
+ promptDeployment,
16
+ promptDomain,
17
+ promptRegistration,
18
+ provision,
19
+ runSetupWizard
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.109",
3
+ "version": "0.5.111",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli-agent.ts CHANGED
@@ -198,4 +198,144 @@ export async function runAgent(_args: string[]) {
198
198
  );
199
199
  console.log(' State: running');
200
200
  } catch {}
201
+
202
+ // 10. Auto-onboarding + welcome email (runs after short delay to let runtime settle)
203
+ setTimeout(async () => {
204
+ try {
205
+ // Get org ID
206
+ const orgRows = await engineDb.query<any>(
207
+ `SELECT org_id FROM managed_agents WHERE id = $1`, [AGENT_ID]
208
+ );
209
+ const orgId = orgRows?.[0]?.org_id;
210
+ if (!orgId) { console.log('[onboarding] No org ID found, skipping'); return; }
211
+
212
+ // Check pending onboarding records
213
+ const pendingRows = await engineDb.query<any>(
214
+ `SELECT r.id, r.policy_id, p.name as policy_name, p.content as policy_content, p.priority
215
+ FROM onboarding_records r
216
+ JOIN org_policies p ON r.policy_id = p.id
217
+ WHERE r.agent_id = $1 AND r.status = 'pending'`,
218
+ [AGENT_ID]
219
+ );
220
+
221
+ if (!pendingRows || pendingRows.length === 0) {
222
+ console.log('[onboarding] Already complete or no records');
223
+ } else {
224
+ console.log(`[onboarding] ${pendingRows.length} pending policies — auto-acknowledging...`);
225
+ const ts = new Date().toISOString();
226
+ const policyNames: string[] = [];
227
+
228
+ for (const row of pendingRows) {
229
+ const policyName = row.policy_name || row.policy_id;
230
+ policyNames.push(policyName);
231
+ console.log(`[onboarding] Reading: ${policyName}`);
232
+
233
+ // Compute content hash
234
+ const { createHash } = await import('crypto');
235
+ const hash = createHash('sha256').update(row.policy_content || '').digest('hex').slice(0, 16);
236
+
237
+ // Update record to acknowledged
238
+ await engineDb.query(
239
+ `UPDATE onboarding_records SET status = 'acknowledged', acknowledged_at = $1, verification_hash = $2, updated_at = $1 WHERE id = $3`,
240
+ [ts, hash, row.id]
241
+ );
242
+ console.log(`[onboarding] ✅ Acknowledged: ${policyName}`);
243
+
244
+ // Store policy knowledge in memory
245
+ if (memoryManager) {
246
+ try {
247
+ await memoryManager.storeMemory(AGENT_ID, {
248
+ content: `Organization policy "${policyName}" (${row.priority}): ${(row.policy_content || '').slice(0, 500)}`,
249
+ category: 'org_knowledge',
250
+ importance: row.priority === 'mandatory' ? 'high' : 'medium',
251
+ confidence: 1.0,
252
+ });
253
+ } catch {}
254
+ }
255
+ }
256
+
257
+ // Record completion in memory
258
+ if (memoryManager) {
259
+ try {
260
+ await memoryManager.storeMemory(AGENT_ID, {
261
+ content: `Completed onboarding: read and acknowledged ${policyNames.length} organization policies: ${policyNames.join(', ')}.`,
262
+ category: 'org_knowledge',
263
+ importance: 'high',
264
+ confidence: 1.0,
265
+ });
266
+ } catch {}
267
+ }
268
+
269
+ console.log(`[onboarding] ✅ Onboarding complete — ${policyNames.length} policies acknowledged`);
270
+ }
271
+
272
+ // 11. Send welcome email to manager if configured
273
+ // Manager email can come from config.managerEmail or config.manager.email
274
+ const managerEmail = (config as any).managerEmail || ((config as any).manager?.type === 'external' ? (config as any).manager.email : null);
275
+ const emailConfig = (config as any).emailConfig;
276
+ if (managerEmail && emailConfig) {
277
+ console.log(`[welcome] Sending introduction email to ${managerEmail}...`);
278
+ try {
279
+ const { createEmailProvider } = await import('./agenticmail/index.js');
280
+ const emailProvider = await createEmailProvider(emailConfig);
281
+
282
+ const agentName = config.displayName || config.name;
283
+ const role = config.identity?.role || 'AI Agent';
284
+ const traits = config.identity?.traits || {};
285
+ const traitLines = Object.entries(traits)
286
+ .filter(([, v]) => v)
287
+ .map(([k, v]) => ` - ${k}: ${v}`)
288
+ .join('\n');
289
+
290
+ const policyCount = pendingRows?.length || 0;
291
+
292
+ const body = `Hello,
293
+
294
+ I'm ${agentName}, your new ${role}. I've just been deployed and have completed my onboarding — I've read and acknowledged all ${policyCount} organization policies.
295
+
296
+ About me:
297
+ - Role: ${role}
298
+ - Communication style: ${config.identity?.tone || 'professional'}
299
+ - Language: ${config.identity?.language || 'English'}
300
+ ${traitLines ? `- Personality traits:\n${traitLines}` : ''}
301
+
302
+ I'm ready to start working. Here's what I can help with:
303
+ - Responding to emails and communications
304
+ - Processing tasks and requests
305
+ - Following organization guidelines and escalation protocols
306
+
307
+ You can reach me by email at ${config.email?.address || emailConfig?.email || 'my configured email address'}, or through the enterprise dashboard.
308
+
309
+ Looking forward to working with you!
310
+
311
+ Best regards,
312
+ ${agentName}`;
313
+
314
+ await emailProvider.send({
315
+ to: managerEmail,
316
+ subject: `Hi! I'm ${agentName}, your new ${role}`,
317
+ text: body,
318
+ });
319
+ console.log(`[welcome] ✅ Welcome email sent to ${managerEmail}`);
320
+
321
+ if (memoryManager) {
322
+ try {
323
+ await memoryManager.storeMemory(AGENT_ID, {
324
+ content: `Sent welcome introduction email to manager at ${managerEmail}. Introduced myself as ${agentName}, ${role}.`,
325
+ category: 'interaction_pattern',
326
+ importance: 'medium',
327
+ confidence: 1.0,
328
+ });
329
+ } catch {}
330
+ }
331
+ } catch (err: any) {
332
+ console.error(`[welcome] Failed to send welcome email: ${err.message}`);
333
+ }
334
+ } else {
335
+ if (!managerEmail) console.log('[welcome] No manager email configured, skipping welcome email');
336
+ }
337
+ } catch (err: any) {
338
+ console.error(`[onboarding] Error: ${err.message}`);
339
+ }
340
+ }, 3000);
201
341
  }
@@ -106,6 +106,9 @@ export interface AgentConfig {
106
106
  };
107
107
  };
108
108
 
109
+ // Reporting
110
+ managerEmail?: string; // Manager/supervisor email — agent sends welcome email + reports here
111
+
109
112
  // Permission profile
110
113
  permissionProfileId: string;
111
114
 
@@ -399,7 +399,8 @@ export class DeploymentEngine {
399
399
  const apiToken = cloud.apiToken;
400
400
  if (!apiToken) throw new Error('Fly.io API token is required');
401
401
 
402
- const appName = cloud.appName || `am-agent-${config.name.toLowerCase().replace(/[^a-z0-9-]/g, '-').slice(0, 30)}`;
402
+ // Reuse previously stored app/machine IDs for redeploy
403
+ const appName = cloud.appName || (config.deployment.config as any).flyAppName || `am-agent-${config.name.toLowerCase().replace(/[^a-z0-9-]/g, '-').slice(0, 30)}`;
403
404
  const region = cloud.region || 'iad';
404
405
  const size = cloud.size || 'shared-cpu-1x';
405
406
  const FLY_API = 'https://api.machines.dev/v1';
@@ -493,15 +494,24 @@ export class DeploymentEngine {
493
494
  };
494
495
 
495
496
  let machineId: string;
496
- if (existingMachines.length > 0) {
497
- // Update existing machine
498
- const existing = existingMachines[0];
497
+ // Filter to only non-destroyed machines
498
+ const liveMachines = (existingMachines || []).filter((m: any) => m.state !== 'destroyed');
499
+ if (liveMachines.length > 0) {
500
+ // Reuse existing machine — stop it first if running, then update
501
+ const existing = liveMachines[0];
499
502
  machineId = existing.id;
503
+ emit('install', 'started', `Reusing existing machine ${machineId} (state: ${existing.state})...`);
504
+ if (existing.state === 'started' || existing.state === 'running') {
505
+ try {
506
+ await flyFetch(`/apps/${appName}/machines/${machineId}/stop`, 'POST');
507
+ await flyFetch(`/apps/${appName}/machines/${machineId}/wait?state=stopped&timeout=30`);
508
+ } catch { /* may already be stopped */ }
509
+ }
500
510
  await flyFetch(`/apps/${appName}/machines/${machineId}`, 'POST', {
501
511
  config: machineConfig,
502
512
  region,
503
513
  });
504
- emit('install', 'completed', `Machine ${machineId} updated`);
514
+ emit('install', 'completed', `Machine ${machineId} updated and restarting`);
505
515
  } else {
506
516
  // Create new machine
507
517
  const machine = await flyFetch(`/apps/${appName}/machines`, 'POST', {
@@ -522,7 +532,7 @@ export class DeploymentEngine {
522
532
  emit('start', 'completed', 'Machine starting (health check pending)');
523
533
  }
524
534
 
525
- // Store deployment metadata
535
+ // Store deployment metadata — persists app/machine IDs for redeployment
526
536
  config.deployment.config.cloud = {
527
537
  ...cloud,
528
538
  provider: 'fly',
@@ -530,6 +540,7 @@ export class DeploymentEngine {
530
540
  region,
531
541
  size,
532
542
  };
543
+ (config.deployment.config as any).flyAppName = appName;
533
544
  (config.deployment.config as any).flyMachineId = machineId;
534
545
  (config.deployment.config as any).deployedAt = new Date().toISOString();
535
546