@agenticmail/enterprise 0.5.14 → 0.5.16

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,47 @@
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-7PFGWQMJ.js";
18
+ import {
19
+ PROVIDER_REGISTRY,
20
+ listAllProviders,
21
+ resolveApiKeyForProvider,
22
+ resolveProvider
23
+ } from "./chunk-ZNR5DDTA.js";
24
+ import "./chunk-TYW5XTOW.js";
25
+ import "./chunk-JLSQOQ5L.js";
26
+ import "./chunk-KFQGP6VL.js";
27
+ export {
28
+ AgentRuntime,
29
+ EmailChannel,
30
+ FollowUpScheduler,
31
+ PROVIDER_REGISTRY,
32
+ SessionManager,
33
+ SubAgentManager,
34
+ ToolRegistry,
35
+ callLLM,
36
+ createAgentRuntime,
37
+ createNoopHooks,
38
+ createRuntimeHooks,
39
+ estimateMessageTokens,
40
+ estimateTokens,
41
+ executeTool,
42
+ listAllProviders,
43
+ resolveApiKeyForProvider,
44
+ resolveProvider,
45
+ runAgentLoop,
46
+ toolsToDefinitions
47
+ };
@@ -0,0 +1,11 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-LJNMWZ7Z.js";
4
+ import "./chunk-ZNR5DDTA.js";
5
+ import "./chunk-RO537U6H.js";
6
+ import "./chunk-DRXMYYKN.js";
7
+ import "./chunk-JLSQOQ5L.js";
8
+ import "./chunk-KFQGP6VL.js";
9
+ export {
10
+ createServer
11
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-TXWPXWDR.js";
10
+ import "./chunk-6TDW6ZNI.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.14",
3
+ "version": "0.5.16",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -48,6 +48,10 @@ export function SettingsPage() {
48
48
  var newProvider = _newProvider[0]; var setNewProvider = _newProvider[1];
49
49
  var _discoverResults = useState({});
50
50
  var discoverResults = _discoverResults[0]; var setDiscoverResults = _discoverResults[1];
51
+ var _apiKeyModal = useState(null); // { providerId, providerName, isUpdate }
52
+ var apiKeyModal = _apiKeyModal[0]; var setApiKeyModal = _apiKeyModal[1];
53
+ var _apiKeyInput = useState('');
54
+ var apiKeyInput = _apiKeyInput[0]; var setApiKeyInput = _apiKeyInput[1];
51
55
 
52
56
  useEffect(() => {
53
57
  apiCall('/settings').then(d => { const s = d.settings || d || {}; setSettings(s); if (s.primaryColor) applyBrandColor(s.primaryColor); }).catch(() => {});
@@ -558,6 +562,10 @@ export function SettingsPage() {
558
562
  setNewProvider: setNewProvider,
559
563
  discoverResults: discoverResults,
560
564
  setDiscoverResults: setDiscoverResults,
565
+ apiKeyModal: apiKeyModal,
566
+ setApiKeyModal: setApiKeyModal,
567
+ apiKeyInput: apiKeyInput,
568
+ setApiKeyInput: setApiKeyInput,
561
569
  onSave: function() {
562
570
  setPricingSaving(true);
563
571
  apiCall('/settings/model-pricing', { method: 'PUT', body: JSON.stringify(pricing) }).then(function(d) {
@@ -1315,22 +1323,14 @@ function ProvidersSection(props) {
1315
1323
  ? h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 } },
1316
1324
  h('span', { style: { color: 'var(--success, #16a34a)' } }, '✓ API key configured via environment'),
1317
1325
  h('button', { className: 'btn btn-sm btn-ghost', style: { padding: '2px 8px', fontSize: 11 }, onClick: function() {
1318
- var key = prompt('Enter new API key for ' + p.name + ' (leave empty to keep current):');
1319
- if (key && key.trim()) {
1320
- apiCall('/providers/' + p.id + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: key.trim() }) })
1321
- .then(function() { toast('API key updated for ' + p.name + '. Restart required.', 'success'); window.location.reload(); })
1322
- .catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
1323
- }
1326
+ setApiKeyInput('');
1327
+ setApiKeyModal({ providerId: p.id, providerName: p.name, isUpdate: true });
1324
1328
  }}, 'Update Key')
1325
1329
  )
1326
1330
  : h('div', null,
1327
1331
  h('button', { className: 'btn btn-sm btn-primary', onClick: function() {
1328
- var key = prompt('Enter your ' + p.name + ' API key:');
1329
- if (key && key.trim()) {
1330
- apiCall('/providers/' + p.id + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: key.trim() }) })
1331
- .then(function() { toast('API key saved for ' + p.name + '!', 'success'); window.location.reload(); })
1332
- .catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
1333
- }
1332
+ setApiKeyInput('');
1333
+ setApiKeyModal({ providerId: p.id, providerName: p.name, isUpdate: false });
1334
1334
  }}, '🔑 Add API Key')
1335
1335
  )
1336
1336
  ),
@@ -1401,6 +1401,52 @@ function ProvidersSection(props) {
1401
1401
  h('button', { className: 'btn', onClick: function() { props.setShowAddProvider(false); } }, 'Cancel'),
1402
1402
  h('button', { className: 'btn btn-primary', onClick: handleAddProvider }, 'Add Provider')
1403
1403
  )
1404
+ ),
1405
+
1406
+ // API Key Modal
1407
+ props.apiKeyModal && h(Modal, {
1408
+ title: (props.apiKeyModal.isUpdate ? 'Update' : 'Add') + ' API Key — ' + props.apiKeyModal.providerName,
1409
+ onClose: function() { props.setApiKeyModal(null); props.setApiKeyInput(''); },
1410
+ },
1411
+ h('div', { style: { marginBottom: 16 } },
1412
+ h('p', { style: { color: 'var(--text-secondary)', fontSize: 13, margin: '0 0 16px 0', lineHeight: 1.5 } },
1413
+ props.apiKeyModal.isUpdate
1414
+ ? 'Enter a new API key to replace the current one for ' + props.apiKeyModal.providerName + '.'
1415
+ : 'Enter your ' + props.apiKeyModal.providerName + ' API key to enable this provider.'
1416
+ ),
1417
+ h('label', { className: 'form-label' }, 'API Key'),
1418
+ h('input', {
1419
+ className: 'input',
1420
+ type: 'password',
1421
+ placeholder: 'sk-...',
1422
+ value: props.apiKeyInput,
1423
+ autoFocus: true,
1424
+ onChange: function(e) { props.setApiKeyInput(e.target.value); },
1425
+ onKeyDown: function(e) {
1426
+ if (e.key === 'Enter' && props.apiKeyInput.trim()) {
1427
+ var m = props.apiKeyModal;
1428
+ apiCall('/providers/' + m.providerId + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: props.apiKeyInput.trim() }) })
1429
+ .then(function() { toast((m.isUpdate ? 'API key updated' : 'API key saved') + ' for ' + m.providerName + '!', 'success'); props.setApiKeyModal(null); props.setApiKeyInput(''); window.location.reload(); })
1430
+ .catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
1431
+ }
1432
+ },
1433
+ style: { fontSize: 14, fontFamily: 'var(--font-mono, monospace)' },
1434
+ }),
1435
+ h('p', { className: 'form-help', style: { marginTop: 6 } }, 'Your key is stored encrypted and never exposed in the dashboard.')
1436
+ ),
1437
+ h('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: 8 } },
1438
+ h('button', { className: 'btn', onClick: function() { props.setApiKeyModal(null); props.setApiKeyInput(''); } }, 'Cancel'),
1439
+ h('button', {
1440
+ className: 'btn btn-primary',
1441
+ disabled: !props.apiKeyInput.trim(),
1442
+ onClick: function() {
1443
+ var m = props.apiKeyModal;
1444
+ apiCall('/providers/' + m.providerId + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: props.apiKeyInput.trim() }) })
1445
+ .then(function() { toast((m.isUpdate ? 'API key updated' : 'API key saved') + ' for ' + m.providerName + '!', 'success'); props.setApiKeyModal(null); props.setApiKeyInput(''); window.location.reload(); })
1446
+ .catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
1447
+ }
1448
+ }, props.apiKeyModal.isUpdate ? 'Update Key' : 'Save Key')
1449
+ )
1404
1450
  )
1405
1451
  );
1406
1452
  }
@@ -1434,6 +1480,10 @@ function ModelPricingTab(props) {
1434
1480
  discoverResults: props.discoverResults,
1435
1481
  setDiscoverResults: props.setDiscoverResults,
1436
1482
  toast: props.toast,
1483
+ apiKeyModal: props.apiKeyModal,
1484
+ setApiKeyModal: props.setApiKeyModal,
1485
+ apiKeyInput: props.apiKeyInput,
1486
+ setApiKeyInput: props.setApiKeyInput,
1437
1487
  }),
1438
1488
 
1439
1489
  // Divider
@@ -11,6 +11,11 @@
11
11
  import { createHash, randomBytes, createCipheriv, createDecipheriv, pbkdf2Sync } from 'crypto';
12
12
  import type { EngineDatabase } from './db-adapter.js';
13
13
 
14
+ function safeJsonParse(val: string | null | undefined, fallback: any = {}): any {
15
+ if (!val) return fallback;
16
+ try { return JSON.parse(val); } catch { return fallback; }
17
+ }
18
+
14
19
  // ─── Types ──────────────────────────────────────────────
15
20
 
16
21
  export interface VaultConfig {
@@ -113,7 +118,7 @@ export class SecureVault {
113
118
  name: r.name,
114
119
  category: r.category,
115
120
  encryptedValue: r.encrypted_value,
116
- metadata: JSON.parse(r.metadata || '{}'),
121
+ metadata: safeJsonParse(r.metadata),
117
122
  createdBy: r.created_by,
118
123
  createdAt: r.created_at,
119
124
  updatedAt: r.updated_at,
@@ -415,7 +420,7 @@ export class SecureVault {
415
420
  const rows = await this.engineDb.query<any>('SELECT * FROM deploy_credentials');
416
421
 
417
422
  for (const row of rows) {
418
- const config = JSON.parse(row.config || '{}');
423
+ const config = safeJsonParse(row.config);
419
424
 
420
425
  // Skip already-encrypted configs
421
426
  if (config._encrypted) continue;
@@ -514,7 +519,7 @@ export class SecureVault {
514
519
  action: r.action,
515
520
  actor: r.actor,
516
521
  ip: r.ip || undefined,
517
- metadata: JSON.parse(r.metadata || '{}'),
522
+ metadata: safeJsonParse(r.metadata),
518
523
  createdAt: r.created_at,
519
524
  }));
520
525
  } catch {