@agenticmail/enterprise 0.5.199 → 0.5.200
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/dashboard/pages/activity.js +14 -1
- package/dist/dashboard/pages/agent-detail/activity.js +17 -1
- package/dist/dashboard/pages/agent-detail/autonomy.js +17 -1
- package/dist/dashboard/pages/agent-detail/budget.js +25 -2
- package/dist/dashboard/pages/agent-detail/channels.js +10 -1
- package/dist/dashboard/pages/agent-detail/communication.js +10 -1
- package/dist/dashboard/pages/agent-detail/configuration.js +42 -1
- package/dist/dashboard/pages/agent-detail/deployment.js +147 -16
- package/dist/dashboard/pages/agent-detail/email.js +10 -1
- package/dist/dashboard/pages/agent-detail/guardrails.js +27 -3
- package/dist/dashboard/pages/agent-detail/manager.js +15 -1
- package/dist/dashboard/pages/agent-detail/meeting-browser.js +14 -2
- package/dist/dashboard/pages/agent-detail/memory.js +24 -5
- package/dist/dashboard/pages/agent-detail/overview.js +159 -21
- package/dist/dashboard/pages/agent-detail/permissions.js +28 -7
- package/dist/dashboard/pages/agent-detail/personal-details.js +17 -1
- package/dist/dashboard/pages/agent-detail/security.js +21 -5
- package/dist/dashboard/pages/agent-detail/skills-section.js +9 -1
- package/dist/dashboard/pages/agent-detail/tool-security.js +35 -8
- package/dist/dashboard/pages/agent-detail/tools.js +10 -1
- package/dist/dashboard/pages/agent-detail/whatsapp.js +11 -1
- package/dist/dashboard/pages/agent-detail/workforce.js +19 -4
- package/dist/dashboard/pages/agents.js +15 -1
- package/dist/dashboard/pages/approvals.js +15 -1
- package/dist/dashboard/pages/audit.js +23 -1
- package/dist/dashboard/pages/compliance.js +24 -2
- package/dist/dashboard/pages/dashboard.js +25 -6
- package/dist/dashboard/pages/dlp.js +23 -2
- package/dist/dashboard/pages/domain-status.js +51 -7
- package/dist/dashboard/pages/guardrails.js +29 -3
- package/dist/dashboard/pages/journal.js +24 -4
- package/dist/dashboard/pages/knowledge-contributions.js +69 -3
- package/dist/dashboard/pages/knowledge-import.js +6 -1
- package/dist/dashboard/pages/knowledge.js +51 -9
- package/dist/dashboard/pages/messages.js +28 -5
- package/dist/dashboard/pages/org-chart.js +18 -1
- package/dist/dashboard/pages/settings.js +30 -6
- package/dist/dashboard/pages/skill-connections.js +18 -4
- package/dist/dashboard/pages/skills.js +11 -1
- package/dist/dashboard/pages/users.js +14 -1
- package/dist/dashboard/pages/vault.js +22 -2
- package/dist/dashboard/pages/workforce.js +17 -1
- package/package.json +1 -1
- package/src/dashboard/HELP-TOOLTIPS-GUIDE.md +45 -0
- package/src/dashboard/pages/activity.js +14 -1
- package/src/dashboard/pages/agent-detail/activity.js +17 -1
- package/src/dashboard/pages/agent-detail/autonomy.js +17 -1
- package/src/dashboard/pages/agent-detail/budget.js +25 -2
- package/src/dashboard/pages/agent-detail/channels.js +10 -1
- package/src/dashboard/pages/agent-detail/communication.js +10 -1
- package/src/dashboard/pages/agent-detail/configuration.js +42 -1
- package/src/dashboard/pages/agent-detail/deployment.js +147 -16
- package/src/dashboard/pages/agent-detail/email.js +10 -1
- package/src/dashboard/pages/agent-detail/guardrails.js +27 -3
- package/src/dashboard/pages/agent-detail/manager.js +15 -1
- package/src/dashboard/pages/agent-detail/meeting-browser.js +14 -2
- package/src/dashboard/pages/agent-detail/memory.js +24 -5
- package/src/dashboard/pages/agent-detail/overview.js +159 -21
- package/src/dashboard/pages/agent-detail/permissions.js +28 -7
- package/src/dashboard/pages/agent-detail/personal-details.js +17 -1
- package/src/dashboard/pages/agent-detail/security.js +21 -5
- package/src/dashboard/pages/agent-detail/skills-section.js +9 -1
- package/src/dashboard/pages/agent-detail/tool-security.js +35 -8
- package/src/dashboard/pages/agent-detail/tools.js +10 -1
- package/src/dashboard/pages/agent-detail/whatsapp.js +11 -1
- package/src/dashboard/pages/agent-detail/workforce.js +19 -4
- package/src/dashboard/pages/agents.js +15 -1
- package/src/dashboard/pages/approvals.js +15 -1
- package/src/dashboard/pages/audit.js +23 -1
- package/src/dashboard/pages/compliance.js +24 -2
- package/src/dashboard/pages/dashboard.js +25 -6
- package/src/dashboard/pages/dlp.js +23 -2
- package/src/dashboard/pages/domain-status.js +51 -7
- package/src/dashboard/pages/guardrails.js +29 -3
- package/src/dashboard/pages/journal.js +24 -4
- package/src/dashboard/pages/knowledge-contributions.js +69 -3
- package/src/dashboard/pages/knowledge-import.js +6 -1
- package/src/dashboard/pages/knowledge.js +51 -9
- package/src/dashboard/pages/messages.js +28 -5
- package/src/dashboard/pages/org-chart.js +18 -1
- package/src/dashboard/pages/settings.js +30 -6
- package/src/dashboard/pages/skill-connections.js +18 -4
- package/src/dashboard/pages/skills.js +11 -1
- package/src/dashboard/pages/users.js +14 -1
- package/src/dashboard/pages/vault.js +22 -2
- package/src/dashboard/pages/workforce.js +17 -1
|
@@ -3,6 +3,7 @@ import { I } from '../../components/icons.js';
|
|
|
3
3
|
import { E } from '../../assets/icons/emoji-icons.js';
|
|
4
4
|
import { TagInput } from '../../components/tag-input.js';
|
|
5
5
|
import { Badge, EmptyState } from './shared.js?v=4';
|
|
6
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
6
7
|
|
|
7
8
|
var _tsCardStyle = { border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: 20, marginBottom: 16 };
|
|
8
9
|
var _tsCardTitle = { fontSize: 15, fontWeight: 600, marginBottom: 4, display: 'flex', alignItems: 'center', gap: 8 };
|
|
@@ -232,7 +233,17 @@ export function ToolSecuritySection(props) {
|
|
|
232
233
|
// Header
|
|
233
234
|
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
234
235
|
h('div', null,
|
|
235
|
-
h('h3', { style: { margin: 0, fontSize: 18, fontWeight: 600 } }, 'Tool Security'
|
|
236
|
+
h('h3', { style: { margin: 0, fontSize: 18, fontWeight: 600, display: 'flex', alignItems: 'center' } }, 'Tool Security', h(HelpButton, { label: 'Tool Security' },
|
|
237
|
+
h('p', null, 'Configure security sandboxes and middleware for this agent\'s tool usage. Unmodified settings inherit from organization defaults.'),
|
|
238
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
239
|
+
h('li', null, h('strong', null, 'Path Sandbox'), ' — Restricts which directories the agent can read/write.'),
|
|
240
|
+
h('li', null, h('strong', null, 'SSRF Protection'), ' — Blocks access to internal networks and metadata endpoints.'),
|
|
241
|
+
h('li', null, h('strong', null, 'Command Sanitizer'), ' — Controls which shell commands are allowed.'),
|
|
242
|
+
h('li', null, h('strong', null, 'Rate Limiting'), ' — Per-tool call limits to prevent runaway behavior.'),
|
|
243
|
+
h('li', null, h('strong', null, 'Circuit Breaker'), ' — Auto-stops calling failing tools after repeated errors.')
|
|
244
|
+
),
|
|
245
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Only override settings you need to change. Agent-level overrides take precedence over org defaults. Use "Reset to Org Defaults" to remove all overrides.')
|
|
246
|
+
)),
|
|
236
247
|
h('p', { style: { margin: '4px 0 0', fontSize: 13, color: 'var(--text-muted)' } },
|
|
237
248
|
'Configure tool security overrides for this agent. Unmodified settings inherit from ',
|
|
238
249
|
h('strong', null, 'org defaults'),
|
|
@@ -273,7 +284,10 @@ export function ToolSecuritySection(props) {
|
|
|
273
284
|
|
|
274
285
|
// Path Sandbox
|
|
275
286
|
h('div', { style: _tsCardStyle },
|
|
276
|
-
h('div', { style: _tsCardTitle }, I.folder(), ' Path Sandbox'
|
|
287
|
+
h('div', { style: _tsCardTitle }, I.folder(), ' Path Sandbox', h(HelpButton, { label: 'Path Sandbox' },
|
|
288
|
+
h('p', null, 'Restricts file system access to specific directories. Prevents agents from reading sensitive files like .env, SSH keys, or system configs.'),
|
|
289
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Add your project directory to allowed dirs. Use blocked patterns to exclude sensitive files like .env or credentials.')
|
|
290
|
+
)),
|
|
277
291
|
h('div', { style: _tsCardDesc }, 'Controls which directories this agent can read/write.'),
|
|
278
292
|
h(TSToggle, { label: 'Enable path sandboxing', checked: ps.enabled !== false, inherited: !isOverridden('pathSandbox', 'enabled'), onChange: function(v) { patchSec('pathSandbox', 'enabled', v); } }),
|
|
279
293
|
h(TagInput, { label: 'Allowed Directories', value: ps.allowedDirs || [], onChange: function(v) { patchSec('pathSandbox', 'allowedDirs', v); }, placeholder: '/path/to/allow', mono: true }),
|
|
@@ -282,7 +296,9 @@ export function ToolSecuritySection(props) {
|
|
|
282
296
|
|
|
283
297
|
// SSRF Guard
|
|
284
298
|
h('div', { style: _tsCardStyle },
|
|
285
|
-
h('div', { style: _tsCardTitle }, I.globe(), ' SSRF Protection'
|
|
299
|
+
h('div', { style: _tsCardTitle }, I.globe(), ' SSRF Protection', h(HelpButton, { label: 'SSRF Protection' },
|
|
300
|
+
h('p', null, 'Server-Side Request Forgery protection prevents the agent from accessing internal infrastructure like cloud metadata endpoints (169.254.x.x), private networks (10.x.x.x), or localhost services.')
|
|
301
|
+
)),
|
|
286
302
|
h('div', { style: _tsCardDesc }, 'Blocks this agent from accessing internal networks and metadata endpoints.'),
|
|
287
303
|
h(TSToggle, { label: 'Enable SSRF protection', checked: ssrf.enabled !== false, inherited: !isOverridden('ssrf', 'enabled'), onChange: function(v) { patchSec('ssrf', 'enabled', v); } }),
|
|
288
304
|
h(TagInput, { label: 'Allowed Hosts', value: ssrf.allowedHosts || [], onChange: function(v) { patchSec('ssrf', 'allowedHosts', v); }, placeholder: 'api.example.com', mono: true }),
|
|
@@ -292,7 +308,10 @@ export function ToolSecuritySection(props) {
|
|
|
292
308
|
|
|
293
309
|
// Command Sanitizer (full width)
|
|
294
310
|
h('div', { style: _tsCardStyle },
|
|
295
|
-
h('div', { style: _tsCardTitle }, I.terminal(), ' Command Sanitizer'
|
|
311
|
+
h('div', { style: _tsCardTitle }, I.terminal(), ' Command Sanitizer', h(HelpButton, { label: 'Command Sanitizer' },
|
|
312
|
+
h('p', null, 'Controls shell command execution. Use blocklist mode to deny dangerous commands, or allowlist mode to only permit specific safe commands.'),
|
|
313
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Allowlist mode is more secure but requires listing every allowed command. Blocklist mode is easier — just block dangerous patterns like "rm -rf" or "curl | sh".')
|
|
314
|
+
)),
|
|
296
315
|
h('div', { style: _tsCardDesc }, 'Controls which shell commands this agent can execute.'),
|
|
297
316
|
h(TSToggle, { label: 'Enable command validation', checked: cs.enabled !== false, inherited: !isOverridden('commandSanitizer', 'enabled'), onChange: function(v) { patchSec('commandSanitizer', 'enabled', v); } }),
|
|
298
317
|
h('div', { style: { marginBottom: 12 } },
|
|
@@ -314,7 +333,9 @@ export function ToolSecuritySection(props) {
|
|
|
314
333
|
|
|
315
334
|
// Audit Logging
|
|
316
335
|
h('div', { style: _tsCardStyle },
|
|
317
|
-
h('div', { style: _tsCardTitle }, I.journal(), ' Audit Logging'
|
|
336
|
+
h('div', { style: _tsCardTitle }, I.journal(), ' Audit Logging', h(HelpButton, { label: 'Audit Logging' },
|
|
337
|
+
h('p', null, 'Records every tool call this agent makes. Essential for compliance, debugging, and understanding agent behavior. Sensitive values are automatically redacted.')
|
|
338
|
+
)),
|
|
318
339
|
h('div', { style: _tsCardDesc }, 'Logs every tool invocation for this agent.'),
|
|
319
340
|
h(TSToggle, { label: 'Enable audit logging', checked: audit.enabled !== false, inherited: !isOverridden('audit', 'enabled'), onChange: function(v) { patchMw('audit', 'enabled', v); } }),
|
|
320
341
|
h(TagInput, { label: 'Keys to Redact', value: audit.redactKeys || [], onChange: function(v) { patchMw('audit', 'redactKeys', v); }, placeholder: 'custom_secret', mono: true })
|
|
@@ -322,7 +343,9 @@ export function ToolSecuritySection(props) {
|
|
|
322
343
|
|
|
323
344
|
// Rate Limiting
|
|
324
345
|
h('div', { style: _tsCardStyle },
|
|
325
|
-
h('div', { style: _tsCardTitle }, I.clock(), ' Rate Limiting'
|
|
346
|
+
h('div', { style: _tsCardTitle }, I.clock(), ' Rate Limiting', h(HelpButton, { label: 'Rate Limiting' },
|
|
347
|
+
h('p', null, 'Sets maximum calls per minute for each tool. Prevents runaway loops where the agent calls the same tool hundreds of times. Each tool has a token bucket that refills at the configured rate.')
|
|
348
|
+
)),
|
|
326
349
|
h('div', { style: _tsCardDesc }, 'Per-tool rate limits for this agent.'),
|
|
327
350
|
h(TSToggle, { label: 'Enable rate limiting', checked: rl.enabled !== false, inherited: !isOverridden('rateLimit', 'enabled'), onChange: function(v) { patchMw('rateLimit', 'enabled', v); } }),
|
|
328
351
|
h(TSRateLimitEditor, { overrides: rl.overrides || {}, onChange: function(v) { patchMw('rateLimit', 'overrides', v); } })
|
|
@@ -330,14 +353,18 @@ export function ToolSecuritySection(props) {
|
|
|
330
353
|
|
|
331
354
|
// Circuit Breaker
|
|
332
355
|
h('div', { style: _tsCardStyle },
|
|
333
|
-
h('div', { style: _tsCardTitle }, I.pause(), ' Circuit Breaker'
|
|
356
|
+
h('div', { style: _tsCardTitle }, I.pause(), ' Circuit Breaker', h(HelpButton, { label: 'Circuit Breaker' },
|
|
357
|
+
h('p', null, 'Automatically stops calling a tool after consecutive failures. Prevents wasting tokens and API calls on broken integrations. The circuit "opens" after failures and "closes" after a cooldown period.')
|
|
358
|
+
)),
|
|
334
359
|
h('div', { style: _tsCardDesc }, 'Auto-stops calling failing tools after consecutive failures.'),
|
|
335
360
|
h(TSToggle, { label: 'Enable circuit breaker', checked: cb.enabled !== false, inherited: !isOverridden('circuitBreaker', 'enabled'), onChange: function(v) { patchMw('circuitBreaker', 'enabled', v); } })
|
|
336
361
|
),
|
|
337
362
|
|
|
338
363
|
// Telemetry
|
|
339
364
|
h('div', { style: _tsCardStyle },
|
|
340
|
-
h('div', { style: _tsCardTitle }, I.chart(), ' Telemetry'
|
|
365
|
+
h('div', { style: _tsCardTitle }, I.chart(), ' Telemetry', h(HelpButton, { label: 'Telemetry' },
|
|
366
|
+
h('p', null, 'Collects timing data, success rates, and usage patterns for this agent\'s tools. Useful for identifying slow tools, optimizing workflows, and capacity planning.')
|
|
367
|
+
)),
|
|
341
368
|
h('div', { style: _tsCardDesc }, 'Collects execution timing and metrics for this agent\'s tools.'),
|
|
342
369
|
h(TSToggle, { label: 'Enable telemetry', checked: tel.enabled !== false, inherited: !isOverridden('telemetry', 'enabled'), onChange: function(v) { patchMw('telemetry', 'enabled', v); } })
|
|
343
370
|
)
|
|
@@ -3,6 +3,7 @@ import { I } from '../../components/icons.js';
|
|
|
3
3
|
import { E } from '../../assets/icons/emoji-icons.js';
|
|
4
4
|
import { Badge, EmptyState } from './shared.js?v=4';
|
|
5
5
|
import { BrowserConfigCard, ToolRestrictionsCard } from './meeting-browser.js?v=4';
|
|
6
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
6
7
|
|
|
7
8
|
// ════════════════════════════════════════════════════════════
|
|
8
9
|
// TOOL SECURITY SECTION
|
|
@@ -166,7 +167,15 @@ export function ToolsSection(props) {
|
|
|
166
167
|
// Stats bar
|
|
167
168
|
h('div', { style: { display: 'flex', gap: 16, marginBottom: 16, flexWrap: 'wrap', alignItems: 'center' } },
|
|
168
169
|
h('div', { className: 'card', style: { padding: '12px 16px', flex: '1 1 auto', minWidth: 150 } },
|
|
169
|
-
h('div', { style: { fontSize: 24, fontWeight: 700, color: 'var(--accent)' } }, stats.enabled || 0
|
|
170
|
+
h('div', { style: { fontSize: 24, fontWeight: 700, color: 'var(--accent)', display: 'flex', alignItems: 'center' } }, stats.enabled || 0, h(HelpButton, { label: 'Tools' },
|
|
171
|
+
h('p', null, 'Tools are the individual functions an agent can call — like sending email, reading files, searching the web, or executing commands.'),
|
|
172
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
173
|
+
h('li', null, h('strong', null, 'Always On'), ' — Core tools that cannot be disabled (e.g., memory, basic utilities).'),
|
|
174
|
+
h('li', null, h('strong', null, 'OAuth Required'), ' — Tools that need an OAuth connection (e.g., Google Workspace).'),
|
|
175
|
+
h('li', null, h('strong', null, 'Integration'), ' — Tools requiring external service configuration.')
|
|
176
|
+
),
|
|
177
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Click any tool category to expand and see the individual tools it contains. Use the toggle to enable/disable entire categories at once.')
|
|
178
|
+
)),
|
|
170
179
|
h('div', { style: { fontSize: 12, color: 'var(--text-muted)' } }, 'of ' + (stats.total || 0) + ' tools enabled')
|
|
171
180
|
),
|
|
172
181
|
h('div', { style: { display: 'flex', gap: 8 } },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h, useState, useEffect, Fragment, useApp, engineCall } from '../../components/utils.js';
|
|
2
2
|
import { E } from '../../assets/icons/emoji-icons.js';
|
|
3
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
3
4
|
|
|
4
5
|
// ─── Styles ───
|
|
5
6
|
var card = { background: 'var(--bg-secondary)', borderRadius: '12px', padding: '24px', marginBottom: '16px', border: '1px solid var(--border)' };
|
|
@@ -775,7 +776,16 @@ export function WhatsAppSection(props) {
|
|
|
775
776
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '20px' } },
|
|
776
777
|
E.whatsapp(28),
|
|
777
778
|
h('div', null,
|
|
778
|
-
h('h2', { style: { margin: 0, fontSize: '20px' } }, 'WhatsApp Business'
|
|
779
|
+
h('h2', { style: { margin: 0, fontSize: '20px', display: 'flex', alignItems: 'center' } }, 'WhatsApp Business', h(HelpButton, { label: 'WhatsApp Business' },
|
|
780
|
+
h('p', null, 'Connect a dedicated business phone number for customer support. Customers message this number and your agent handles their queries automatically.'),
|
|
781
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
782
|
+
h('li', null, h('strong', null, 'Same number mode'), ' — Use your personal WhatsApp for both personal and business messages. The agent recognizes your manager number.'),
|
|
783
|
+
h('li', null, h('strong', null, 'Separate number'), ' — Dedicated business number. Personal WhatsApp stays private.'),
|
|
784
|
+
h('li', null, h('strong', null, 'Customer pairing'), ' — New customers get a code and await approval before chatting.'),
|
|
785
|
+
h('li', null, h('strong', null, 'Prompt injection protection'), ' — Customer messages are sandboxed to prevent manipulation.')
|
|
786
|
+
),
|
|
787
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Start with same-number mode for simplicity. Switch to a separate number when you need clear separation between personal and business messages.')
|
|
788
|
+
)),
|
|
779
789
|
h('p', { style: { margin: 0, fontSize: '13px', color: 'var(--text-secondary)' } }, 'Connect a dedicated business number for customer support \u2014 separate from your personal WhatsApp')
|
|
780
790
|
)
|
|
781
791
|
),
|
|
@@ -3,6 +3,7 @@ import { I } from '../../components/icons.js';
|
|
|
3
3
|
import { E } from '../../assets/icons/emoji-icons.js';
|
|
4
4
|
import { TimezoneSelect } from '../../components/timezones.js';
|
|
5
5
|
import { Badge, StatCard, EmptyState, formatTime } from './shared.js?v=4';
|
|
6
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
6
7
|
|
|
7
8
|
// ════════════════════════════════════════════════════════════
|
|
8
9
|
// WORKFORCE SECTION
|
|
@@ -212,7 +213,10 @@ export function WorkforceSection(props) {
|
|
|
212
213
|
// ─── Status Card (Real-Time) ──────────────────────────
|
|
213
214
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
214
215
|
h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
215
|
-
h('span',
|
|
216
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Agent Status', h(HelpButton, { label: 'Agent Status' },
|
|
217
|
+
h('p', null, 'Real-time status of this agent. Shows whether the agent is online, idle, or has errors. Clock in/out controls the agent\'s work schedule.'),
|
|
218
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Clock-in/out can be enforced by the schedule. When clocked out, the agent pauses or queues incoming work depending on off-hours settings.')
|
|
219
|
+
)),
|
|
216
220
|
h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
|
|
217
221
|
rtStatus && h('span', {
|
|
218
222
|
className: 'badge badge-' + (rtStatus.status === 'online' ? 'success' : rtStatus.status === 'idle' ? 'info' : rtStatus.status === 'error' ? 'danger' : 'neutral'),
|
|
@@ -242,7 +246,14 @@ export function WorkforceSection(props) {
|
|
|
242
246
|
// ─── Schedule Card ──────────────────────────────────
|
|
243
247
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
244
248
|
h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
245
|
-
h('span',
|
|
249
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Schedule', h(HelpButton, { label: 'Schedule' },
|
|
250
|
+
h('p', null, 'Define when this agent is active. Supports standard hours (e.g., 9-5 M-F), shift patterns, or custom schedules.'),
|
|
251
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
252
|
+
h('li', null, h('strong', null, 'Enforce Clock-In/Out'), ' — Agent must be clocked in to work.'),
|
|
253
|
+
h('li', null, h('strong', null, 'Auto-Wake'), ' — Automatically start the agent at schedule start.'),
|
|
254
|
+
h('li', null, h('strong', null, 'Off-Hours Action'), ' — Pause, stop, or queue work outside schedule.')
|
|
255
|
+
)
|
|
256
|
+
)),
|
|
246
257
|
!editing && h('button', { className: 'btn btn-ghost btn-sm', onClick: startEdit }, I.edit(), schedule ? ' Edit' : ' Configure')
|
|
247
258
|
),
|
|
248
259
|
h('div', { className: 'card-body' },
|
|
@@ -392,7 +403,9 @@ export function WorkforceSection(props) {
|
|
|
392
403
|
// ─── Task Queue ─────────────────────────────────────
|
|
393
404
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
394
405
|
h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
395
|
-
h('span',
|
|
406
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Task Queue', h(HelpButton, { label: 'Task Queue' },
|
|
407
|
+
h('p', null, 'Manually assign tasks to this agent. Tasks have priority (urgent/high/normal/low) and type (email/research/communication/general). The agent processes tasks based on priority order.')
|
|
408
|
+
)),
|
|
396
409
|
h('button', { className: 'btn btn-primary btn-sm', onClick: function() { setShowAddTask(true); } }, I.plus(), ' Add Task')
|
|
397
410
|
),
|
|
398
411
|
tasks.length > 0
|
|
@@ -457,7 +470,9 @@ export function WorkforceSection(props) {
|
|
|
457
470
|
|
|
458
471
|
return h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
459
472
|
h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
460
|
-
h('span',
|
|
473
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Clock History', h(HelpButton, { label: 'Clock History' },
|
|
474
|
+
h('p', null, 'Complete record of all clock-in and clock-out events for this agent. Useful for tracking work hours, debugging scheduling issues, and generating time reports. Click any record for details.')
|
|
475
|
+
)),
|
|
461
476
|
h('span', { style: { fontSize: 12, color: 'var(--text-muted)' } }, totalFiltered + ' record' + (totalFiltered !== 1 ? 's' : ''))
|
|
462
477
|
),
|
|
463
478
|
// Filters
|
|
@@ -2,6 +2,7 @@ import { h, useState, useEffect, useCallback, Fragment, useApp, apiCall, engineC
|
|
|
2
2
|
import { I } from '../components/icons.js';
|
|
3
3
|
import { E } from '../assets/icons/emoji-icons.js';
|
|
4
4
|
import { CULTURES, LANGUAGES, PersonaForm } from '../components/persona-fields.js';
|
|
5
|
+
import { HelpButton } from '../components/help-button.js';
|
|
5
6
|
|
|
6
7
|
// ════════════════════════════════════════════════════════════
|
|
7
8
|
// DEPLOY MODAL
|
|
@@ -1133,9 +1134,22 @@ export function AgentsPage({ onSelectAgent }) {
|
|
|
1133
1134
|
|
|
1134
1135
|
// Delete moved to agent detail overview tab with triple confirmation
|
|
1135
1136
|
|
|
1137
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
1138
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
1139
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
1140
|
+
|
|
1136
1141
|
return h(Fragment, null,
|
|
1137
1142
|
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
1138
|
-
h('div', null, h('h1', { style: { fontSize: 20, fontWeight: 700
|
|
1143
|
+
h('div', null, h('h1', { style: { fontSize: 20, fontWeight: 700, display: 'flex', alignItems: 'center' } }, 'Agents', h(HelpButton, { label: 'Agents' },
|
|
1144
|
+
h('p', null, 'Your AI workforce. Each agent has its own email identity, personality, skills, permissions, and deployment target.'),
|
|
1145
|
+
h('h4', { style: _h4 }, 'Agent lifecycle'),
|
|
1146
|
+
h('ul', { style: _ul },
|
|
1147
|
+
h('li', null, h('strong', null, 'Create'), ' — Use the wizard to pick a role template, configure skills and permissions.'),
|
|
1148
|
+
h('li', null, h('strong', null, 'Deploy'), ' — Send the agent to Fly.io, Docker, Railway, VPS, or run locally.'),
|
|
1149
|
+
h('li', null, h('strong', null, 'Monitor'), ' — Click any agent to see their activity, emails, sessions, and journal.')
|
|
1150
|
+
),
|
|
1151
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Click an agent\'s name to access their full detail page with logs, email, workforce schedule, and more.')
|
|
1152
|
+
)), h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Manage your AI agents — create, configure, deploy, and monitor')),
|
|
1139
1153
|
h('button', { className: 'btn btn-primary', onClick: () => setCreating(true) }, I.plus(), ' Create Agent')
|
|
1140
1154
|
),
|
|
1141
1155
|
creating && h(CreateAgentWizard, { onClose: () => setCreating(false), onCreated: load, toast }),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h, useState, useEffect, Fragment, useApp, engineCall, showConfirm, buildAgentEmailMap, buildAgentDataMap, resolveAgentEmail, renderAgentBadge, getOrgId } from '../components/utils.js';
|
|
2
2
|
import { I } from '../components/icons.js';
|
|
3
|
+
import { HelpButton } from '../components/help-button.js';
|
|
3
4
|
|
|
4
5
|
export function ApprovalsPage() {
|
|
5
6
|
const { toast } = useApp();
|
|
@@ -27,9 +28,22 @@ export function ApprovalsPage() {
|
|
|
27
28
|
} catch (e) { toast(e.message, 'error'); }
|
|
28
29
|
};
|
|
29
30
|
|
|
31
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
32
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
33
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
34
|
+
|
|
30
35
|
return h(Fragment, null,
|
|
31
36
|
h('div', { style: { marginBottom: 20 } },
|
|
32
|
-
h('h1', { style: { fontSize: 20, fontWeight: 700 } }, 'Approvals'
|
|
37
|
+
h('h1', { style: { fontSize: 20, fontWeight: 700, display: 'flex', alignItems: 'center' } }, 'Approvals', h(HelpButton, { label: 'Approvals' },
|
|
38
|
+
h('p', null, 'The human-in-the-loop checkpoint. When agents attempt sensitive actions (based on your permission settings), they pause and wait for your approval here.'),
|
|
39
|
+
h('h4', { style: _h4 }, 'How it works'),
|
|
40
|
+
h('ul', { style: _ul },
|
|
41
|
+
h('li', null, h('strong', null, 'Agent triggers action'), ' — e.g., sending an email, deleting data, or making a financial call.'),
|
|
42
|
+
h('li', null, h('strong', null, 'Request appears here'), ' — with full context: which agent, what action, risk level.'),
|
|
43
|
+
h('li', null, h('strong', null, 'You decide'), ' — approve or reject. The agent resumes or aborts accordingly.')
|
|
44
|
+
),
|
|
45
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Configure which actions require approval in each agent\'s Permissions settings. Start strict, then loosen as you build trust.')
|
|
46
|
+
)),
|
|
33
47
|
h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Review and approve agent actions that require human oversight')
|
|
34
48
|
),
|
|
35
49
|
h('div', { className: 'tabs' },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
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
|
+
import { HelpButton } from '../components/help-button.js';
|
|
4
5
|
|
|
5
6
|
var PAGE_SIZE = 50;
|
|
6
7
|
|
|
@@ -78,10 +79,31 @@ export function AuditPage() {
|
|
|
78
79
|
|
|
79
80
|
var totalPages = Math.max(1, Math.ceil((total || (hasMore ? (page + 2) * PAGE_SIZE : (page + 1) * PAGE_SIZE)) / PAGE_SIZE));
|
|
80
81
|
|
|
82
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
83
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
84
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
85
|
+
|
|
81
86
|
return h(Fragment, null,
|
|
82
87
|
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
83
88
|
h('div', null,
|
|
84
|
-
h('h1', { style: { fontSize: 20, fontWeight: 700 } }, 'Audit Log'
|
|
89
|
+
h('h1', { style: { fontSize: 20, fontWeight: 700, display: 'flex', alignItems: 'center' } }, 'Audit Log', h(HelpButton, { label: 'Audit Log' },
|
|
90
|
+
h('p', null, 'A tamper-evident record of every administrative action performed in your organization. Essential for security investigations, compliance audits, and change tracking.'),
|
|
91
|
+
h('h4', { style: _h4 }, 'What gets logged'),
|
|
92
|
+
h('ul', { style: _ul },
|
|
93
|
+
h('li', null, h('strong', null, 'User actions'), ' — logins, role changes, user creation/deletion.'),
|
|
94
|
+
h('li', null, h('strong', null, 'Agent changes'), ' — configuration updates, deployments, pauses, kills.'),
|
|
95
|
+
h('li', null, h('strong', null, 'Policy updates'), ' — guardrail rule changes, DLP rule modifications.'),
|
|
96
|
+
h('li', null, h('strong', null, 'System events'), ' — automated interventions, scheduled tasks.')
|
|
97
|
+
),
|
|
98
|
+
h('h4', { style: _h4 }, 'Color coding'),
|
|
99
|
+
h('ul', { style: _ul },
|
|
100
|
+
h('li', null, h('strong', null, 'Green'), ' — Create/add actions.'),
|
|
101
|
+
h('li', null, h('strong', null, 'Red'), ' — Delete/remove/revoke actions.'),
|
|
102
|
+
h('li', null, h('strong', null, 'Yellow'), ' — Update/edit actions.'),
|
|
103
|
+
h('li', null, h('strong', null, 'Blue'), ' — Login/auth actions.')
|
|
104
|
+
),
|
|
105
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Use the filter box to search across actions, users, and targets. Click any row to see full details including IP address and metadata.')
|
|
106
|
+
)),
|
|
85
107
|
h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Complete record of all administrative actions and changes')
|
|
86
108
|
),
|
|
87
109
|
h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h, useState, useEffect, Fragment, useApp, engineCall, buildAgentEmailMap, buildAgentDataMap, resolveAgentEmail, renderAgentBadge, getOrgId } from '../components/utils.js';
|
|
2
2
|
import { I } from '../components/icons.js';
|
|
3
|
+
import { HelpButton } from '../components/help-button.js';
|
|
3
4
|
|
|
4
5
|
export function CompliancePage() {
|
|
5
6
|
const { toast } = useApp();
|
|
@@ -34,14 +35,35 @@ export function CompliancePage() {
|
|
|
34
35
|
window.open('/api/engine/compliance/reports/' + id + '/download?format=' + format, '_blank');
|
|
35
36
|
};
|
|
36
37
|
|
|
38
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
39
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
40
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
41
|
+
|
|
37
42
|
return h('div', { className: 'page-inner' },
|
|
38
|
-
h('div', { className: 'page-header' }, h('h1',
|
|
43
|
+
h('div', { className: 'page-header' }, h('h1', { style: { display: 'flex', alignItems: 'center' } }, 'Compliance Reporting', h(HelpButton, { label: 'Compliance Reporting' },
|
|
44
|
+
h('p', null, 'Generate and manage compliance reports for regulatory frameworks. Supports SOC2 summaries, GDPR data exports, and audit summaries.'),
|
|
45
|
+
h('h4', { style: _h4 }, 'Report types'),
|
|
46
|
+
h('ul', { style: _ul },
|
|
47
|
+
h('li', null, h('strong', null, 'SOC2 Summary'), ' — Documents security controls, access patterns, and policy enforcement for SOC2 auditors.'),
|
|
48
|
+
h('li', null, h('strong', null, 'GDPR Export'), ' — Generates a data subject access report for a specific agent, showing all personal data processed.'),
|
|
49
|
+
h('li', null, h('strong', null, 'Audit Summary'), ' — Aggregated view of all administrative actions over a date range.')
|
|
50
|
+
),
|
|
51
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Generate reports before compliance audits. Download in JSON for programmatic processing or CSV for spreadsheet review.')
|
|
52
|
+
))),
|
|
39
53
|
h('div', { className: 'tabs', style: { marginBottom: 16 } },
|
|
40
54
|
['reports', 'generate'].map(t => h('button', { key: t, className: 'tab' + (tab === t ? ' active' : ''), onClick: () => setTab(t) }, t.charAt(0).toUpperCase() + t.slice(1)))
|
|
41
55
|
),
|
|
42
56
|
tab === 'generate' && h('div', { className: 'card' },
|
|
43
57
|
h('div', { className: 'card-body' },
|
|
44
|
-
h('h3', { style: { marginBottom: 16 } }, 'Generate Report'
|
|
58
|
+
h('h3', { style: { marginBottom: 16, display: 'flex', alignItems: 'center' } }, 'Generate Report', h(HelpButton, { label: 'Generate Report' },
|
|
59
|
+
h('p', null, 'Create a new compliance report. Select the report type, date range, and optionally scope to a specific agent.'),
|
|
60
|
+
h('ul', { style: _ul },
|
|
61
|
+
h('li', null, 'SOC2 and Audit reports use a date range to scope the data.'),
|
|
62
|
+
h('li', null, 'GDPR exports require selecting a specific agent.'),
|
|
63
|
+
h('li', null, 'Reports are generated asynchronously and appear in the Reports tab when complete.')
|
|
64
|
+
),
|
|
65
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'For SOC2 audits, generate monthly reports to maintain a continuous compliance record.')
|
|
66
|
+
)),
|
|
45
67
|
h('label', { className: 'field-label' }, 'Report Type'),
|
|
46
68
|
h('select', { className: 'input', value: form.type, onChange: e => setForm({ ...form, type: e.target.value }) }, h('option', { value: 'soc2' }, 'SOC2 Summary'), h('option', { value: 'gdpr' }, 'GDPR Export'), h('option', { value: 'audit' }, 'Audit Summary')),
|
|
47
69
|
form.type !== 'gdpr' && h('div', { style: { display: 'flex', gap: 12, marginTop: 8 } },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { h, useState, useEffect, Fragment, buildAgentEmailMap, buildAgentDataMap, resolveAgentEmail, renderAgentBadge, getOrgId, useApp, apiCall, engineCall } from '../components/utils.js';
|
|
2
2
|
import { I } from '../components/icons.js';
|
|
3
3
|
import { DetailModal } from '../components/modal.js';
|
|
4
|
+
import { HelpButton } from '../components/help-button.js';
|
|
4
5
|
|
|
5
6
|
export function SetupChecklist({ onNavigate }) {
|
|
6
7
|
const [status, setStatus] = useState(null);
|
|
@@ -67,18 +68,33 @@ export function DashboardPage() {
|
|
|
67
68
|
const agentData = buildAgentDataMap(mergedForMap);
|
|
68
69
|
const { setPage: navTo } = useApp();
|
|
69
70
|
|
|
71
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
72
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
73
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
74
|
+
|
|
70
75
|
return h(Fragment, null,
|
|
71
76
|
h(SetupChecklist, { onNavigate: function(pg) { if (navTo) navTo(pg); } }),
|
|
72
77
|
h('div', { className: 'stat-grid' },
|
|
73
|
-
h('div', { className: 'stat-card' }, h('div', { className: 'stat-label' }, 'Total Agents'
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
h('div', { className: 'stat-card' }, h('div', { className: 'stat-label' }, '
|
|
78
|
+
h('div', { className: 'stat-card' }, h('div', { className: 'stat-label', style: { display: 'flex', alignItems: 'center' } }, 'Total Agents', h(HelpButton, { label: 'Total Agents' },
|
|
79
|
+
h('p', null, 'The total number of agents created in your organization, including active, paused, and archived agents.')
|
|
80
|
+
)), h('div', { className: 'stat-value' }, stats?.totalAgents ?? agents.length ?? '-')),
|
|
81
|
+
h('div', { className: 'stat-card' }, h('div', { className: 'stat-label', style: { display: 'flex', alignItems: 'center' } }, 'Active Agents', h(HelpButton, { label: 'Active Agents' },
|
|
82
|
+
h('p', null, 'Agents currently running and available to process tasks. If this is lower than Total Agents, some agents may be paused or archived.')
|
|
83
|
+
)), h('div', { className: 'stat-value', style: { color: 'var(--success)' } }, (stats?.activeAgents ?? agents.filter(function(a) { return a.status === 'active'; }).length) || '-')),
|
|
84
|
+
h('div', { className: 'stat-card' }, h('div', { className: 'stat-label', style: { display: 'flex', alignItems: 'center' } }, 'Users', h(HelpButton, { label: 'Users' },
|
|
85
|
+
h('p', null, 'Human team members with access to this dashboard. Manage users and invite team members from the Users page.')
|
|
86
|
+
)), h('div', { className: 'stat-value' }, stats?.totalUsers ?? '-')),
|
|
87
|
+
h('div', { className: 'stat-card' }, h('div', { className: 'stat-label', style: { display: 'flex', alignItems: 'center' } }, 'Audit Events', h(HelpButton, { label: 'Audit Events' },
|
|
88
|
+
h('p', null, 'Total logged events across all agents — tool calls, deployments, errors, etc. Visit the Activity page for full details.')
|
|
89
|
+
)), h('div', { className: 'stat-value' }, stats?.totalAuditEvents ?? '-'))
|
|
77
90
|
),
|
|
78
91
|
|
|
79
92
|
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
80
93
|
h('div', { className: 'card' },
|
|
81
|
-
h('div', { className: 'card-header' }, h('h3',
|
|
94
|
+
h('div', { className: 'card-header' }, h('h3', { style: { display: 'flex', alignItems: 'center' } }, 'Agents', h(HelpButton, { label: 'Agents' },
|
|
95
|
+
h('p', null, 'A quick overview of your agents. Click "View all" to manage them — create new agents, configure skills, deploy, and monitor.'),
|
|
96
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Click an agent\'s name to see their full detail page with logs, email, sessions, and more.')
|
|
97
|
+
)), h('button', { className: 'btn btn-sm btn-secondary', onClick: function() { navTo('agents'); } }, 'View all')),
|
|
82
98
|
h('div', { className: 'card-body-flush' },
|
|
83
99
|
agents.length === 0
|
|
84
100
|
? h('div', { className: 'empty-state' }, h('h3', null, 'No agents yet'), h('p', null, 'Create your first agent to get started'))
|
|
@@ -96,7 +112,10 @@ export function DashboardPage() {
|
|
|
96
112
|
),
|
|
97
113
|
|
|
98
114
|
h('div', { className: 'card' },
|
|
99
|
-
h('div', { className: 'card-header' }, h('h3',
|
|
115
|
+
h('div', { className: 'card-header' }, h('h3', { style: { display: 'flex', alignItems: 'center' } }, 'Recent Activity', h(HelpButton, { label: 'Recent Activity' },
|
|
116
|
+
h('p', null, 'The latest events across all agents — deployments, tool calls, errors, and status changes. Shows the 8 most recent events.'),
|
|
117
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Click any event to see its full details. Red badges indicate errors that may need attention.')
|
|
118
|
+
)), h('button', { className: 'btn btn-sm btn-secondary', onClick: function() { navTo('activity'); } }, 'View all')),
|
|
100
119
|
h('div', { className: 'card-body' },
|
|
101
120
|
events.length === 0
|
|
102
121
|
? h('div', { style: { textAlign: 'center', padding: 24, color: 'var(--text-muted)', fontSize: 13 } }, 'No activity yet')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h, useState, useEffect, Fragment, useApp, engineCall, buildAgentEmailMap, buildAgentDataMap, resolveAgentEmail, renderAgentBadge, getOrgId } from '../components/utils.js';
|
|
2
2
|
import { I } from '../components/icons.js';
|
|
3
|
+
import { HelpButton } from '../components/help-button.js';
|
|
3
4
|
|
|
4
5
|
export function DLPPage() {
|
|
5
6
|
const { toast } = useApp();
|
|
@@ -36,8 +37,25 @@ export function DLPPage() {
|
|
|
36
37
|
|
|
37
38
|
const severityColor = (s) => s === 'critical' ? 'var(--danger)' : s === 'high' ? 'var(--warning)' : s === 'medium' ? 'var(--info)' : 'var(--text-muted)';
|
|
38
39
|
|
|
40
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
41
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
42
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
43
|
+
|
|
39
44
|
return h('div', { className: 'page-inner' },
|
|
40
|
-
h('div', { className: 'page-header' }, h('h1',
|
|
45
|
+
h('div', { className: 'page-header' }, h('h1', { style: { display: 'flex', alignItems: 'center' } }, 'Data Loss Prevention', h(HelpButton, { label: 'Data Loss Prevention' },
|
|
46
|
+
h('p', null, 'DLP prevents agents from accidentally leaking sensitive data like API keys, passwords, credit card numbers, or personal information in emails and tool outputs.'),
|
|
47
|
+
h('h4', { style: _h4 }, 'How it works'),
|
|
48
|
+
h('ul', { style: _ul },
|
|
49
|
+
h('li', null, h('strong', null, 'Rules'), ' — Define patterns (regex, keywords, or PII types) to detect sensitive data.'),
|
|
50
|
+
h('li', null, h('strong', null, 'Actions'), ' — Block, redact, warn, or log when a match is found.'),
|
|
51
|
+
h('li', null, h('strong', null, 'Violations'), ' — Every detection is logged for audit and investigation.')
|
|
52
|
+
),
|
|
53
|
+
h('h4', { style: _h4 }, 'Built-in PII types'),
|
|
54
|
+
h('ul', { style: _ul },
|
|
55
|
+
h('li', null, 'email, ssn, credit_card, phone, api_key, aws_key')
|
|
56
|
+
),
|
|
57
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Use the Test tab to validate your rules against sample content before deploying them.')
|
|
58
|
+
)), h('button', { className: 'btn btn-primary', onClick: () => setShowModal(true) }, I.plus(), ' Add Rule')),
|
|
41
59
|
h('div', { className: 'tabs', style: { marginBottom: 16 } },
|
|
42
60
|
['rules', 'violations', 'test'].map(t => h('button', { key: t, className: 'tab' + (tab === t ? ' active' : ''), onClick: () => setTab(t) }, t.charAt(0).toUpperCase() + t.slice(1)))
|
|
43
61
|
),
|
|
@@ -75,7 +93,10 @@ export function DLPPage() {
|
|
|
75
93
|
),
|
|
76
94
|
tab === 'test' && h('div', { className: 'card' },
|
|
77
95
|
h('div', { className: 'card-body' },
|
|
78
|
-
h('h3', { style: { marginBottom: 12 } }, 'Test DLP Scan'
|
|
96
|
+
h('h3', { style: { marginBottom: 12, display: 'flex', alignItems: 'center' } }, 'Test DLP Scan', h(HelpButton, { label: 'Test DLP Scan' },
|
|
97
|
+
h('p', null, 'Paste any content here to test it against all active DLP rules. Shows which rules match and how many times.'),
|
|
98
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Test with realistic data samples before deploying new rules to avoid false positives.')
|
|
99
|
+
)),
|
|
79
100
|
h('textarea', { className: 'input', style: { minHeight: 100, marginBottom: 12 }, placeholder: 'Paste content to test against DLP rules...', value: testContent, onChange: (e) => setTestContent(e.target.value) }),
|
|
80
101
|
h('button', { className: 'btn btn-primary', onClick: testScan }, 'Run Scan'),
|
|
81
102
|
testResults && h('div', { style: { marginTop: 16 } },
|