@agenticmail/enterprise 0.5.60 → 0.5.62

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/dist/cli.js CHANGED
@@ -48,7 +48,7 @@ Skill Development:
48
48
  break;
49
49
  case "setup":
50
50
  default:
51
- import("./setup-DCQIIXJG.js").then((m) => m.runSetupWizard()).catch(fatal);
51
+ import("./setup-SPKFGFRP.js").then((m) => m.runSetupWizard()).catch(fatal);
52
52
  break;
53
53
  }
54
54
  function fatal(err) {
@@ -1,33 +1,51 @@
1
- import { h, useState, useEffect, Fragment, useApp, apiCall } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, Fragment, useApp, apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { DetailModal } from '../components/modal.js';
4
4
 
5
+ var PAGE_SIZE = 50;
6
+
5
7
  export function AuditPage() {
6
- const [logs, setLogs] = useState([]);
7
- const [loading, setLoading] = useState(true);
8
- const [selected, setSelected] = useState(null);
9
- const [filter, setFilter] = useState('');
8
+ var [logs, setLogs] = useState([]);
9
+ var [loading, setLoading] = useState(true);
10
+ var [selected, setSelected] = useState(null);
11
+ var [filter, setFilter] = useState('');
12
+ var [page, setPage] = useState(0);
13
+ var [total, setTotal] = useState(0);
14
+ var [hasMore, setHasMore] = useState(false);
10
15
 
11
- useEffect(() => {
12
- apiCall('/audit?limit=200').then(d => { var arr = d.events || d.entries || d.logs || d; setLogs(Array.isArray(arr) ? arr : []); setLoading(false); }).catch(() => setLoading(false));
16
+ var loadPage = useCallback(function(p) {
17
+ setLoading(true);
18
+ var offset = p * PAGE_SIZE;
19
+ apiCall('/audit?limit=' + PAGE_SIZE + '&offset=' + offset)
20
+ .then(function(d) {
21
+ var arr = d.events || d.entries || d.logs || d;
22
+ arr = Array.isArray(arr) ? arr : [];
23
+ setLogs(arr);
24
+ setTotal(d.total || arr.length);
25
+ setHasMore(arr.length >= PAGE_SIZE);
26
+ setLoading(false);
27
+ })
28
+ .catch(function() { setLoading(false); });
13
29
  }, []);
14
30
 
15
- // Extract display name: prefer email from details, fall back to actor ID
16
- const actorDisplay = (l) => {
31
+ useEffect(function() { loadPage(0); }, []);
32
+
33
+ var goPage = function(p) { setPage(p); loadPage(p); };
34
+
35
+ var actorDisplay = function(l) {
17
36
  if (l.details && l.details.email) return l.details.email;
18
37
  if (l.actorType === 'system') return 'System';
19
38
  return l.actor || l.userId || l.user || '-';
20
39
  };
21
40
 
22
- // Extract role badge from details
23
- const actorRole = (l) => {
41
+ var actorRole = function(l) {
24
42
  if (l.details && l.details.role) return l.details.role;
25
43
  return l.actorType || null;
26
44
  };
27
45
 
28
- const filtered = filter
29
- ? logs.filter(l => {
30
- const s = filter.toLowerCase();
46
+ var filtered = filter
47
+ ? logs.filter(function(l) {
48
+ var s = filter.toLowerCase();
31
49
  return (l.action || '').toLowerCase().includes(s)
32
50
  || actorDisplay(l).toLowerCase().includes(s)
33
51
  || (l.resource || '').toLowerCase().includes(s)
@@ -35,9 +53,9 @@ export function AuditPage() {
35
53
  })
36
54
  : logs;
37
55
 
38
- const actionColor = (action) => {
56
+ var actionColor = function(action) {
39
57
  if (!action) return 'badge-neutral';
40
- const a = action.toLowerCase();
58
+ var a = action.toLowerCase();
41
59
  if (a.includes('create') || a.includes('add')) return 'badge-success';
42
60
  if (a.includes('delete') || a.includes('remove') || a.includes('revoke')) return 'badge-danger';
43
61
  if (a.includes('update') || a.includes('edit') || a.includes('patch')) return 'badge-warning';
@@ -45,7 +63,7 @@ export function AuditPage() {
45
63
  return 'badge-neutral';
46
64
  };
47
65
 
48
- const roleColor = (role) => {
66
+ var roleColor = function(role) {
49
67
  if (!role) return 'badge-neutral';
50
68
  if (role === 'owner') return 'badge-danger';
51
69
  if (role === 'admin') return 'badge-warning';
@@ -53,12 +71,13 @@ export function AuditPage() {
53
71
  return 'badge-neutral';
54
72
  };
55
73
 
56
- // Friendly resource display: "/api/agents/abc123" → "agents/abc123"
57
- const resourceDisplay = (r) => {
74
+ var resourceDisplay = function(r) {
58
75
  if (!r) return '-';
59
76
  return r.replace(/^\/api\//, '').replace(/^\//, '');
60
77
  };
61
78
 
79
+ var totalPages = Math.max(1, Math.ceil((total || (hasMore ? (page + 2) * PAGE_SIZE : (page + 1) * PAGE_SIZE)) / PAGE_SIZE));
80
+
62
81
  return h(Fragment, null,
63
82
  h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
64
83
  h('div', null,
@@ -66,11 +85,11 @@ export function AuditPage() {
66
85
  h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Complete record of all administrative actions and changes')
67
86
  ),
68
87
  h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
69
- h('span', { style: { fontSize: 12, color: 'var(--text-muted)' } }, filtered.length + ' entries'),
88
+ total > 0 && h('span', { style: { fontSize: 12, color: 'var(--text-muted)' } }, total + ' total'),
70
89
  h('input', {
71
90
  className: 'input', placeholder: 'Filter by action, user, target...',
72
91
  style: { width: 260, fontSize: 13 },
73
- value: filter, onChange: e => setFilter(e.target.value)
92
+ value: filter, onChange: function(e) { setFilter(e.target.value); }
74
93
  })
75
94
  )
76
95
  ),
@@ -88,11 +107,11 @@ export function AuditPage() {
88
107
  h('th', null, 'IP'),
89
108
  h('th', { style: { width: 40 } })
90
109
  )),
91
- h('tbody', null, filtered.map((l, i) =>
92
- h('tr', {
110
+ h('tbody', null, filtered.map(function(l, i) {
111
+ return h('tr', {
93
112
  key: i,
94
113
  style: { cursor: 'pointer' },
95
- onClick: () => setSelected(l),
114
+ onClick: function() { setSelected(l); },
96
115
  title: 'Click to view details'
97
116
  },
98
117
  h('td', { style: { fontSize: 12, color: 'var(--text-muted)', whiteSpace: 'nowrap' } },
@@ -105,17 +124,36 @@ export function AuditPage() {
105
124
  resourceDisplay(l.resource)
106
125
  ),
107
126
  h('td', { style: { fontSize: 12, color: 'var(--text-muted)' } }, l.ip || '-'),
108
- h('td', null, h('button', { className: 'btn btn-ghost btn-icon', style: { padding: 4, fontSize: 14, color: 'var(--text-muted)' }, onClick: e => { e.stopPropagation(); setSelected(l); } }, '\u203A'))
109
- )
110
- ))
127
+ h('td', null, h('button', { className: 'btn btn-ghost btn-icon', style: { padding: 4, fontSize: 14, color: 'var(--text-muted)' }, onClick: function(e) { e.stopPropagation(); setSelected(l); } }, '\u203A'))
128
+ );
129
+ }))
111
130
  )
131
+ ),
132
+
133
+ // Pagination
134
+ (hasMore || page > 0) && h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 16px', borderTop: '1px solid var(--border)', fontSize: 13 } },
135
+ h('span', { style: { color: 'var(--text-muted)' } },
136
+ 'Showing ' + (page * PAGE_SIZE + 1) + '–' + (page * PAGE_SIZE + filtered.length) + (total ? ' of ' + total : '')
137
+ ),
138
+ h('div', { style: { display: 'flex', gap: 4 } },
139
+ h('button', {
140
+ className: 'btn btn-secondary btn-sm',
141
+ disabled: page === 0,
142
+ onClick: function() { goPage(page - 1); }
143
+ }, '\u2190 Previous'),
144
+ h('span', { style: { padding: '4px 12px', fontSize: 12, color: 'var(--text-secondary)' } }, 'Page ' + (page + 1)),
145
+ h('button', {
146
+ className: 'btn btn-secondary btn-sm',
147
+ disabled: !hasMore,
148
+ onClick: function() { goPage(page + 1); }
149
+ }, 'Next \u2192')
150
+ )
112
151
  )
113
152
  ),
114
153
 
115
- // ─── Detail Modal ──────────────────────────────
116
154
  selected && h(DetailModal, {
117
155
  title: 'Audit Entry',
118
- onClose: () => setSelected(null),
156
+ onClose: function() { setSelected(null); },
119
157
  data: {
120
158
  timestamp: selected.timestamp,
121
159
  action: selected.action,
@@ -260,7 +260,8 @@ export function SettingsPage() {
260
260
  h('div', { className: 'card-header' }, h('h3', null, 'Info')),
261
261
  h('div', { className: 'card-body' },
262
262
  h('div', { style: { display: 'grid', gridTemplateColumns: '140px 1fr', gap: '6px 16px', fontSize: 13 } },
263
- h('span', { style: { color: 'var(--text-muted)' } }, 'Organization ID'), h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, settings.id || '-'),
263
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Organization ID'), h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, settings.orgId || settings.id || '-'),
264
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Version'), h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, settings.version || window.__ENTERPRISE_VERSION || '-'),
264
265
  h('span', { style: { color: 'var(--text-muted)' } }, 'Created'), h('span', null, settings.createdAt ? new Date(settings.createdAt).toLocaleString() : '-'),
265
266
  h('span', { style: { color: 'var(--text-muted)' } }, 'Last Updated'), h('span', null, settings.updatedAt ? new Date(settings.updatedAt).toLocaleString() : '-')
266
267
  )
package/dist/index.js CHANGED
@@ -50,11 +50,11 @@ import {
50
50
  requireRole,
51
51
  securityHeaders,
52
52
  validate
53
- } from "./chunk-6PNEB7CI.js";
53
+ } from "./chunk-VMRMCEL7.js";
54
54
  import {
55
55
  provision,
56
56
  runSetupWizard
57
- } from "./chunk-CWFBG45X.js";
57
+ } from "./chunk-M5BY3ZSI.js";
58
58
  import {
59
59
  ENGINE_TABLES,
60
60
  ENGINE_TABLES_POSTGRES,
@@ -0,0 +1,12 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-VMRMCEL7.js";
4
+ import "./chunk-3SMTCIR4.js";
5
+ import "./chunk-JLSQOQ5L.js";
6
+ import "./chunk-RO537U6H.js";
7
+ import "./chunk-DRXMYYKN.js";
8
+ import "./chunk-67KZYSLU.js";
9
+ import "./chunk-KFQGP6VL.js";
10
+ export {
11
+ createServer
12
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-PFSSNZ2W.js";
4
+ import "./chunk-3SMTCIR4.js";
5
+ import "./chunk-JLSQOQ5L.js";
6
+ import "./chunk-RO537U6H.js";
7
+ import "./chunk-DRXMYYKN.js";
8
+ import "./chunk-67KZYSLU.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-L6PN3MGP.js";
10
+ import "./chunk-M4PRT53C.js";
11
+ import "./chunk-KFQGP6VL.js";
12
+ export {
13
+ promptCompanyInfo,
14
+ promptDatabase,
15
+ promptDeployment,
16
+ promptDomain,
17
+ promptRegistration,
18
+ provision,
19
+ runSetupWizard
20
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-M5BY3ZSI.js";
10
+ import "./chunk-M4PRT53C.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.60",
3
+ "version": "0.5.62",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,33 +1,51 @@
1
- import { h, useState, useEffect, Fragment, useApp, apiCall } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, Fragment, useApp, apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { DetailModal } from '../components/modal.js';
4
4
 
5
+ var PAGE_SIZE = 50;
6
+
5
7
  export function AuditPage() {
6
- const [logs, setLogs] = useState([]);
7
- const [loading, setLoading] = useState(true);
8
- const [selected, setSelected] = useState(null);
9
- const [filter, setFilter] = useState('');
8
+ var [logs, setLogs] = useState([]);
9
+ var [loading, setLoading] = useState(true);
10
+ var [selected, setSelected] = useState(null);
11
+ var [filter, setFilter] = useState('');
12
+ var [page, setPage] = useState(0);
13
+ var [total, setTotal] = useState(0);
14
+ var [hasMore, setHasMore] = useState(false);
10
15
 
11
- useEffect(() => {
12
- apiCall('/audit?limit=200').then(d => { var arr = d.events || d.entries || d.logs || d; setLogs(Array.isArray(arr) ? arr : []); setLoading(false); }).catch(() => setLoading(false));
16
+ var loadPage = useCallback(function(p) {
17
+ setLoading(true);
18
+ var offset = p * PAGE_SIZE;
19
+ apiCall('/audit?limit=' + PAGE_SIZE + '&offset=' + offset)
20
+ .then(function(d) {
21
+ var arr = d.events || d.entries || d.logs || d;
22
+ arr = Array.isArray(arr) ? arr : [];
23
+ setLogs(arr);
24
+ setTotal(d.total || arr.length);
25
+ setHasMore(arr.length >= PAGE_SIZE);
26
+ setLoading(false);
27
+ })
28
+ .catch(function() { setLoading(false); });
13
29
  }, []);
14
30
 
15
- // Extract display name: prefer email from details, fall back to actor ID
16
- const actorDisplay = (l) => {
31
+ useEffect(function() { loadPage(0); }, []);
32
+
33
+ var goPage = function(p) { setPage(p); loadPage(p); };
34
+
35
+ var actorDisplay = function(l) {
17
36
  if (l.details && l.details.email) return l.details.email;
18
37
  if (l.actorType === 'system') return 'System';
19
38
  return l.actor || l.userId || l.user || '-';
20
39
  };
21
40
 
22
- // Extract role badge from details
23
- const actorRole = (l) => {
41
+ var actorRole = function(l) {
24
42
  if (l.details && l.details.role) return l.details.role;
25
43
  return l.actorType || null;
26
44
  };
27
45
 
28
- const filtered = filter
29
- ? logs.filter(l => {
30
- const s = filter.toLowerCase();
46
+ var filtered = filter
47
+ ? logs.filter(function(l) {
48
+ var s = filter.toLowerCase();
31
49
  return (l.action || '').toLowerCase().includes(s)
32
50
  || actorDisplay(l).toLowerCase().includes(s)
33
51
  || (l.resource || '').toLowerCase().includes(s)
@@ -35,9 +53,9 @@ export function AuditPage() {
35
53
  })
36
54
  : logs;
37
55
 
38
- const actionColor = (action) => {
56
+ var actionColor = function(action) {
39
57
  if (!action) return 'badge-neutral';
40
- const a = action.toLowerCase();
58
+ var a = action.toLowerCase();
41
59
  if (a.includes('create') || a.includes('add')) return 'badge-success';
42
60
  if (a.includes('delete') || a.includes('remove') || a.includes('revoke')) return 'badge-danger';
43
61
  if (a.includes('update') || a.includes('edit') || a.includes('patch')) return 'badge-warning';
@@ -45,7 +63,7 @@ export function AuditPage() {
45
63
  return 'badge-neutral';
46
64
  };
47
65
 
48
- const roleColor = (role) => {
66
+ var roleColor = function(role) {
49
67
  if (!role) return 'badge-neutral';
50
68
  if (role === 'owner') return 'badge-danger';
51
69
  if (role === 'admin') return 'badge-warning';
@@ -53,12 +71,13 @@ export function AuditPage() {
53
71
  return 'badge-neutral';
54
72
  };
55
73
 
56
- // Friendly resource display: "/api/agents/abc123" → "agents/abc123"
57
- const resourceDisplay = (r) => {
74
+ var resourceDisplay = function(r) {
58
75
  if (!r) return '-';
59
76
  return r.replace(/^\/api\//, '').replace(/^\//, '');
60
77
  };
61
78
 
79
+ var totalPages = Math.max(1, Math.ceil((total || (hasMore ? (page + 2) * PAGE_SIZE : (page + 1) * PAGE_SIZE)) / PAGE_SIZE));
80
+
62
81
  return h(Fragment, null,
63
82
  h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
64
83
  h('div', null,
@@ -66,11 +85,11 @@ export function AuditPage() {
66
85
  h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Complete record of all administrative actions and changes')
67
86
  ),
68
87
  h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
69
- h('span', { style: { fontSize: 12, color: 'var(--text-muted)' } }, filtered.length + ' entries'),
88
+ total > 0 && h('span', { style: { fontSize: 12, color: 'var(--text-muted)' } }, total + ' total'),
70
89
  h('input', {
71
90
  className: 'input', placeholder: 'Filter by action, user, target...',
72
91
  style: { width: 260, fontSize: 13 },
73
- value: filter, onChange: e => setFilter(e.target.value)
92
+ value: filter, onChange: function(e) { setFilter(e.target.value); }
74
93
  })
75
94
  )
76
95
  ),
@@ -88,11 +107,11 @@ export function AuditPage() {
88
107
  h('th', null, 'IP'),
89
108
  h('th', { style: { width: 40 } })
90
109
  )),
91
- h('tbody', null, filtered.map((l, i) =>
92
- h('tr', {
110
+ h('tbody', null, filtered.map(function(l, i) {
111
+ return h('tr', {
93
112
  key: i,
94
113
  style: { cursor: 'pointer' },
95
- onClick: () => setSelected(l),
114
+ onClick: function() { setSelected(l); },
96
115
  title: 'Click to view details'
97
116
  },
98
117
  h('td', { style: { fontSize: 12, color: 'var(--text-muted)', whiteSpace: 'nowrap' } },
@@ -105,17 +124,36 @@ export function AuditPage() {
105
124
  resourceDisplay(l.resource)
106
125
  ),
107
126
  h('td', { style: { fontSize: 12, color: 'var(--text-muted)' } }, l.ip || '-'),
108
- h('td', null, h('button', { className: 'btn btn-ghost btn-icon', style: { padding: 4, fontSize: 14, color: 'var(--text-muted)' }, onClick: e => { e.stopPropagation(); setSelected(l); } }, '\u203A'))
109
- )
110
- ))
127
+ h('td', null, h('button', { className: 'btn btn-ghost btn-icon', style: { padding: 4, fontSize: 14, color: 'var(--text-muted)' }, onClick: function(e) { e.stopPropagation(); setSelected(l); } }, '\u203A'))
128
+ );
129
+ }))
111
130
  )
131
+ ),
132
+
133
+ // Pagination
134
+ (hasMore || page > 0) && h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 16px', borderTop: '1px solid var(--border)', fontSize: 13 } },
135
+ h('span', { style: { color: 'var(--text-muted)' } },
136
+ 'Showing ' + (page * PAGE_SIZE + 1) + '–' + (page * PAGE_SIZE + filtered.length) + (total ? ' of ' + total : '')
137
+ ),
138
+ h('div', { style: { display: 'flex', gap: 4 } },
139
+ h('button', {
140
+ className: 'btn btn-secondary btn-sm',
141
+ disabled: page === 0,
142
+ onClick: function() { goPage(page - 1); }
143
+ }, '\u2190 Previous'),
144
+ h('span', { style: { padding: '4px 12px', fontSize: 12, color: 'var(--text-secondary)' } }, 'Page ' + (page + 1)),
145
+ h('button', {
146
+ className: 'btn btn-secondary btn-sm',
147
+ disabled: !hasMore,
148
+ onClick: function() { goPage(page + 1); }
149
+ }, 'Next \u2192')
150
+ )
112
151
  )
113
152
  ),
114
153
 
115
- // ─── Detail Modal ──────────────────────────────
116
154
  selected && h(DetailModal, {
117
155
  title: 'Audit Entry',
118
- onClose: () => setSelected(null),
156
+ onClose: function() { setSelected(null); },
119
157
  data: {
120
158
  timestamp: selected.timestamp,
121
159
  action: selected.action,
@@ -260,7 +260,8 @@ export function SettingsPage() {
260
260
  h('div', { className: 'card-header' }, h('h3', null, 'Info')),
261
261
  h('div', { className: 'card-body' },
262
262
  h('div', { style: { display: 'grid', gridTemplateColumns: '140px 1fr', gap: '6px 16px', fontSize: 13 } },
263
- h('span', { style: { color: 'var(--text-muted)' } }, 'Organization ID'), h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, settings.id || '-'),
263
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Organization ID'), h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, settings.orgId || settings.id || '-'),
264
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Version'), h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, settings.version || window.__ENTERPRISE_VERSION || '-'),
264
265
  h('span', { style: { color: 'var(--text-muted)' } }, 'Created'), h('span', null, settings.createdAt ? new Date(settings.createdAt).toLocaleString() : '-'),
265
266
  h('span', { style: { color: 'var(--text-muted)' } }, 'Last Updated'), h('span', null, settings.updatedAt ? new Date(settings.updatedAt).toLocaleString() : '-')
266
267
  )
package/src/server.ts CHANGED
@@ -319,6 +319,23 @@ export function createServer(config: ServerConfig): ServerInstance {
319
319
 
320
320
  async function serveDashboard(c: any) {
321
321
  let html = getDashboardHtml();
322
+ // Inject version — try multiple paths
323
+ let _version = '';
324
+ for (const rel of ['../package.json', './package.json', '../../package.json']) {
325
+ if (_version) break;
326
+ try {
327
+ const p = join(dirname(fileURLToPath(import.meta.url)), rel);
328
+ _version = JSON.parse(readFileSync(p, 'utf-8')).version;
329
+ } catch { /* try next */ }
330
+ }
331
+ if (!_version) {
332
+ // Fallback: search from cwd
333
+ try { _version = JSON.parse(readFileSync(join(process.cwd(), 'node_modules', '@agenticmail', 'enterprise', 'package.json'), 'utf-8')).version; } catch { /* noop */ }
334
+ }
335
+ if (_version) {
336
+ html = html.replace('</head>', `<script>window.__ENTERPRISE_VERSION__="${_version}";</script></head>`);
337
+ }
338
+
322
339
  if (!_setupComplete) {
323
340
  const injection = `<script>window.__EM_SETUP_STATE__=${JSON.stringify({ needsBootstrap: true })};</script>`;
324
341
  html = html.replace('</head>', injection + '</head>');