@agenticmail/enterprise 0.5.305 → 0.5.306

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.
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } , apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { HelpButton } from '../components/help-button.js';
4
4
  import { useOrgContext } from '../components/org-switcher.js';
@@ -104,7 +104,7 @@ export function GuardrailsPage() {
104
104
  var _ag = useState([]);
105
105
  var agents = _ag[0]; var setAgents = _ag[1];
106
106
  useEffect(function() {
107
- engineCall('/agents?orgId=' + effectiveOrgId).then(function(d) { setAgents(d.agents || []); }).catch(function() {});
107
+ apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).then(function(d) { setAgents(d.agents || []); }).catch(function() {});
108
108
  }, []);
109
109
 
110
110
  var TABS = [
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, Fragment, useApp, engineCall, buildAgentEmailMap, buildAgentDataMap, resolveAgentEmail, renderAgentBadge, getOrgId } from '../components/utils.js';
1
+ import { h, useState, useEffect, Fragment, useApp, engineCall, buildAgentEmailMap, buildAgentDataMap, resolveAgentEmail, renderAgentBadge, getOrgId } , apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { HelpButton } from '../components/help-button.js';
4
4
  import { useOrgContext } from '../components/org-switcher.js';
@@ -16,7 +16,7 @@ export function JournalPage() {
16
16
  const load = () => {
17
17
  engineCall('/journal?orgId=' + effectiveOrgId + '&limit=50').then(d => { setEntries(d.entries || []); setTotal(d.total || 0); }).catch(() => {});
18
18
  engineCall('/journal/stats/default').then(d => setStats(d)).catch(() => {});
19
- engineCall('/agents?orgId=' + effectiveOrgId).then(d => setAgents(d.agents || [])).catch(() => {});
19
+ apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).then(d => setAgents(d.agents || [])).catch(() => {});
20
20
  };
21
21
  useEffect(load, []);
22
22
 
@@ -42,7 +42,7 @@ export function KnowledgeContributionsPage() {
42
42
  var [searchAgentFilter, setSearchAgentFilter] = useState('');
43
43
 
44
44
  // Effective org ID: uses client org if selected, else default
45
- var effectiveOrgId = orgCtx.selectedOrgId || effectiveOrgId;
45
+ var effectiveOrgId = orgCtx.selectedOrgId || getOrgId();
46
46
 
47
47
  var loadBases = useCallback(function() {
48
48
  Promise.all([
@@ -17,7 +17,7 @@ export function KnowledgeBasePage() {
17
17
  const [chunks, setChunks] = useState([]);
18
18
  const [selectedDoc, setSelectedDoc] = useState(null);
19
19
  const [editing, setEditing] = useState(false);
20
- const [editForm, setEditForm] = useState({ name: '', description: '' });
20
+ const [editForm, setEditForm] = useState({ name: '', description: '', clientOrgId: '' });
21
21
  const [loading, setLoading] = useState(false);
22
22
  const [showImport, setShowImport] = useState(false);
23
23
  const [importKb, setImportKb] = useState(null);
@@ -54,7 +54,7 @@ export function KnowledgeBasePage() {
54
54
  setDocs(kbData.documents || []);
55
55
  setChunks([]);
56
56
  setSelectedDoc(null);
57
- setEditForm({ name: kbData.name || '', description: kbData.description || '' });
57
+ setEditForm({ name: kbData.name || '', description: kbData.description || '', clientOrgId: kbData.clientOrgId || '' });
58
58
  } catch (e) {
59
59
  toast('Failed to load knowledge base: ' + e.message, 'error');
60
60
  }
@@ -122,9 +122,9 @@ export function KnowledgeBasePage() {
122
122
  const saveEdit = async () => {
123
123
  if (!selected) return;
124
124
  try {
125
- await engineCall('/knowledge-bases/' + selected.id, { method: 'PUT', body: JSON.stringify({ name: editForm.name, description: editForm.description }) });
125
+ await engineCall('/knowledge-bases/' + selected.id, { method: 'PUT', body: JSON.stringify({ name: editForm.name, description: editForm.description, clientOrgId: editForm.clientOrgId || null }) });
126
126
  toast('Knowledge base updated', 'success');
127
- setSelected(s => ({ ...s, name: editForm.name, description: editForm.description }));
127
+ setSelected(s => ({ ...s, name: editForm.name, description: editForm.description, clientOrgId: editForm.clientOrgId }));
128
128
  setEditing(false);
129
129
  load();
130
130
  } catch (e) { toast(e.message, 'error'); }
@@ -171,7 +171,16 @@ export function KnowledgeBasePage() {
171
171
  h('div', { className: 'card', style: { marginBottom: 16 } },
172
172
  h('div', { className: 'card-body' },
173
173
  editing
174
- ? h('textarea', { className: 'input', rows: 3, value: editForm.description, onChange: e => setEditForm(f => ({ ...f, description: e.target.value })), placeholder: 'Knowledge base description...' })
174
+ ? h(Fragment, null,
175
+ h('textarea', { className: 'input', rows: 3, value: editForm.description, onChange: e => setEditForm(f => ({ ...f, description: e.target.value })), placeholder: 'Knowledge base description...', style: { marginBottom: 8 } }),
176
+ clientOrgs.length > 0 && h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
177
+ h('label', { style: { fontSize: 12, fontWeight: 600, whiteSpace: 'nowrap' } }, 'Organization:'),
178
+ h('select', { className: 'input', value: editForm.clientOrgId, onChange: e => setEditForm(f => ({ ...f, clientOrgId: e.target.value })), style: { fontSize: 12, maxWidth: 250 } },
179
+ h('option', { value: '' }, 'My Organization (internal)'),
180
+ clientOrgs.filter(o => o.is_active !== false).map(o => h('option', { key: o.id, value: o.id }, o.name))
181
+ )
182
+ )
183
+ )
175
184
  : h('p', { style: { color: 'var(--text-secondary)', fontSize: 13, margin: 0 } }, selected.description || 'No description'),
176
185
  h('div', { style: { display: 'flex', gap: 12, marginTop: 12, fontSize: 12, color: 'var(--text-muted)' } },
177
186
  h('span', null, 'ID: ', h('code', null, selected.id)),
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, useRef, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } from '../components/utils.js';
1
+ import { h, useState, useEffect, useRef, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } , apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { HelpButton } from '../components/help-button.js';
4
4
  import { useOrgContext } from '../components/org-switcher.js';
@@ -22,7 +22,7 @@ export function MessagesPage() {
22
22
  engineCall('/messages?orgId=' + effectiveOrgId + '&limit=100').then(d => setMessages(d.messages || [])).catch(() => {});
23
23
  };
24
24
  const loadAgents = () => {
25
- engineCall('/agents?orgId=' + effectiveOrgId).then(d => setAgents(d.agents || [])).catch(() => {});
25
+ apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).then(d => setAgents(d.agents || [])).catch(() => {});
26
26
  };
27
27
  const loadTopology = () => {
28
28
  engineCall('/messages/topology?orgId=' + effectiveOrgId).then(d => setTopology(d.topology || null)).catch(() => {});
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, useCallback, useRef, Fragment, useApp, engineCall, getOrgId } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, useRef, Fragment, useApp, engineCall, getOrgId } , apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { HelpButton } from '../components/help-button.js';
4
4
  import { useOrgContext } from '../components/org-switcher.js';
@@ -154,7 +154,7 @@ export function OrgChartPage() {
154
154
  setLoading(true); setError(null);
155
155
  Promise.all([
156
156
  engineCall('/hierarchy/org-chart').catch(function() { return null; }),
157
- engineCall('/agents?orgId=' + effectiveOrgId).catch(function() { return { agents: [] }; }),
157
+ apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).catch(function() { return { agents: [] }; }),
158
158
  ]).then(function(res) {
159
159
  var hierRes = res[0]; var agentRes = res[1];
160
160
  var avatarMap = {};
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, useCallback, useRef, Fragment, useApp, engineCall, getOrgId } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, useRef, Fragment, useApp, engineCall, getOrgId } , apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { HelpButton } from '../components/help-button.js';
4
4
  import { useOrgContext } from '../components/org-switcher.js';
@@ -440,7 +440,7 @@ export function TaskPipelinePage() {
440
440
  var app = useApp();
441
441
  var toast = app.toast;
442
442
  var orgCtx = useOrgContext();
443
- var effectiveOrgId = orgCtx.selectedOrgId || effectiveOrgId;
443
+ var effectiveOrgId = orgCtx.selectedOrgId || getOrgId();
444
444
  var _tasks = useState([]);
445
445
  var tasks = _tasks[0]; var setTasks = _tasks[1];
446
446
  var _stats = useState({ created: 0, assigned: 0, inProgress: 0, completed: 0, failed: 0, cancelled: 0, total: 0, todayCompleted: 0, todayFailed: 0, todayCreated: 0, avgDurationMs: 0, totalCost: 0, totalTokens: 0, topAgents: [] });
@@ -477,16 +477,26 @@ export function TaskPipelinePage() {
477
477
  Promise.all([
478
478
  engineCall('/task-pipeline?limit=200'),
479
479
  engineCall('/task-pipeline/stats'),
480
- engineCall('/agents?orgId=' + effectiveOrgId).catch(function() { return { agents: [] }; }),
480
+ apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).catch(function() { return { agents: [] }; }),
481
481
  ]).then(function(res) {
482
- setTasks(res[0]?.tasks || []);
483
- setStats(res[1] || stats);
482
+ var allTasks = res[0]?.tasks || [];
483
+ var orgAgents = res[2]?.agents || [];
484
484
  // Build agent avatar/name map
485
485
  var map = {};
486
- (res[2]?.agents || []).forEach(function(a) {
487
- map[a.id] = { name: a.config?.name || a.id, avatar: a.config?.identity?.avatar || a.config?.avatar || a.config?.persona?.avatar || null };
486
+ orgAgents.forEach(function(a) {
487
+ map[a.id] = { name: a.config?.name || a.name || a.id, avatar: a.config?.identity?.avatar || a.config?.avatar || a.config?.persona?.avatar || null };
488
488
  });
489
489
  setAgentMap(map);
490
+ // Filter tasks by org's agents when org is selected
491
+ if (orgCtx.selectedOrgId && orgAgents.length > 0) {
492
+ var agentIds = {};
493
+ orgAgents.forEach(function(a) { agentIds[a.id] = true; });
494
+ allTasks = allTasks.filter(function(t) { return agentIds[t.assignedAgent] || agentIds[t.createdBy]; });
495
+ } else if (orgCtx.selectedOrgId && orgAgents.length === 0) {
496
+ allTasks = []; // No agents in this org = no tasks
497
+ }
498
+ setTasks(allTasks);
499
+ setStats(res[1] || stats);
490
500
  }).catch(function(err) { console.error('[TaskPipeline]', err); })
491
501
  .finally(function() { setLoading(false); });
492
502
  }, [effectiveOrgId]);
@@ -494,6 +494,21 @@ export function UsersPage() {
494
494
  setResetting(false);
495
495
  };
496
496
 
497
+ var openEditUser = function(u) {
498
+ setEditUser(u);
499
+ setEditForm({ name: u.name || '', role: u.role || 'viewer', clientOrgId: u.clientOrgId || '' });
500
+ };
501
+
502
+ var doEditUser = async function() {
503
+ if (!editUser) return;
504
+ try {
505
+ await apiCall('/users/' + editUser.id, { method: 'PATCH', body: JSON.stringify({ name: editForm.name, role: editForm.role, clientOrgId: editForm.clientOrgId || null }) });
506
+ toast('User updated', 'success');
507
+ setEditUser(null);
508
+ load();
509
+ } catch (e) { toast(e.message || 'Update failed', 'error'); }
510
+ };
511
+
497
512
  var toggleActive = async function(user) {
498
513
  var action = user.isActive === false ? 'reactivate' : 'deactivate';
499
514
  var ok = await showConfirm({
@@ -515,6 +530,8 @@ export function UsersPage() {
515
530
  var [deleteStep, setDeleteStep] = useState(0);
516
531
  var [deleteTarget, setDeleteTarget] = useState(null);
517
532
  var [deleteTyped, setDeleteTyped] = useState('');
533
+ var [editUser, setEditUser] = useState(null);
534
+ var [editForm, setEditForm] = useState({ name: '', role: '', clientOrgId: '' });
518
535
 
519
536
  var startDelete = function(user) { setDeleteTarget(user); setDeleteStep(1); setDeleteTyped(''); };
520
537
  var cancelDelete = function() { setDeleteTarget(null); setDeleteStep(0); setDeleteTyped(''); };
@@ -655,6 +672,52 @@ export function UsersPage() {
655
672
  ),
656
673
 
657
674
  // Permission editor modal
675
+ // Edit User modal
676
+ editUser && h(Modal, {
677
+ title: 'Edit User — ' + (editUser.name || editUser.email),
678
+ onClose: function() { setEditUser(null); },
679
+ width: 420,
680
+ footer: h(Fragment, null,
681
+ h('button', { className: 'btn btn-secondary', onClick: function() { setEditUser(null); } }, 'Cancel'),
682
+ h('button', { className: 'btn btn-primary', onClick: doEditUser }, 'Save Changes')
683
+ )
684
+ },
685
+ h('div', { className: 'form-group' },
686
+ h('label', { className: 'form-label' }, 'Name'),
687
+ h('input', { className: 'input', value: editForm.name, onChange: function(e) { setEditForm(function(f) { return Object.assign({}, f, { name: e.target.value }); }); } })
688
+ ),
689
+ h('div', { className: 'form-group' },
690
+ h('label', { className: 'form-label' }, 'Role'),
691
+ h('select', { className: 'input', value: editForm.role, onChange: function(e) { setEditForm(function(f) { return Object.assign({}, f, { role: e.target.value }); }); } },
692
+ h('option', { value: 'viewer' }, 'Viewer'),
693
+ h('option', { value: 'member' }, 'Member'),
694
+ h('option', { value: 'admin' }, 'Admin'),
695
+ h('option', { value: 'owner' }, 'Owner')
696
+ ),
697
+ h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 4 } },
698
+ editForm.role === 'owner' ? 'Full access to everything. Cannot be restricted.' :
699
+ editForm.role === 'admin' ? 'Full access by default. Can be restricted via permissions.' :
700
+ editForm.role === 'member' ? 'Access controlled by permissions. Can view and act on assigned pages.' :
701
+ 'Read-only access. Can view but not modify.'
702
+ )
703
+ ),
704
+ clientOrgs.length > 0 && h('div', { className: 'form-group' },
705
+ h('label', { className: 'form-label' }, 'Client Organization'),
706
+ h('select', { className: 'input', value: editForm.clientOrgId, onChange: function(e) { setEditForm(function(f) { return Object.assign({}, f, { clientOrgId: e.target.value }); }); } },
707
+ h('option', { value: '' }, 'None (Internal User)'),
708
+ clientOrgs.filter(function(o) { return o.is_active !== false; }).map(function(o) {
709
+ return h('option', { key: o.id, value: o.id }, o.name);
710
+ })
711
+ ),
712
+ editForm.clientOrgId && h('div', { style: { fontSize: 11, color: 'var(--warning, #f59e0b)', marginTop: 4 } },
713
+ 'This user will only see agents and data from this organization.'
714
+ )
715
+ ),
716
+ h('div', { style: { fontSize: 12, color: 'var(--text-muted)', padding: '8px 0', borderTop: '1px solid var(--border)', marginTop: 8 } },
717
+ 'Email: ', h('code', null, editUser.email), ' (cannot be changed)'
718
+ )
719
+ ),
720
+
658
721
  permTarget && pageRegistry && h(PermissionEditor, {
659
722
  userId: permTarget.id,
660
723
  userName: permTarget.name || permTarget.email,
@@ -768,6 +831,7 @@ export function UsersPage() {
768
831
  h('td', { style: { fontSize: 12, color: 'var(--text-muted)' } }, u.createdAt ? new Date(u.createdAt).toLocaleDateString() : '-'),
769
832
  h('td', null,
770
833
  h('div', { style: { display: 'flex', gap: 4 } },
834
+ h('button', { className: 'btn btn-ghost btn-sm', title: 'Edit User', onClick: function() { openEditUser(u); } }, I.edit()),
771
835
  h('button', {
772
836
  className: 'btn btn-ghost btn-sm',
773
837
  title: isRestricted ? 'Edit Permissions' : 'Permissions (Owner/Admin have full access)',
@@ -1,4 +1,4 @@
1
- import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } from '../components/utils.js';
1
+ import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } , apiCall } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { TimezoneSelect } from '../components/timezones.js';
4
4
  import { HelpButton } from '../components/help-button.js';
@@ -47,7 +47,7 @@ export function WorkforcePage() {
47
47
  setSchedules(schedulesRes.schedules || []);
48
48
  setBudgetData(budgetRes);
49
49
  setClockRecords(recordsRes.records || []);
50
- engineCall('/agents?orgId=' + effectiveOrgId).then(d => setAgents(d.agents || [])).catch(() => {});
50
+ apiCall('/agents' + (orgCtx.selectedOrgId ? '?clientOrgId=' + orgCtx.selectedOrgId : '')).then(d => setAgents(d.agents || [])).catch(() => {});
51
51
  } catch (err) { toast('Failed to load workforce data', 'error'); }
52
52
  setLoading(false);
53
53
  };