@agenticmail/enterprise 0.5.247 → 0.5.249

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,114 @@
1
+ import "./chunk-KFQGP6VL.js";
2
+
3
+ // src/cli-serve.ts
4
+ import { existsSync, readFileSync } from "fs";
5
+ import { join } from "path";
6
+ import { homedir } from "os";
7
+ function loadEnvFile() {
8
+ const candidates = [
9
+ join(process.cwd(), ".env"),
10
+ join(homedir(), ".agenticmail", ".env")
11
+ ];
12
+ for (const envPath of candidates) {
13
+ if (!existsSync(envPath)) continue;
14
+ try {
15
+ const content = readFileSync(envPath, "utf8");
16
+ for (const line of content.split("\n")) {
17
+ const trimmed = line.trim();
18
+ if (!trimmed || trimmed.startsWith("#")) continue;
19
+ const eq = trimmed.indexOf("=");
20
+ if (eq < 0) continue;
21
+ const key = trimmed.slice(0, eq).trim();
22
+ let val = trimmed.slice(eq + 1).trim();
23
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
24
+ val = val.slice(1, -1);
25
+ }
26
+ if (!process.env[key]) process.env[key] = val;
27
+ }
28
+ console.log(`Loaded config from ${envPath}`);
29
+ return;
30
+ } catch {
31
+ }
32
+ }
33
+ }
34
+ async function ensureSecrets() {
35
+ const { randomUUID } = await import("crypto");
36
+ const envDir = join(homedir(), ".agenticmail");
37
+ const envPath = join(envDir, ".env");
38
+ let dirty = false;
39
+ if (!process.env.JWT_SECRET) {
40
+ process.env.JWT_SECRET = randomUUID() + randomUUID();
41
+ dirty = true;
42
+ console.log("[startup] Generated new JWT_SECRET (existing sessions will need to re-login)");
43
+ }
44
+ if (!process.env.AGENTICMAIL_VAULT_KEY) {
45
+ process.env.AGENTICMAIL_VAULT_KEY = randomUUID() + randomUUID();
46
+ dirty = true;
47
+ console.log("[startup] Generated new AGENTICMAIL_VAULT_KEY");
48
+ console.log("[startup] \u26A0\uFE0F Previously encrypted credentials will need to be re-entered in the dashboard");
49
+ }
50
+ if (dirty) {
51
+ try {
52
+ if (!existsSync(envDir)) {
53
+ const { mkdirSync } = await import("fs");
54
+ mkdirSync(envDir, { recursive: true });
55
+ }
56
+ const { appendFileSync } = await import("fs");
57
+ const lines = [];
58
+ let existing = "";
59
+ if (existsSync(envPath)) {
60
+ existing = readFileSync(envPath, "utf8");
61
+ }
62
+ if (!existing.includes("JWT_SECRET=")) {
63
+ lines.push(`JWT_SECRET=${process.env.JWT_SECRET}`);
64
+ }
65
+ if (!existing.includes("AGENTICMAIL_VAULT_KEY=")) {
66
+ lines.push(`AGENTICMAIL_VAULT_KEY=${process.env.AGENTICMAIL_VAULT_KEY}`);
67
+ }
68
+ if (lines.length) {
69
+ appendFileSync(envPath, "\n" + lines.join("\n") + "\n", { mode: 384 });
70
+ console.log(`[startup] Saved secrets to ${envPath}`);
71
+ }
72
+ } catch (e) {
73
+ console.warn(`[startup] Could not save secrets to ${envPath}: ${e.message}`);
74
+ }
75
+ }
76
+ }
77
+ async function runServe(_args) {
78
+ loadEnvFile();
79
+ const DATABASE_URL = process.env.DATABASE_URL;
80
+ const PORT = parseInt(process.env.PORT || "8080", 10);
81
+ await ensureSecrets();
82
+ const JWT_SECRET = process.env.JWT_SECRET;
83
+ const VAULT_KEY = process.env.AGENTICMAIL_VAULT_KEY;
84
+ if (!DATABASE_URL) {
85
+ console.error("ERROR: DATABASE_URL is required.");
86
+ console.error("");
87
+ console.error("Set it via environment variable or .env file:");
88
+ console.error(" DATABASE_URL=postgresql://user:pass@host:5432/db npx @agenticmail/enterprise start");
89
+ console.error("");
90
+ console.error("Or create a .env file (in cwd or ~/.agenticmail/.env):");
91
+ console.error(" DATABASE_URL=postgresql://user:pass@host:5432/db");
92
+ console.error(" JWT_SECRET=your-secret-here");
93
+ console.error(" PORT=3200");
94
+ process.exit(1);
95
+ }
96
+ const { createAdapter } = await import("./factory-672W7A5B.js");
97
+ const { createServer } = await import("./server-DT5K3D55.js");
98
+ const db = await createAdapter({
99
+ type: DATABASE_URL.startsWith("postgres") ? "postgres" : "sqlite",
100
+ connectionString: DATABASE_URL
101
+ });
102
+ await db.migrate();
103
+ const server = createServer({
104
+ port: PORT,
105
+ db,
106
+ jwtSecret: JWT_SECRET,
107
+ corsOrigins: ["*"]
108
+ });
109
+ await server.start();
110
+ console.log(`AgenticMail Enterprise server running on :${PORT}`);
111
+ }
112
+ export {
113
+ runServe
114
+ };
package/dist/cli.js CHANGED
@@ -53,14 +53,14 @@ Skill Development:
53
53
  break;
54
54
  case "serve":
55
55
  case "start":
56
- import("./cli-serve-V7YB747O.js").then((m) => m.runServe(args.slice(1))).catch(fatal);
56
+ import("./cli-serve-SUPVRGDZ.js").then((m) => m.runServe(args.slice(1))).catch(fatal);
57
57
  break;
58
58
  case "agent":
59
- import("./cli-agent-O5AL2A3U.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
59
+ import("./cli-agent-6DT3UZHY.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
60
60
  break;
61
61
  case "setup":
62
62
  default:
63
- import("./setup-SOQGPCGF.js").then((m) => m.runSetupWizard()).catch(fatal);
63
+ import("./setup-6EUJP3OZ.js").then((m) => m.runSetupWizard()).catch(fatal);
64
64
  break;
65
65
  }
66
66
  function fatal(err) {
@@ -29,31 +29,25 @@ export function HelpButton(props) {
29
29
  onMouseLeave: function(e) { e.currentTarget.style.borderColor = 'var(--text-muted, #6b7280)'; e.currentTarget.style.color = 'var(--text-muted, #6b7280)'; }
30
30
  }, '?'),
31
31
  isOpen && h('div', {
32
- onClick: function(e) { e.stopPropagation(); },
32
+ id: 'help-overlay',
33
+ onMouseDown: function(e) { if (e.target.id === 'help-overlay') setOpen(false); },
33
34
  style: {
34
35
  position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, zIndex: 200,
36
+ background: 'rgba(0,0,0,0.5)',
37
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
35
38
  }
36
39
  },
37
- // Backdrop — click to close
38
40
  h('div', {
39
- onClick: function(e) { e.stopPropagation(); setOpen(false); },
40
- style: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)' }
41
- }),
42
- // Help panel — centered card, NOT a Modal component
43
- h('div', {
44
- onClick: function(e) { e.stopPropagation(); },
45
41
  style: {
46
- position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
47
42
  background: 'var(--bg-card, #181b28)', border: '1px solid var(--border)',
48
43
  borderRadius: 'var(--radius-xl, 14px)', width: 520, maxWidth: '92vw', maxHeight: '80vh',
49
44
  overflow: 'hidden', boxShadow: '0 25px 50px rgba(0,0,0,0.4)',
50
45
  }
51
46
  },
52
- // Header
53
47
  h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '14px 20px', borderBottom: '1px solid var(--border)' } },
54
48
  h('h3', { style: { fontSize: 15, fontWeight: 700, margin: 0 } }, props.label || 'Help'),
55
49
  h('button', {
56
- onClick: function(e) { e.stopPropagation(); setOpen(false); },
50
+ onMouseDown: function(e) { e.stopPropagation(); setOpen(false); },
57
51
  style: {
58
52
  display: 'flex', alignItems: 'center', justifyContent: 'center',
59
53
  width: 28, height: 28, borderRadius: 6, border: 'none',
@@ -62,7 +56,6 @@ export function HelpButton(props) {
62
56
  }
63
57
  }, I.x())
64
58
  ),
65
- // Body
66
59
  h('div', { style: { padding: '16px 20px', overflowY: 'auto', maxHeight: 'calc(80vh - 60px)', fontSize: 14, lineHeight: 1.7, color: 'var(--text-secondary, #9ca3af)' } },
67
60
  props.children
68
61
  )
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, adminCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { Modal } from '../components/modal.js';
4
4
  import { HelpButton } from '../components/help-button.js';
@@ -44,9 +44,10 @@ function McpServersSection() {
44
44
  var _showAdd = useState(false); var showAdd = _showAdd[0]; var setShowAdd = _showAdd[1];
45
45
  var _editServer = useState(null); var editServer = _editServer[0]; var setEditServer = _editServer[1];
46
46
  var _testing = useState(null); var testing = _testing[0]; var setTesting = _testing[1];
47
+ var _agents = useState([]); var agents = _agents[0]; var setAgents = _agents[1];
47
48
 
48
49
  // Add/edit form
49
- var _form = useState({ name: '', type: 'stdio', command: '', args: '', url: '', apiKey: '', headers: '{}', env: '{}', enabled: true, description: '', autoRestart: true, timeout: 30 });
50
+ var _form = useState({ name: '', type: 'stdio', command: '', args: '', url: '', apiKey: '', headers: '{}', env: '{}', enabled: true, description: '', autoRestart: true, timeout: 30, assignedAgents: [] });
50
51
  var form = _form[0]; var setForm = _form[1];
51
52
 
52
53
  var load = useCallback(function() {
@@ -58,9 +59,12 @@ function McpServersSection() {
58
59
  }, []);
59
60
 
60
61
  useEffect(function() { load(); }, [load]);
62
+ useEffect(function() {
63
+ adminCall('/agents').then(function(d) { setAgents((d.agents || d || []).filter(function(a) { return a.status !== 'archived'; })); }).catch(function() {});
64
+ }, []);
61
65
 
62
66
  var resetForm = function() {
63
- setForm({ name: '', type: 'stdio', command: '', args: '', url: '', apiKey: '', headers: '{}', env: '{}', enabled: true, description: '', autoRestart: true, timeout: 30 });
67
+ setForm({ name: '', type: 'stdio', command: '', args: '', url: '', apiKey: '', headers: '{}', env: '{}', enabled: true, description: '', autoRestart: true, timeout: 30, assignedAgents: [] });
64
68
  };
65
69
 
66
70
  var openAdd = function() { resetForm(); setEditServer(null); setShowAdd(true); };
@@ -79,6 +83,7 @@ function McpServersSection() {
79
83
  description: server.description || '',
80
84
  autoRestart: server.autoRestart !== false,
81
85
  timeout: server.timeout || 30,
86
+ assignedAgents: server.assignedAgents || [],
82
87
  });
83
88
  setEditServer(server);
84
89
  setShowAdd(true);
@@ -92,6 +97,7 @@ function McpServersSection() {
92
97
  description: form.description.trim(),
93
98
  autoRestart: form.autoRestart,
94
99
  timeout: parseInt(form.timeout) || 30,
100
+ assignedAgents: form.assignedAgents || [],
95
101
  };
96
102
  if (form.type === 'stdio') {
97
103
  payload.command = form.command.trim();
@@ -210,7 +216,13 @@ function McpServersSection() {
210
216
  ? (server.command + ' ' + (server.args || []).join(' ')).trim()
211
217
  : server.url || ''
212
218
  ),
213
- server.description && h('div', { style: { fontSize: 11, color: 'var(--text-secondary)', marginTop: 2 } }, server.description)
219
+ server.description && h('div', { style: { fontSize: 11, color: 'var(--text-secondary)', marginTop: 2 } }, server.description),
220
+ server.assignedAgents && server.assignedAgents.length > 0 && h('div', { style: { fontSize: 10, color: 'var(--text-muted)', marginTop: 3 } },
221
+ 'Agents: ' + server.assignedAgents.map(function(aid) {
222
+ var a = agents.find(function(x) { return x.id === aid; });
223
+ return a ? (a.display_name || a.name) : aid.slice(0, 8);
224
+ }).join(', ')
225
+ )
214
226
  ),
215
227
  h('div', { style: { display: 'flex', gap: 4, flexShrink: 0 } },
216
228
  h('button', { className: 'btn btn-ghost btn-sm', title: 'Test connection', disabled: isTesting, onClick: function() { testServer(server); } },
@@ -400,6 +412,38 @@ function McpServersSection() {
400
412
  h('p', { style: { marginTop: 8 } }, 'Keep this on unless you have a reason to disable it.')
401
413
  )
402
414
  )
415
+ ),
416
+ // Agent assignment
417
+ agents.length > 0 && h('div', { className: 'form-group', style: { marginTop: 16 } },
418
+ h('label', { className: 'form-label', style: { display: 'flex', alignItems: 'center' } }, 'Agent Access', h(HelpButton, { label: 'Agent Access' },
419
+ h('p', null, 'Choose which agents can use this MCP server\'s tools. If none are selected, ALL agents can use it.'),
420
+ h('p', { style: { marginTop: 8 } }, 'Use this to restrict sensitive tools (like database access) to specific agents only.')
421
+ )),
422
+ h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 6 } },
423
+ agents.map(function(a) {
424
+ var isSelected = (form.assignedAgents || []).includes(a.id);
425
+ return h('button', {
426
+ key: a.id,
427
+ type: 'button',
428
+ style: {
429
+ padding: '4px 10px', borderRadius: 6, fontSize: 12, cursor: 'pointer',
430
+ border: '1px solid ' + (isSelected ? 'var(--primary)' : 'var(--border)'),
431
+ background: isSelected ? 'var(--primary)' : 'var(--bg-secondary)',
432
+ color: isSelected ? '#fff' : 'var(--text-primary)',
433
+ },
434
+ onClick: function() {
435
+ var current = form.assignedAgents || [];
436
+ var next = isSelected ? current.filter(function(x) { return x !== a.id; }) : current.concat(a.id);
437
+ setForm(Object.assign({}, form, { assignedAgents: next }));
438
+ }
439
+ }, a.display_name || a.name);
440
+ })
441
+ ),
442
+ h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 4 } },
443
+ form.assignedAgents && form.assignedAgents.length > 0
444
+ ? form.assignedAgents.length + ' agent(s) selected — only they can use this server'
445
+ : 'No agents selected — all agents can use this server'
446
+ )
403
447
  )
404
448
  ),
405
449
  // Preset templates
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  provision,
9
9
  runSetupWizard
10
- } from "./chunk-TM3CIRVW.js";
10
+ } from "./chunk-PNBWEEJZ.js";
11
11
  import {
12
12
  AgenticMailManager,
13
13
  GoogleEmailProvider,
@@ -28,7 +28,7 @@ import {
28
28
  executeTool,
29
29
  runAgentLoop,
30
30
  toolsToDefinitions
31
- } from "./chunk-4VZAJQUR.js";
31
+ } from "./chunk-RNREJCPG.js";
32
32
  import {
33
33
  ValidationError,
34
34
  auditLogger,
@@ -42,7 +42,7 @@ import {
42
42
  requireRole,
43
43
  securityHeaders,
44
44
  validate
45
- } from "./chunk-EIORALQZ.js";
45
+ } from "./chunk-XWVKQO6P.js";
46
46
  import "./chunk-OF4MUWWS.js";
47
47
  import {
48
48
  PROVIDER_REGISTRY,