@agenticmail/enterprise 0.5.199 → 0.5.201

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.
Files changed (110) hide show
  1. package/dist/agent-heartbeat-EGMBRD3R.js +510 -0
  2. package/dist/chunk-5C3SCMY5.js +4457 -0
  3. package/dist/chunk-6OZYUTPL.js +1224 -0
  4. package/dist/chunk-ZR4Z42HT.js +3679 -0
  5. package/dist/cli-agent-PLMDHMRR.js +1602 -0
  6. package/dist/cli-serve-PLBAWN7N.js +114 -0
  7. package/dist/cli.js +3 -3
  8. package/dist/dashboard/app.js +3 -0
  9. package/dist/dashboard/components/icons.js +1 -0
  10. package/dist/dashboard/pages/activity.js +14 -1
  11. package/dist/dashboard/pages/agent-detail/activity.js +17 -1
  12. package/dist/dashboard/pages/agent-detail/autonomy.js +17 -1
  13. package/dist/dashboard/pages/agent-detail/budget.js +25 -2
  14. package/dist/dashboard/pages/agent-detail/channels.js +10 -1
  15. package/dist/dashboard/pages/agent-detail/communication.js +10 -1
  16. package/dist/dashboard/pages/agent-detail/configuration.js +42 -1
  17. package/dist/dashboard/pages/agent-detail/deployment.js +147 -16
  18. package/dist/dashboard/pages/agent-detail/email.js +10 -1
  19. package/dist/dashboard/pages/agent-detail/guardrails.js +27 -3
  20. package/dist/dashboard/pages/agent-detail/manager.js +15 -1
  21. package/dist/dashboard/pages/agent-detail/meeting-browser.js +14 -2
  22. package/dist/dashboard/pages/agent-detail/memory.js +24 -5
  23. package/dist/dashboard/pages/agent-detail/overview.js +159 -21
  24. package/dist/dashboard/pages/agent-detail/permissions.js +28 -7
  25. package/dist/dashboard/pages/agent-detail/personal-details.js +17 -1
  26. package/dist/dashboard/pages/agent-detail/security.js +21 -5
  27. package/dist/dashboard/pages/agent-detail/skills-section.js +9 -1
  28. package/dist/dashboard/pages/agent-detail/tool-security.js +35 -8
  29. package/dist/dashboard/pages/agent-detail/tools.js +10 -1
  30. package/dist/dashboard/pages/agent-detail/whatsapp.js +11 -1
  31. package/dist/dashboard/pages/agent-detail/workforce.js +19 -4
  32. package/dist/dashboard/pages/agents.js +15 -1
  33. package/dist/dashboard/pages/approvals.js +15 -1
  34. package/dist/dashboard/pages/audit.js +23 -1
  35. package/dist/dashboard/pages/compliance.js +24 -2
  36. package/dist/dashboard/pages/dashboard.js +25 -6
  37. package/dist/dashboard/pages/dlp.js +23 -2
  38. package/dist/dashboard/pages/domain-status.js +51 -7
  39. package/dist/dashboard/pages/guardrails.js +29 -3
  40. package/dist/dashboard/pages/journal.js +24 -4
  41. package/dist/dashboard/pages/knowledge-contributions.js +69 -3
  42. package/dist/dashboard/pages/knowledge-import.js +6 -1
  43. package/dist/dashboard/pages/knowledge.js +51 -9
  44. package/dist/dashboard/pages/messages.js +28 -5
  45. package/dist/dashboard/pages/org-chart.js +18 -1
  46. package/dist/dashboard/pages/settings.js +30 -6
  47. package/dist/dashboard/pages/skill-connections.js +18 -4
  48. package/dist/dashboard/pages/skills.js +11 -1
  49. package/dist/dashboard/pages/task-pipeline.js +455 -0
  50. package/dist/dashboard/pages/users.js +14 -1
  51. package/dist/dashboard/pages/vault.js +22 -2
  52. package/dist/dashboard/pages/workforce.js +17 -1
  53. package/dist/index.js +3 -3
  54. package/dist/routes-KHABOHOV.js +13273 -0
  55. package/dist/runtime-6WFHCG3N.js +45 -0
  56. package/dist/server-BENJQHTB.js +15 -0
  57. package/dist/setup-7RQIFV5Y.js +20 -0
  58. package/package.json +1 -1
  59. package/src/dashboard/HELP-TOOLTIPS-GUIDE.md +45 -0
  60. package/src/dashboard/app.js +3 -0
  61. package/src/dashboard/components/icons.js +1 -0
  62. package/src/dashboard/pages/activity.js +14 -1
  63. package/src/dashboard/pages/agent-detail/activity.js +17 -1
  64. package/src/dashboard/pages/agent-detail/autonomy.js +17 -1
  65. package/src/dashboard/pages/agent-detail/budget.js +25 -2
  66. package/src/dashboard/pages/agent-detail/channels.js +10 -1
  67. package/src/dashboard/pages/agent-detail/communication.js +10 -1
  68. package/src/dashboard/pages/agent-detail/configuration.js +42 -1
  69. package/src/dashboard/pages/agent-detail/deployment.js +147 -16
  70. package/src/dashboard/pages/agent-detail/email.js +10 -1
  71. package/src/dashboard/pages/agent-detail/guardrails.js +27 -3
  72. package/src/dashboard/pages/agent-detail/manager.js +15 -1
  73. package/src/dashboard/pages/agent-detail/meeting-browser.js +14 -2
  74. package/src/dashboard/pages/agent-detail/memory.js +24 -5
  75. package/src/dashboard/pages/agent-detail/overview.js +159 -21
  76. package/src/dashboard/pages/agent-detail/permissions.js +28 -7
  77. package/src/dashboard/pages/agent-detail/personal-details.js +17 -1
  78. package/src/dashboard/pages/agent-detail/security.js +21 -5
  79. package/src/dashboard/pages/agent-detail/skills-section.js +9 -1
  80. package/src/dashboard/pages/agent-detail/tool-security.js +35 -8
  81. package/src/dashboard/pages/agent-detail/tools.js +10 -1
  82. package/src/dashboard/pages/agent-detail/whatsapp.js +11 -1
  83. package/src/dashboard/pages/agent-detail/workforce.js +19 -4
  84. package/src/dashboard/pages/agents.js +15 -1
  85. package/src/dashboard/pages/approvals.js +15 -1
  86. package/src/dashboard/pages/audit.js +23 -1
  87. package/src/dashboard/pages/compliance.js +24 -2
  88. package/src/dashboard/pages/dashboard.js +25 -6
  89. package/src/dashboard/pages/dlp.js +23 -2
  90. package/src/dashboard/pages/domain-status.js +51 -7
  91. package/src/dashboard/pages/guardrails.js +29 -3
  92. package/src/dashboard/pages/journal.js +24 -4
  93. package/src/dashboard/pages/knowledge-contributions.js +69 -3
  94. package/src/dashboard/pages/knowledge-import.js +6 -1
  95. package/src/dashboard/pages/knowledge.js +51 -9
  96. package/src/dashboard/pages/messages.js +28 -5
  97. package/src/dashboard/pages/org-chart.js +18 -1
  98. package/src/dashboard/pages/settings.js +30 -6
  99. package/src/dashboard/pages/skill-connections.js +18 -4
  100. package/src/dashboard/pages/skills.js +11 -1
  101. package/src/dashboard/pages/task-pipeline.js +455 -0
  102. package/src/dashboard/pages/users.js +14 -1
  103. package/src/dashboard/pages/vault.js +22 -2
  104. package/src/dashboard/pages/workforce.js +17 -1
  105. package/src/engine/model-fallback.ts +141 -0
  106. package/src/engine/routes.ts +5 -0
  107. package/src/engine/task-queue-after-spawn.ts +66 -0
  108. package/src/engine/task-queue-before-spawn.ts +109 -0
  109. package/src/engine/task-queue-routes.ts +133 -0
  110. package/src/engine/task-queue.ts +369 -0
@@ -0,0 +1,455 @@
1
+ import { h, useState, useEffect, useCallback, useRef, Fragment, useApp, engineCall, getOrgId } from '../components/utils.js';
2
+ import { I } from '../components/icons.js';
3
+ import { HelpButton } from '../components/help-button.js';
4
+
5
+ // ─── Colors ──────────────────────────────────────────────
6
+ const STATUS_COLORS = {
7
+ created: '#6366f1',
8
+ assigned: '#f59e0b',
9
+ in_progress: '#06b6d4',
10
+ completed: '#22c55e',
11
+ failed: '#ef4444',
12
+ cancelled: '#6b7394',
13
+ };
14
+ const PRIORITY_COLORS = { urgent: '#ef4444', high: '#f59e0b', normal: '#6366f1', low: '#6b7394' };
15
+ const CATEGORY_ICONS = { email: '\u2709', research: '\uD83D\uDD0D', meeting: '\uD83D\uDCC5', workflow: '\u2699', writing: '\u270F', deployment: '\uD83D\uDE80', review: '\u2714', monitoring: '\uD83D\uDCE1', custom: '\uD83D\uDCCB' };
16
+ const BG = '#0a0c14';
17
+ const ACCENT = '#6366f1';
18
+
19
+ // ─── Styles ──────────────────────────────────────────────
20
+ const _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
21
+ const _ul = { paddingLeft: 20, margin: '4px 0 8px' };
22
+ const _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
23
+
24
+ // ─── Pipeline Columns (Kanban) ───────────────────────────
25
+ const COLUMNS = [
26
+ { key: 'created', label: 'Queued', color: STATUS_COLORS.created },
27
+ { key: 'assigned', label: 'Assigned', color: STATUS_COLORS.assigned },
28
+ { key: 'in_progress', label: 'In Progress', color: STATUS_COLORS.in_progress },
29
+ { key: 'completed', label: 'Completed', color: STATUS_COLORS.completed },
30
+ { key: 'failed', label: 'Failed', color: STATUS_COLORS.failed },
31
+ ];
32
+
33
+ function formatDuration(ms) {
34
+ if (!ms) return '-';
35
+ var s = Math.floor(ms / 1000);
36
+ if (s < 60) return s + 's';
37
+ var m = Math.floor(s / 60);
38
+ if (m < 60) return m + 'm ' + (s % 60) + 's';
39
+ var hr = Math.floor(m / 60);
40
+ return hr + 'h ' + (m % 60) + 'm';
41
+ }
42
+
43
+ function timeAgo(ts) {
44
+ if (!ts) return '-';
45
+ var diff = Date.now() - new Date(ts).getTime();
46
+ if (diff < 5000) return 'just now';
47
+ if (diff < 60000) return Math.floor(diff / 1000) + 's ago';
48
+ if (diff < 3600000) return Math.floor(diff / 60000) + 'm ago';
49
+ if (diff < 86400000) return Math.floor(diff / 3600000) + 'h ago';
50
+ return Math.floor(diff / 86400000) + 'd ago';
51
+ }
52
+
53
+ // ─── Task Card Component ─────────────────────────────────
54
+ function TaskCard({ task, onSelect }) {
55
+ var priColor = PRIORITY_COLORS[task.priority] || PRIORITY_COLORS.normal;
56
+ var catIcon = CATEGORY_ICONS[task.category] || CATEGORY_ICONS.custom;
57
+
58
+ return h('div', {
59
+ onClick: function() { onSelect(task); },
60
+ style: {
61
+ background: 'var(--bg-secondary, #111827)',
62
+ border: '1px solid var(--border, #1e293b)',
63
+ borderLeft: '3px solid ' + priColor,
64
+ borderRadius: 'var(--radius, 8px)',
65
+ padding: 12,
66
+ marginBottom: 8,
67
+ cursor: 'pointer',
68
+ transition: 'transform 0.1s, box-shadow 0.1s',
69
+ },
70
+ onMouseEnter: function(e) { e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.3)'; },
71
+ onMouseLeave: function(e) { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; },
72
+ },
73
+ // Header: icon + title
74
+ h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 } },
75
+ h('span', { style: { fontSize: 14 } }, catIcon),
76
+ h('span', { style: { fontSize: 13, fontWeight: 600, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, task.title)
77
+ ),
78
+ // Agent + time
79
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: 11, color: 'var(--text-muted)' } },
80
+ h('span', null, task.assignedToName || task.assignedTo || '-'),
81
+ h('span', null, timeAgo(task.createdAt))
82
+ ),
83
+ // Progress bar (if in progress)
84
+ task.status === 'in_progress' && task.progress > 0 && h('div', { style: { marginTop: 6, height: 3, background: 'var(--border)', borderRadius: 2, overflow: 'hidden' } },
85
+ h('div', { style: { height: '100%', width: task.progress + '%', background: STATUS_COLORS.in_progress, borderRadius: 2, transition: 'width 0.3s' } })
86
+ ),
87
+ // Tags
88
+ task.tags && task.tags.length > 0 && h('div', { style: { display: 'flex', gap: 4, marginTop: 6, flexWrap: 'wrap' } },
89
+ task.tags.map(function(tag) {
90
+ return h('span', { key: tag, style: { fontSize: 10, padding: '1px 6px', borderRadius: 10, background: 'var(--accent-soft, rgba(99,102,241,0.15))', color: 'var(--accent, #6366f1)' } }, tag);
91
+ })
92
+ )
93
+ );
94
+ }
95
+
96
+ // ─── Task Detail Modal ───────────────────────────────────
97
+ function TaskDetail({ task, onClose, onCancel }) {
98
+ if (!task) return null;
99
+ var statusColor = STATUS_COLORS[task.status] || '#6b7394';
100
+
101
+ return h('div', { className: 'modal-overlay', onClick: onClose },
102
+ h('div', { className: 'modal', onClick: function(e) { e.stopPropagation(); }, style: { width: 560, maxHeight: '80vh', overflow: 'auto' } },
103
+ h('div', { className: 'modal-header' },
104
+ h('h2', null, task.title),
105
+ h('button', { className: 'btn btn-ghost btn-icon', onClick: onClose }, '\u00D7')
106
+ ),
107
+ h('div', { className: 'modal-body', style: { padding: 20 } },
108
+ // Status badge
109
+ h('div', { style: { display: 'flex', gap: 8, marginBottom: 16, alignItems: 'center' } },
110
+ h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 12, fontWeight: 600, background: statusColor + '22', color: statusColor, border: '1px solid ' + statusColor + '44' } },
111
+ task.status.replace('_', ' ').toUpperCase()
112
+ ),
113
+ h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 12, background: (PRIORITY_COLORS[task.priority] || '#6366f1') + '22', color: PRIORITY_COLORS[task.priority] || '#6366f1' } },
114
+ task.priority.toUpperCase()
115
+ ),
116
+ h('span', { style: { padding: '3px 10px', borderRadius: 12, fontSize: 12, background: 'var(--bg-tertiary)', color: 'var(--text-muted)' } },
117
+ (CATEGORY_ICONS[task.category] || '') + ' ' + task.category
118
+ )
119
+ ),
120
+
121
+ // Description
122
+ task.description && h('div', { style: { marginBottom: 16, fontSize: 13, lineHeight: 1.6, color: 'var(--text-secondary)' } }, task.description),
123
+
124
+ // Progress
125
+ task.status === 'in_progress' && h('div', { style: { marginBottom: 16 } },
126
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 } },
127
+ h('span', null, 'Progress'),
128
+ h('span', null, task.progress + '%')
129
+ ),
130
+ h('div', { style: { height: 6, background: 'var(--border)', borderRadius: 3, overflow: 'hidden' } },
131
+ h('div', { style: { height: '100%', width: task.progress + '%', background: STATUS_COLORS.in_progress, borderRadius: 3 } })
132
+ )
133
+ ),
134
+
135
+ // Metadata grid
136
+ h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px 24px', fontSize: 13, marginBottom: 16 } },
137
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Assigned To'), h('div', null, task.assignedToName || task.assignedTo || '-')),
138
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Created By'), h('div', null, task.createdByName || task.createdBy || '-')),
139
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Created'), h('div', null, task.createdAt ? new Date(task.createdAt).toLocaleString() : '-')),
140
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Started'), h('div', null, task.startedAt ? new Date(task.startedAt).toLocaleString() : '-')),
141
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Completed'), h('div', null, task.completedAt ? new Date(task.completedAt).toLocaleString() : '-')),
142
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Duration'), h('div', null, formatDuration(task.actualDurationMs))),
143
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Model'), h('div', null, task.modelUsed || task.model || '-')),
144
+ h('div', null, h('div', { style: { color: 'var(--text-muted)', fontSize: 11, marginBottom: 2 } }, 'Tokens / Cost'), h('div', null, (task.tokensUsed || 0).toLocaleString() + ' / $' + (task.costUsd || 0).toFixed(4)))
145
+ ),
146
+
147
+ // Error
148
+ task.error && h('div', { style: { padding: 12, background: 'rgba(239,68,68,0.1)', border: '1px solid rgba(239,68,68,0.3)', borderRadius: 'var(--radius)', marginBottom: 16, fontSize: 13, color: '#ef4444' } },
149
+ h('strong', null, 'Error: '), task.error
150
+ ),
151
+
152
+ // Result
153
+ task.result && h('div', { style: { marginBottom: 16 } },
154
+ h('div', { style: { fontSize: 12, color: 'var(--text-muted)', marginBottom: 4 } }, 'Result'),
155
+ h('pre', { style: { fontSize: 12, background: 'var(--bg-tertiary)', padding: 12, borderRadius: 'var(--radius)', overflow: 'auto', maxHeight: 200 } },
156
+ JSON.stringify(task.result, null, 2)
157
+ )
158
+ ),
159
+
160
+ // Actions
161
+ (task.status === 'created' || task.status === 'assigned' || task.status === 'in_progress') && h('div', { style: { display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 16, borderTop: '1px solid var(--border)', paddingTop: 16 } },
162
+ h('button', { className: 'btn btn-danger btn-sm', onClick: function() { onCancel(task.id); } }, 'Cancel Task')
163
+ )
164
+ )
165
+ )
166
+ );
167
+ }
168
+
169
+ // ─── Stats Bar ───────────────────────────────────────────
170
+ function StatsBar({ stats }) {
171
+ var items = [
172
+ { label: 'Queued', value: stats.created, color: STATUS_COLORS.created },
173
+ { label: 'Assigned', value: stats.assigned, color: STATUS_COLORS.assigned },
174
+ { label: 'In Progress', value: stats.inProgress, color: STATUS_COLORS.in_progress },
175
+ { label: 'Completed', value: stats.completed, color: STATUS_COLORS.completed },
176
+ { label: 'Failed', value: stats.failed, color: STATUS_COLORS.failed },
177
+ ];
178
+ return h('div', { style: { display: 'flex', gap: 16, marginBottom: 20, flexWrap: 'wrap' } },
179
+ items.map(function(it) {
180
+ return h('div', { key: it.label, style: { background: 'var(--bg-secondary)', border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '12px 20px', minWidth: 120, textAlign: 'center' } },
181
+ h('div', { style: { fontSize: 28, fontWeight: 700, color: it.color, lineHeight: 1 } }, it.value),
182
+ h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 4 } }, it.label)
183
+ );
184
+ })
185
+ );
186
+ }
187
+
188
+ // ─── Main Page Component ─────────────────────────────────
189
+ export function TaskPipelinePage() {
190
+ var { toast } = useApp();
191
+ var [tasks, setTasks] = useState([]);
192
+ var [stats, setStats] = useState({ created: 0, assigned: 0, inProgress: 0, completed: 0, failed: 0, cancelled: 0, total: 0 });
193
+ var [selectedTask, setSelectedTask] = useState(null);
194
+ var [view, setView] = useState('kanban'); // 'kanban' | 'list' | 'timeline'
195
+ var [filter, setFilter] = useState('all'); // 'all' | 'active' | 'completed' | 'failed'
196
+ var [loading, setLoading] = useState(true);
197
+ var eventSourceRef = useRef(null);
198
+
199
+ // Fetch initial data
200
+ var loadData = useCallback(function() {
201
+ setLoading(true);
202
+ Promise.all([
203
+ engineCall('/task-pipeline?limit=200'),
204
+ engineCall('/task-pipeline/stats'),
205
+ ]).then(function(results) {
206
+ setTasks(results[0]?.tasks || []);
207
+ setStats(results[1] || stats);
208
+ }).catch(function(err) {
209
+ console.error('[TaskPipeline] load error:', err);
210
+ }).finally(function() { setLoading(false); });
211
+ }, []);
212
+
213
+ // SSE for real-time updates
214
+ useEffect(function() {
215
+ loadData();
216
+
217
+ // Connect to SSE stream
218
+ var baseUrl = window.__ENGINE_BASE || '/engine';
219
+ var es = new EventSource(baseUrl + '/task-pipeline/stream');
220
+ eventSourceRef.current = es;
221
+
222
+ es.onmessage = function(e) {
223
+ try {
224
+ var event = JSON.parse(e.data);
225
+ if (event.type === 'init') {
226
+ // Initial state from SSE
227
+ if (event.tasks) setTasks(function(prev) {
228
+ var map = new Map();
229
+ prev.forEach(function(t) { map.set(t.id, t); });
230
+ event.tasks.forEach(function(t) { map.set(t.id, t); });
231
+ return Array.from(map.values()).sort(function(a, b) { return new Date(b.createdAt) - new Date(a.createdAt); });
232
+ });
233
+ if (event.stats) setStats(event.stats);
234
+ } else if (event.task) {
235
+ // Real-time task event
236
+ setTasks(function(prev) {
237
+ var idx = prev.findIndex(function(t) { return t.id === event.task.id; });
238
+ if (idx >= 0) {
239
+ var next = prev.slice();
240
+ next[idx] = event.task;
241
+ return next;
242
+ }
243
+ return [event.task].concat(prev);
244
+ });
245
+ // Update stats locally
246
+ setStats(function(prev) {
247
+ var s = Object.assign({}, prev);
248
+ if (event.type === 'task_created') { s.created++; s.total++; }
249
+ else if (event.type === 'task_completed') { s.completed++; s.inProgress = Math.max(0, s.inProgress - 1); }
250
+ else if (event.type === 'task_failed') { s.failed++; s.inProgress = Math.max(0, s.inProgress - 1); }
251
+ return s;
252
+ });
253
+ // Update selected task if viewing it
254
+ setSelectedTask(function(prev) {
255
+ if (prev && prev.id === event.task.id) return event.task;
256
+ return prev;
257
+ });
258
+ }
259
+ } catch (err) { /* ignore parse errors */ }
260
+ };
261
+
262
+ es.onerror = function() {
263
+ // Reconnect handled by browser
264
+ };
265
+
266
+ return function() {
267
+ if (es) es.close();
268
+ };
269
+ }, []);
270
+
271
+ // Periodic stats refresh
272
+ useEffect(function() {
273
+ var interval = setInterval(function() {
274
+ engineCall('/task-pipeline/stats').then(function(s) { if (s) setStats(s); }).catch(function() {});
275
+ }, 30000);
276
+ return function() { clearInterval(interval); };
277
+ }, []);
278
+
279
+ var cancelTask = useCallback(function(taskId) {
280
+ engineCall('/task-pipeline/' + taskId + '/cancel', { method: 'POST' })
281
+ .then(function(res) {
282
+ toast('Task cancelled', 'success');
283
+ setSelectedTask(null);
284
+ loadData();
285
+ })
286
+ .catch(function(err) { toast(err.message || 'Failed to cancel', 'error'); });
287
+ }, []);
288
+
289
+ // Filter tasks
290
+ var filteredTasks = tasks.filter(function(t) {
291
+ if (filter === 'active') return t.status === 'created' || t.status === 'assigned' || t.status === 'in_progress';
292
+ if (filter === 'completed') return t.status === 'completed';
293
+ if (filter === 'failed') return t.status === 'failed' || t.status === 'cancelled';
294
+ return true;
295
+ });
296
+
297
+ // Group by status for kanban
298
+ var columns = {};
299
+ COLUMNS.forEach(function(col) { columns[col.key] = []; });
300
+ filteredTasks.forEach(function(t) {
301
+ if (columns[t.status]) columns[t.status].push(t);
302
+ else if (t.status === 'cancelled' && columns.failed) columns.failed.push(t);
303
+ });
304
+
305
+ if (loading) {
306
+ return h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } }, 'Loading task pipeline...');
307
+ }
308
+
309
+ return h(Fragment, null,
310
+ // ─── Header ────────────────────────────────────────
311
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
312
+ h('div', { style: { display: 'flex', alignItems: 'center', gap: 12 } },
313
+ h('h1', { style: { fontSize: 22, fontWeight: 700 } }, I.workflow(), ' Task Pipeline'),
314
+ h(HelpButton, { title: 'Task Pipeline' },
315
+ h('p', null, 'The centralized task pipeline shows every task assigned to agents across your organization in real-time.'),
316
+ h('h4', { style: _h4 }, 'How It Works'),
317
+ h('ul', { style: _ul },
318
+ h('li', null, 'Tasks are automatically recorded when agents are spawned for work'),
319
+ h('li', null, 'The pipeline tracks task status from creation through completion'),
320
+ h('li', null, 'Real-time updates via SSE — no need to refresh'),
321
+ h('li', null, 'Smart metadata extraction categorizes tasks automatically')
322
+ ),
323
+ h('h4', { style: _h4 }, 'Task Lifecycle'),
324
+ h('ul', { style: _ul },
325
+ h('li', null, h('strong', null, 'Queued'), ' — Task created, waiting to be assigned'),
326
+ h('li', null, h('strong', null, 'Assigned'), ' — Agent selected, about to start'),
327
+ h('li', null, h('strong', null, 'In Progress'), ' — Agent actively working'),
328
+ h('li', null, h('strong', null, 'Completed'), ' — Task finished successfully'),
329
+ h('li', null, h('strong', null, 'Failed'), ' — Task encountered an error')
330
+ ),
331
+ h('div', { style: _tip }, 'Tip: Click any task card to see full details including model used, tokens consumed, duration, and results.')
332
+ )
333
+ ),
334
+ h('div', { style: { display: 'flex', gap: 8 } },
335
+ // View toggle
336
+ h('div', { style: { display: 'flex', border: '1px solid var(--border)', borderRadius: 'var(--radius)', overflow: 'hidden' } },
337
+ ['kanban', 'list'].map(function(v) {
338
+ return h('button', {
339
+ key: v,
340
+ className: 'btn btn-sm ' + (view === v ? 'btn-primary' : 'btn-ghost'),
341
+ onClick: function() { setView(v); },
342
+ style: { borderRadius: 0, textTransform: 'capitalize', fontSize: 12 }
343
+ }, v);
344
+ })
345
+ ),
346
+ // Filter
347
+ h('select', {
348
+ className: 'form-control',
349
+ value: filter,
350
+ onChange: function(e) { setFilter(e.target.value); },
351
+ style: { fontSize: 12, padding: '4px 8px', width: 'auto' }
352
+ },
353
+ h('option', { value: 'all' }, 'All Tasks'),
354
+ h('option', { value: 'active' }, 'Active Only'),
355
+ h('option', { value: 'completed' }, 'Completed'),
356
+ h('option', { value: 'failed' }, 'Failed / Cancelled')
357
+ ),
358
+ h('button', { className: 'btn btn-secondary btn-sm', onClick: loadData }, I.refresh(), ' Refresh')
359
+ )
360
+ ),
361
+
362
+ // ─── Stats Bar ─────────────────────────────────────
363
+ h(StatsBar, { stats: stats }),
364
+
365
+ // ─── Live indicator ────────────────────────────────
366
+ h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, marginBottom: 16, fontSize: 12, color: 'var(--text-muted)' } },
367
+ h('div', { style: { width: 8, height: 8, borderRadius: '50%', background: '#22c55e', animation: 'pulse 2s infinite' } }),
368
+ 'Live — updates in real-time',
369
+ h('span', { style: { marginLeft: 'auto' } }, filteredTasks.length + ' tasks')
370
+ ),
371
+
372
+ // ─── Kanban View ───────────────────────────────────
373
+ view === 'kanban' && h('div', {
374
+ style: {
375
+ display: 'grid',
376
+ gridTemplateColumns: 'repeat(' + COLUMNS.length + ', 1fr)',
377
+ gap: 12,
378
+ minHeight: 400,
379
+ }
380
+ },
381
+ COLUMNS.map(function(col) {
382
+ var colTasks = columns[col.key] || [];
383
+ return h('div', { key: col.key, style: { background: 'var(--bg-primary)', border: '1px solid var(--border)', borderRadius: 'var(--radius)', overflow: 'hidden' } },
384
+ // Column header
385
+ h('div', { style: { padding: '10px 12px', borderBottom: '2px solid ' + col.color, display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
386
+ h('span', { style: { fontSize: 13, fontWeight: 600 } }, col.label),
387
+ h('span', { style: { fontSize: 11, padding: '2px 8px', borderRadius: 10, background: col.color + '22', color: col.color, fontWeight: 600 } }, colTasks.length)
388
+ ),
389
+ // Cards
390
+ h('div', { style: { padding: 8, maxHeight: 500, overflowY: 'auto' } },
391
+ colTasks.length === 0
392
+ ? h('div', { style: { padding: 20, textAlign: 'center', color: 'var(--text-muted)', fontSize: 12 } }, 'No tasks')
393
+ : colTasks.map(function(t) {
394
+ return h(TaskCard, { key: t.id, task: t, onSelect: setSelectedTask });
395
+ })
396
+ )
397
+ );
398
+ })
399
+ ),
400
+
401
+ // ─── List View ─────────────────────────────────────
402
+ view === 'list' && h('div', { className: 'card' },
403
+ h('div', { style: { overflowX: 'auto' } },
404
+ h('table', { className: 'table' },
405
+ h('thead', null,
406
+ h('tr', null,
407
+ h('th', null, 'Task'),
408
+ h('th', null, 'Agent'),
409
+ h('th', null, 'Status'),
410
+ h('th', null, 'Priority'),
411
+ h('th', null, 'Category'),
412
+ h('th', null, 'Created'),
413
+ h('th', null, 'Duration'),
414
+ h('th', null, 'Model')
415
+ )
416
+ ),
417
+ h('tbody', null,
418
+ filteredTasks.length === 0
419
+ ? h('tr', null, h('td', { colSpan: 8, style: { textAlign: 'center', color: 'var(--text-muted)', padding: 40 } }, 'No tasks found'))
420
+ : filteredTasks.map(function(t) {
421
+ var statusColor = STATUS_COLORS[t.status] || '#6b7394';
422
+ return h('tr', {
423
+ key: t.id,
424
+ onClick: function() { setSelectedTask(t); },
425
+ style: { cursor: 'pointer' }
426
+ },
427
+ h('td', { style: { maxWidth: 250, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontWeight: 500 } }, t.title),
428
+ h('td', { style: { fontSize: 13 } }, t.assignedToName || '-'),
429
+ h('td', null,
430
+ h('span', { style: { padding: '2px 8px', borderRadius: 10, fontSize: 11, fontWeight: 600, background: statusColor + '22', color: statusColor } },
431
+ t.status.replace('_', ' ')
432
+ )
433
+ ),
434
+ h('td', null,
435
+ h('span', { style: { fontSize: 11, color: PRIORITY_COLORS[t.priority] || '#6366f1' } }, t.priority)
436
+ ),
437
+ h('td', { style: { fontSize: 12 } }, (CATEGORY_ICONS[t.category] || '') + ' ' + t.category),
438
+ h('td', { style: { fontSize: 12, color: 'var(--text-muted)' } }, timeAgo(t.createdAt)),
439
+ h('td', { style: { fontSize: 12 } }, formatDuration(t.actualDurationMs)),
440
+ h('td', { style: { fontSize: 12, fontFamily: 'var(--font-mono)' } }, t.modelUsed || t.model || '-')
441
+ );
442
+ })
443
+ )
444
+ )
445
+ )
446
+ ),
447
+
448
+ // ─── Task Detail Modal ─────────────────────────────
449
+ selectedTask && h(TaskDetail, {
450
+ task: selectedTask,
451
+ onClose: function() { setSelectedTask(null); },
452
+ onCancel: cancelTask
453
+ })
454
+ );
455
+ }
@@ -1,6 +1,7 @@
1
1
  import { h, useState, useEffect, Fragment, useApp, apiCall, showConfirm } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { Modal } from '../components/modal.js';
4
+ import { HelpButton } from '../components/help-button.js';
4
5
 
5
6
  export function UsersPage() {
6
7
  var { toast } = useApp();
@@ -58,7 +59,19 @@ export function UsersPage() {
58
59
 
59
60
  return h(Fragment, null,
60
61
  h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
61
- h('div', null, h('h1', { style: { fontSize: 20, fontWeight: 700 } }, 'Users'), h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Manage team members and their access')),
62
+ h('div', null, h('h1', { style: { fontSize: 20, fontWeight: 700, display: 'flex', alignItems: 'center' } }, 'Users', h(HelpButton, { label: 'Users' },
63
+ h('p', null, 'Manage dashboard users who can access and administer the AgenticMail Enterprise console. Each user has a role that controls what they can see and do.'),
64
+ h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, 'Roles'),
65
+ h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
66
+ h('li', null, h('strong', null, 'Owner'), ' — Full access including billing, user management, and destructive actions.'),
67
+ h('li', null, h('strong', null, 'Admin'), ' — Can manage agents, policies, and most settings. Cannot manage billing.'),
68
+ h('li', null, h('strong', null, 'Member'), ' — Can view dashboards and interact with agents. Limited config access.'),
69
+ h('li', null, h('strong', null, 'Viewer'), ' — Read-only access to dashboards and reports.')
70
+ ),
71
+ h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, '2FA (Two-Factor Authentication)'),
72
+ h('p', null, 'Users can enable TOTP-based 2FA for extra security. The 2FA column shows whether it\'s active.'),
73
+ h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Use the lock icon to reset a user\'s password. The "Generate" button creates a secure random password.')
74
+ )), h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Manage team members and their access')),
62
75
  h('button', { className: 'btn btn-primary', onClick: function() { setCreating(true); } }, I.plus(), ' Add User')
63
76
  ),
64
77
 
@@ -1,6 +1,7 @@
1
1
  import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, getOrgId } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { Modal } from '../components/modal.js';
4
+ import { HelpButton } from '../components/help-button.js';
4
5
 
5
6
  var PAGE_SIZE = 25;
6
7
 
@@ -522,7 +523,16 @@ export function VaultPage() {
522
523
 
523
524
  h('div', { className: 'card' },
524
525
  h('div', { className: 'card-header' },
525
- h('h3', { style: { fontSize: 14, fontWeight: 600 } }, 'Secrets by Category')
526
+ h('h3', { style: { fontSize: 14, fontWeight: 600, display: 'flex', alignItems: 'center' } }, 'Secrets by Category', h(HelpButton, { label: 'Secrets by Category' },
527
+ h('p', null, 'Breakdown of stored secrets by their category. Helps you understand what types of credentials are in your vault.'),
528
+ h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
529
+ h('li', null, h('strong', null, 'Deploy Credentials'), ' — Infrastructure and deployment secrets.'),
530
+ h('li', null, h('strong', null, 'Skill Credentials'), ' — API keys for agent tools (OpenAI, Slack, etc).'),
531
+ h('li', null, h('strong', null, 'Cloud Storage'), ' — AWS, GCP, and other cloud provider keys.'),
532
+ h('li', null, h('strong', null, 'API Keys'), ' — General-purpose API keys.'),
533
+ h('li', null, h('strong', null, 'Custom'), ' — User-defined secrets.')
534
+ )
535
+ ))
526
536
  ),
527
537
  h('div', { className: 'card-body' },
528
538
  Object.keys(byCategory).length === 0
@@ -563,7 +573,17 @@ export function VaultPage() {
563
573
  return h(Fragment, null,
564
574
  h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
565
575
  h('div', null,
566
- h('h1', { style: { fontSize: 20, fontWeight: 700 } }, 'Vault'),
576
+ h('h1', { style: { fontSize: 20, fontWeight: 700, display: 'flex', alignItems: 'center' } }, 'Vault', h(HelpButton, { label: 'Vault' },
577
+ h('p', null, 'Securely store and manage API keys, passwords, and credentials used by your agents. All secrets are encrypted at rest with AES-256-GCM.'),
578
+ h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, 'Key features'),
579
+ h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
580
+ h('li', null, h('strong', null, 'Platform presets'), ' — Quick setup for OpenAI, Anthropic, GitHub, Stripe, and more.'),
581
+ h('li', null, h('strong', null, 'Key rotation'), ' — Re-encrypt secrets with fresh keys without changing the value.'),
582
+ h('li', null, h('strong', null, 'Full audit trail'), ' — Every read, create, delete, and rotate is logged.'),
583
+ h('li', null, h('strong', null, 'Auto-detection'), ' — Secrets stored as skill:<platform>:<key> are auto-detected by agent tools.')
584
+ ),
585
+ h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Rotate secrets periodically. Use "Rotate All" for bulk re-encryption after a security incident.')
586
+ )),
567
587
  h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Encrypted secrets management with AES-256-GCM')
568
588
  ),
569
589
  h('button', { className: 'btn btn-secondary', onClick: function() { loadSecrets(); loadStatus(); if (tab === 'audit') loadAudit(); } }, I.refresh(), ' Refresh')
@@ -1,6 +1,7 @@
1
1
  import { h, useState, useEffect, useCallback, Fragment, useApp, engineCall, buildAgentEmailMap, resolveAgentEmail, buildAgentDataMap, renderAgentBadge, getOrgId } from '../components/utils.js';
2
2
  import { I } from '../components/icons.js';
3
3
  import { TimezoneSelect } from '../components/timezones.js';
4
+ import { HelpButton } from '../components/help-button.js';
4
5
 
5
6
  export function WorkforcePage() {
6
7
  const { toast } = useApp();
@@ -245,9 +246,24 @@ export function WorkforcePage() {
245
246
  { key: 'history', label: 'Clock History' },
246
247
  ];
247
248
 
249
+ var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
250
+ var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
251
+ var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
252
+
248
253
  return h('div', { className: 'page-inner' },
249
254
  h('div', { className: 'page-header' },
250
- h('h1', null, 'Workforce Management'),
255
+ h('h1', { style: { display: 'flex', alignItems: 'center' } }, 'Workforce Management', h(HelpButton, { label: 'Workforce Management' },
256
+ h('p', null, 'Manage your agents like employees — set work schedules, assign tasks, track budgets, and monitor clock-in/out history.'),
257
+ h('h4', { style: _h4 }, 'Key sections'),
258
+ h('ul', { style: _ul },
259
+ h('li', null, h('strong', null, 'Overview'), ' — See which agents are clocked in, off duty, or unscheduled.'),
260
+ h('li', null, h('strong', null, 'Schedules'), ' — Define working hours, shifts, and auto-wake rules.'),
261
+ h('li', null, h('strong', null, 'Task Queue'), ' — Assign and track tasks for specific agents.'),
262
+ h('li', null, h('strong', null, 'Budgets'), ' — Set token caps to control agent spending.'),
263
+ h('li', null, h('strong', null, 'Clock History'), ' — Audit trail of all clock-in/out events.')
264
+ ),
265
+ h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Use schedules with auto-wake to have agents automatically start working at their scheduled time each day.')
266
+ )),
251
267
  h('button', { className: 'btn btn-ghost', onClick: loadData }, I.refresh(), ' Refresh')
252
268
  ),
253
269
  // Tab bar
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  provision,
9
9
  runSetupWizard
10
- } from "./chunk-Y4N3XCNP.js";
10
+ } from "./chunk-6OZYUTPL.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-NJHOYEVI.js";
31
+ } from "./chunk-5C3SCMY5.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-ZZXPEZOC.js";
45
+ } from "./chunk-ZR4Z42HT.js";
46
46
  import "./chunk-OF4MUWWS.js";
47
47
  import {
48
48
  PROVIDER_REGISTRY,