@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.
- package/dist/agent-heartbeat-EGMBRD3R.js +510 -0
- package/dist/chunk-5C3SCMY5.js +4457 -0
- package/dist/chunk-6OZYUTPL.js +1224 -0
- package/dist/chunk-ZR4Z42HT.js +3679 -0
- package/dist/cli-agent-PLMDHMRR.js +1602 -0
- package/dist/cli-serve-PLBAWN7N.js +114 -0
- package/dist/cli.js +3 -3
- package/dist/dashboard/app.js +3 -0
- package/dist/dashboard/components/icons.js +1 -0
- 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/task-pipeline.js +455 -0
- 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/dist/index.js +3 -3
- package/dist/routes-KHABOHOV.js +13273 -0
- package/dist/runtime-6WFHCG3N.js +45 -0
- package/dist/server-BENJQHTB.js +15 -0
- package/dist/setup-7RQIFV5Y.js +20 -0
- package/package.json +1 -1
- package/src/dashboard/HELP-TOOLTIPS-GUIDE.md +45 -0
- package/src/dashboard/app.js +3 -0
- package/src/dashboard/components/icons.js +1 -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/task-pipeline.js +455 -0
- package/src/dashboard/pages/users.js +14 -1
- package/src/dashboard/pages/vault.js +22 -2
- package/src/dashboard/pages/workforce.js +17 -1
- package/src/engine/model-fallback.ts +141 -0
- package/src/engine/routes.ts +5 -0
- package/src/engine/task-queue-after-spawn.ts +66 -0
- package/src/engine/task-queue-before-spawn.ts +109 -0
- package/src/engine/task-queue-routes.ts +133 -0
- package/src/engine/task-queue.ts +369 -0
|
@@ -3,6 +3,7 @@ import { I } from '../../components/icons.js';
|
|
|
3
3
|
import { E } from '../../assets/icons/emoji-icons.js';
|
|
4
4
|
import { Badge, StatCard, EmptyState, formatNumber, formatCost, formatTime, MEMORY_CATEGORIES, memCatColor, memCatLabel, importanceBadgeColor } from './shared.js?v=4';
|
|
5
5
|
import { resolveManager } from './manager.js?v=4';
|
|
6
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
6
7
|
|
|
7
8
|
var CATEGORY_COLORS = {
|
|
8
9
|
code_of_conduct: '#6366f1', communication: '#0ea5e9', data_handling: '#f59e0b',
|
|
@@ -118,17 +119,17 @@ export function OverviewSection(props) {
|
|
|
118
119
|
.finally(function() { setActing(''); });
|
|
119
120
|
};
|
|
120
121
|
|
|
121
|
-
//
|
|
122
|
-
var [deleteStep, setDeleteStep] = useState(0); // 0=hidden, 1=
|
|
122
|
+
// 5-step confirmation delete flow
|
|
123
|
+
var [deleteStep, setDeleteStep] = useState(0); // 0=hidden, 1-5=steps
|
|
123
124
|
var [deleteTyped, setDeleteTyped] = useState('');
|
|
125
|
+
var [deleteChecked, setDeleteChecked] = useState(false);
|
|
124
126
|
|
|
125
|
-
var startDelete = function() { setDeleteStep(1); setDeleteTyped(''); };
|
|
126
|
-
var cancelDelete = function() { setDeleteStep(0); setDeleteTyped(''); };
|
|
127
|
+
var startDelete = function() { setDeleteStep(1); setDeleteTyped(''); setDeleteChecked(false); };
|
|
128
|
+
var cancelDelete = function() { setDeleteStep(0); setDeleteTyped(''); setDeleteChecked(false); };
|
|
127
129
|
|
|
128
130
|
var advanceDelete = async function() {
|
|
129
|
-
if (deleteStep
|
|
130
|
-
if (deleteStep ===
|
|
131
|
-
if (deleteStep === 3) {
|
|
131
|
+
if (deleteStep < 5) { setDeleteStep(deleteStep + 1); setDeleteChecked(false); return; }
|
|
132
|
+
if (deleteStep === 5) {
|
|
132
133
|
var expectedName = (engineAgent?.name || '').trim().toLowerCase();
|
|
133
134
|
if (deleteTyped.trim().toLowerCase() !== expectedName) {
|
|
134
135
|
toast('Agent name does not match', 'error');
|
|
@@ -185,6 +186,11 @@ export function OverviewSection(props) {
|
|
|
185
186
|
return h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } }, 'Loading overview...');
|
|
186
187
|
}
|
|
187
188
|
|
|
189
|
+
// Help tooltip styles
|
|
190
|
+
var _h4 = { marginTop: 16, marginBottom: 8, fontSize: 14 };
|
|
191
|
+
var _ul = { paddingLeft: 20, margin: '4px 0 8px' };
|
|
192
|
+
var _tip = { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 };
|
|
193
|
+
|
|
188
194
|
return h(Fragment, null,
|
|
189
195
|
|
|
190
196
|
// ─── Agent Summary Card ─────────────────────────────
|
|
@@ -227,6 +233,21 @@ export function OverviewSection(props) {
|
|
|
227
233
|
),
|
|
228
234
|
|
|
229
235
|
// ─── Stats Grid ─────────────────────────────────────
|
|
236
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 4, marginBottom: 8 } },
|
|
237
|
+
h('div', { style: { fontSize: 13, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.05em' } }, 'Today\'s Usage'),
|
|
238
|
+
h(HelpButton, { label: 'Today\'s Usage Stats' },
|
|
239
|
+
h('p', null, 'Real-time performance metrics for this agent over the current day (UTC).'),
|
|
240
|
+
h('h4', { style: _h4 }, 'Metrics Explained'),
|
|
241
|
+
h('ul', { style: _ul },
|
|
242
|
+
h('li', null, h('strong', null, 'Tokens Today'), ' — Total input + output tokens consumed by the LLM. Higher token usage means more complex conversations or longer outputs.'),
|
|
243
|
+
h('li', null, h('strong', null, 'Cost Today'), ' — Estimated API cost based on token usage and the agent\'s configured model pricing.'),
|
|
244
|
+
h('li', null, h('strong', null, 'Uptime'), ' — How long the agent has been running since last restart. Resets when the engine restarts.'),
|
|
245
|
+
h('li', null, h('strong', null, 'Error Rate'), ' — Percentage of requests that resulted in errors (timeouts, API failures, guardrail blocks). Above 5% is flagged in red.'),
|
|
246
|
+
h('li', null, h('strong', null, 'Active Sessions'), ' — Currently open conversation sessions. Each chat, email thread, or task is a separate session.')
|
|
247
|
+
),
|
|
248
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'If cost is climbing faster than expected, check the Budget tab to set daily/monthly spending limits.')
|
|
249
|
+
)
|
|
250
|
+
),
|
|
230
251
|
h('div', { className: 'stat-grid', style: { marginBottom: 20 } },
|
|
231
252
|
h(StatCard, { label: 'Tokens Today', value: formatNumber(tokensToday) }),
|
|
232
253
|
h(StatCard, { label: 'Cost Today', value: formatCost(costToday) }),
|
|
@@ -240,7 +261,18 @@ export function OverviewSection(props) {
|
|
|
240
261
|
|
|
241
262
|
// Onboarding Status
|
|
242
263
|
h('div', { className: 'card' },
|
|
243
|
-
h('div', { className: 'card-header' }, h('span',
|
|
264
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Onboarding',
|
|
265
|
+
h(HelpButton, { label: 'Agent Onboarding' },
|
|
266
|
+
h('p', null, 'Onboarding ensures the agent acknowledges your organization\'s policies, guardrails, and code of conduct before it starts working.'),
|
|
267
|
+
h('h4', { style: _h4 }, 'How It Works'),
|
|
268
|
+
h('ul', { style: _ul },
|
|
269
|
+
h('li', null, 'When initiated, the agent reads and acknowledges each policy you\'ve configured in Guardrails.'),
|
|
270
|
+
h('li', null, 'The agent must complete onboarding before it can process tasks.'),
|
|
271
|
+
h('li', null, '"Force Complete" skips the acknowledgement process — use this for agents that don\'t need formal onboarding.')
|
|
272
|
+
),
|
|
273
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Set up your guardrail policies first (Guardrails tab), then onboard the agent. The agent will reference these policies in every interaction.')
|
|
274
|
+
)
|
|
275
|
+
)),
|
|
244
276
|
h('div', { className: 'card-body' },
|
|
245
277
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 } },
|
|
246
278
|
onboardingStatus?.onboarded
|
|
@@ -280,7 +312,19 @@ export function OverviewSection(props) {
|
|
|
280
312
|
|
|
281
313
|
// Guardrails Status
|
|
282
314
|
h('div', { className: 'card' },
|
|
283
|
-
h('div', { className: 'card-header' }, h('span',
|
|
315
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Guardrails',
|
|
316
|
+
h(HelpButton, { label: 'Guardrails Status' },
|
|
317
|
+
h('p', null, 'Guardrails are safety rules that constrain the agent\'s behavior. When active, the agent is monitored and can be automatically paused if it violates a policy.'),
|
|
318
|
+
h('h4', { style: _h4 }, 'States'),
|
|
319
|
+
h('ul', { style: _ul },
|
|
320
|
+
h('li', null, h('strong', null, 'Active'), ' — The agent is running normally with all guardrails enforced.'),
|
|
321
|
+
h('li', null, h('strong', null, 'Paused'), ' — The agent has been paused (manually or by an automated trigger). It will not process new tasks until resumed.')
|
|
322
|
+
),
|
|
323
|
+
h('h4', { style: _h4 }, 'Interventions'),
|
|
324
|
+
h('p', null, 'The intervention count tracks how many times a guardrail rule has triggered (e.g., blocked a response, flagged content, or paused the agent). High counts may indicate the agent needs reconfiguration.'),
|
|
325
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Configure guardrail policies in the Guardrails tab. Use "pause" triggers for critical rules and "log" triggers for monitoring.')
|
|
326
|
+
)
|
|
327
|
+
)),
|
|
284
328
|
h('div', { className: 'card-body' },
|
|
285
329
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 } },
|
|
286
330
|
guardrailStatus?.paused
|
|
@@ -295,7 +339,17 @@ export function OverviewSection(props) {
|
|
|
295
339
|
|
|
296
340
|
// Workforce Status
|
|
297
341
|
h('div', { className: 'card' },
|
|
298
|
-
h('div', { className: 'card-header' }, h('span',
|
|
342
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Workforce',
|
|
343
|
+
h(HelpButton, { label: 'Workforce Status' },
|
|
344
|
+
h('p', null, 'Workforce management tracks the agent\'s work schedule and availability, similar to an employee clocking in and out.'),
|
|
345
|
+
h('h4', { style: _h4 }, 'Clock In / Clock Out'),
|
|
346
|
+
h('ul', { style: _ul },
|
|
347
|
+
h('li', null, h('strong', null, 'Clocked In'), ' — The agent is on duty and will process incoming tasks, messages, and emails.'),
|
|
348
|
+
h('li', null, h('strong', null, 'Clocked Out'), ' — The agent is off duty. Depending on configuration, tasks may queue until the agent clocks back in.')
|
|
349
|
+
),
|
|
350
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Set up automatic schedules in the Workforce tab so agents clock in/out at specific times (e.g., business hours only).')
|
|
351
|
+
)
|
|
352
|
+
)),
|
|
299
353
|
h('div', { className: 'card-body' },
|
|
300
354
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 } },
|
|
301
355
|
workforceStatus?.clockedIn
|
|
@@ -312,7 +366,20 @@ export function OverviewSection(props) {
|
|
|
312
366
|
// ─── Real-Time Status Card ────────────────────────────
|
|
313
367
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
314
368
|
h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
315
|
-
h('span',
|
|
369
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Live Status',
|
|
370
|
+
h(HelpButton, { label: 'Live Status' },
|
|
371
|
+
h('p', null, 'Real-time status streamed via Server-Sent Events (SSE). Updates automatically without refreshing the page.'),
|
|
372
|
+
h('h4', { style: _h4 }, 'Status Indicators'),
|
|
373
|
+
h('ul', { style: _ul },
|
|
374
|
+
h('li', null, h('strong', null, 'Online'), ' — Agent is running and processing requests normally.'),
|
|
375
|
+
h('li', null, h('strong', null, 'Idle'), ' — Agent is running but not currently processing any task.'),
|
|
376
|
+
h('li', null, h('strong', null, 'Busy'), ' — Agent is actively processing a request or task.'),
|
|
377
|
+
h('li', null, h('strong', null, 'Error'), ' — Agent encountered an issue. Check the Activity tab for details.')
|
|
378
|
+
),
|
|
379
|
+
h('p', null, 'The current task, model, and token count are shown when the agent is actively working.'),
|
|
380
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'If the status shows "offline" but the agent should be running, try restarting from Quick Actions.')
|
|
381
|
+
)
|
|
382
|
+
),
|
|
316
383
|
rtStatus ? h('span', {
|
|
317
384
|
className: 'badge badge-' + (rtStatus.status === 'online' ? 'success' : rtStatus.status === 'idle' ? 'info' : rtStatus.status === 'error' ? 'danger' : 'neutral'),
|
|
318
385
|
style: { textTransform: 'capitalize' }
|
|
@@ -353,7 +420,18 @@ export function OverviewSection(props) {
|
|
|
353
420
|
|
|
354
421
|
// ─── Quick Actions Bar ──────────────────────────────
|
|
355
422
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
356
|
-
h('div', { className: 'card-header' }, h('span',
|
|
423
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Quick Actions',
|
|
424
|
+
h(HelpButton, { label: 'Quick Actions' },
|
|
425
|
+
h('p', null, 'Common agent operations you can perform directly from the overview.'),
|
|
426
|
+
h('ul', { style: _ul },
|
|
427
|
+
h('li', null, h('strong', null, 'Pause / Resume'), ' — Temporarily stop the agent from processing tasks. Existing sessions are preserved.'),
|
|
428
|
+
h('li', null, h('strong', null, 'Clock In / Out'), ' — Toggle the agent\'s workforce availability.'),
|
|
429
|
+
h('li', null, h('strong', null, 'Restart'), ' — Restart the agent\'s engine if it\'s stuck or behaving unexpectedly.'),
|
|
430
|
+
h('li', null, h('strong', null, 'Redeploy'), ' — Re-deploy with the latest configuration changes.')
|
|
431
|
+
),
|
|
432
|
+
h('div', { style: _tip }, h('strong', null, 'Tip: '), 'Pause is instant and safe — it doesn\'t lose any context. Use it when you need to make config changes.')
|
|
433
|
+
)
|
|
434
|
+
)),
|
|
357
435
|
h('div', { className: 'card-body', style: { display: 'flex', flexWrap: 'wrap', gap: 10 } },
|
|
358
436
|
|
|
359
437
|
// Reset state (when in error/degraded)
|
|
@@ -437,35 +515,95 @@ export function OverviewSection(props) {
|
|
|
437
515
|
|
|
438
516
|
// ─── Triple Confirmation Modals ───────────────────────
|
|
439
517
|
deleteStep >= 1 && h('div', { className: 'modal-overlay', onClick: cancelDelete },
|
|
440
|
-
h('div', { className: 'modal', onClick: function(e) { e.stopPropagation(); }, style: { width:
|
|
518
|
+
h('div', { className: 'modal', onClick: function(e) { e.stopPropagation(); }, style: { width: 480 } },
|
|
441
519
|
h('div', { className: 'modal-header' },
|
|
442
520
|
h('h2', { style: { color: 'var(--danger)' } },
|
|
443
|
-
|
|
521
|
+
['', 'Step 1: Are you sure?', 'Step 2: Data Loss Warning', 'Step 3: Memory & Knowledge Loss', 'Step 4: Communication & Integration Impact', 'Step 5: Final Confirmation'][deleteStep]
|
|
444
522
|
),
|
|
445
523
|
h('button', { className: 'btn btn-ghost btn-icon', onClick: cancelDelete }, '\u00D7')
|
|
446
524
|
),
|
|
525
|
+
// Step indicator
|
|
526
|
+
h('div', { style: { display: 'flex', gap: 4, padding: '0 20px', paddingTop: 12 } },
|
|
527
|
+
[1,2,3,4,5].map(function(s) {
|
|
528
|
+
return h('div', { key: s, style: { flex: 1, height: 4, borderRadius: 2, background: s <= deleteStep ? 'var(--danger)' : 'var(--border)' } });
|
|
529
|
+
})
|
|
530
|
+
),
|
|
447
531
|
h('div', { className: 'modal-body', style: { padding: 20 } },
|
|
532
|
+
|
|
533
|
+
// Step 1 — Initial warning
|
|
448
534
|
deleteStep === 1 && h(Fragment, null,
|
|
449
535
|
h('p', { style: { marginBottom: 12 } }, 'You are about to delete agent ', h('strong', null, engineAgent?.name || agentId), '.'),
|
|
450
|
-
h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'This will permanently remove
|
|
536
|
+
h('p', { style: { color: 'var(--text-muted)', fontSize: 13, marginBottom: 12 } }, 'This is a destructive action that will permanently remove this agent and everything associated with it. There is no undo, no recycle bin, and no way to recover.'),
|
|
537
|
+
h('p', { style: { fontSize: 13 } }, 'Please proceed through the next steps to understand exactly what will be lost.'),
|
|
451
538
|
h('div', { style: { display: 'flex', gap: 8, marginTop: 20, justifyContent: 'flex-end' } },
|
|
452
539
|
h('button', { className: 'btn btn-secondary', onClick: cancelDelete }, 'Cancel'),
|
|
453
|
-
h('button', { className: 'btn btn-danger', onClick: advanceDelete }, '
|
|
540
|
+
h('button', { className: 'btn btn-danger', onClick: advanceDelete }, 'I understand, continue')
|
|
454
541
|
)
|
|
455
542
|
),
|
|
543
|
+
|
|
544
|
+
// Step 2 — Data loss
|
|
456
545
|
deleteStep === 2 && h(Fragment, null,
|
|
457
546
|
h('div', { style: { background: 'var(--danger-soft)', border: '1px solid var(--danger)', borderRadius: 'var(--radius)', padding: 12, marginBottom: 16 } },
|
|
458
|
-
h('strong', { style: { color: 'var(--danger)' } }, '
|
|
459
|
-
h('
|
|
547
|
+
h('strong', { style: { color: 'var(--danger)', display: 'block', marginBottom: 6 } }, 'ALL AGENT DATA WILL BE DESTROYED'),
|
|
548
|
+
h('ul', { style: { margin: '4px 0 0', paddingLeft: 18, fontSize: 13 } },
|
|
549
|
+
h('li', null, 'All email messages (inbox, sent, drafts, folders)'),
|
|
550
|
+
h('li', null, 'All conversation sessions and chat history'),
|
|
551
|
+
h('li', null, 'All tool execution logs and audit trails'),
|
|
552
|
+
h('li', null, 'All configuration, settings, and deployment config'),
|
|
553
|
+
h('li', null, 'All scheduled jobs, cron tasks, and automations')
|
|
554
|
+
)
|
|
460
555
|
),
|
|
461
|
-
h('p', { style: {
|
|
556
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)' } }, 'If you need any of this data, export it BEFORE proceeding.'),
|
|
462
557
|
h('div', { style: { display: 'flex', gap: 8, marginTop: 20, justifyContent: 'flex-end' } },
|
|
463
558
|
h('button', { className: 'btn btn-secondary', onClick: cancelDelete }, 'Cancel'),
|
|
464
|
-
h('button', { className: 'btn btn-danger', onClick: advanceDelete }, '
|
|
559
|
+
h('button', { className: 'btn btn-danger', onClick: advanceDelete }, 'Continue anyway')
|
|
465
560
|
)
|
|
466
561
|
),
|
|
562
|
+
|
|
563
|
+
// Step 3 — Memory & knowledge loss
|
|
467
564
|
deleteStep === 3 && h(Fragment, null,
|
|
468
|
-
h('
|
|
565
|
+
h('div', { style: { background: 'var(--danger-soft)', border: '1px solid var(--danger)', borderRadius: 'var(--radius)', padding: 12, marginBottom: 16 } },
|
|
566
|
+
h('strong', { style: { color: 'var(--danger)', display: 'block', marginBottom: 6 } }, 'MEMORY & KNOWLEDGE PERMANENTLY LOST'),
|
|
567
|
+
h('ul', { style: { margin: '4px 0 0', paddingLeft: 18, fontSize: 13 } },
|
|
568
|
+
h('li', null, 'All long-term memory entries the agent has built over time'),
|
|
569
|
+
h('li', null, 'All learned preferences, patterns, and behavioral adaptations'),
|
|
570
|
+
h('li', null, 'All knowledge base contributions and embeddings'),
|
|
571
|
+
h('li', null, 'All training data, fine-tuning, and custom instructions'),
|
|
572
|
+
h('li', null, 'The agent\'s entire personality and relationship context')
|
|
573
|
+
)
|
|
574
|
+
),
|
|
575
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)' } }, 'This agent has been learning and building context. Once deleted, this knowledge cannot be reconstructed even if you create a new agent with the same name.'),
|
|
576
|
+
h('div', { style: { display: 'flex', gap: 8, marginTop: 20, justifyContent: 'flex-end' } },
|
|
577
|
+
h('button', { className: 'btn btn-secondary', onClick: cancelDelete }, 'Cancel'),
|
|
578
|
+
h('button', { className: 'btn btn-danger', onClick: advanceDelete }, 'Continue anyway')
|
|
579
|
+
)
|
|
580
|
+
),
|
|
581
|
+
|
|
582
|
+
// Step 4 — Communication & integration impact
|
|
583
|
+
deleteStep === 4 && h(Fragment, null,
|
|
584
|
+
h('div', { style: { background: 'var(--danger-soft)', border: '1px solid var(--danger)', borderRadius: 'var(--radius)', padding: 12, marginBottom: 16 } },
|
|
585
|
+
h('strong', { style: { color: 'var(--danger)', display: 'block', marginBottom: 6 } }, 'COMMUNICATION & INTEGRATION IMPACT'),
|
|
586
|
+
h('ul', { style: { margin: '4px 0 0', paddingLeft: 18, fontSize: 13 } },
|
|
587
|
+
h('li', null, 'The agent\'s email address will stop working immediately'),
|
|
588
|
+
h('li', null, 'Any external services or APIs relying on this agent will break'),
|
|
589
|
+
h('li', null, 'Other agents that communicate with this agent will lose their connection'),
|
|
590
|
+
h('li', null, 'Active workflows, approval chains, and escalation paths will be disrupted'),
|
|
591
|
+
h('li', null, 'Contacts and external parties will receive bounced emails')
|
|
592
|
+
)
|
|
593
|
+
),
|
|
594
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)' } }, 'If this agent is part of a team or workflow, consider reassigning its responsibilities first.'),
|
|
595
|
+
h('div', { style: { display: 'flex', gap: 8, marginTop: 20, justifyContent: 'flex-end' } },
|
|
596
|
+
h('button', { className: 'btn btn-secondary', onClick: cancelDelete }, 'Cancel'),
|
|
597
|
+
h('button', { className: 'btn btn-danger', onClick: advanceDelete }, 'I accept the consequences')
|
|
598
|
+
)
|
|
599
|
+
),
|
|
600
|
+
|
|
601
|
+
// Step 5 — Type name to confirm
|
|
602
|
+
deleteStep === 5 && h(Fragment, null,
|
|
603
|
+
h('div', { style: { background: 'var(--danger-soft)', border: '1px solid var(--danger)', borderRadius: 'var(--radius)', padding: 12, marginBottom: 16, textAlign: 'center' } },
|
|
604
|
+
h('strong', { style: { color: 'var(--danger)', fontSize: 15 } }, 'THIS ACTION IS PERMANENT AND IRREVERSIBLE')
|
|
605
|
+
),
|
|
606
|
+
h('p', { style: { marginBottom: 12 } }, 'To confirm deletion, type the agent name ', h('strong', { style: { fontFamily: 'var(--font-mono)', background: 'var(--bg-tertiary)', padding: '2px 6px', borderRadius: 4 } }, engineAgent?.name || agentId), ' below:'),
|
|
469
607
|
h('input', {
|
|
470
608
|
type: 'text',
|
|
471
609
|
className: 'form-control',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { h, useState, useEffect, useCallback, Fragment, useApp, apiCall, engineCall, formatUptime, buildAgentDataMap, renderAgentBadge, showConfirm, getOrgId } from '../../components/utils.js';
|
|
2
2
|
import { I } from '../../components/icons.js';
|
|
3
3
|
import { Badge, EmptyState, riskBadgeClass } from './shared.js?v=4';
|
|
4
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
4
5
|
|
|
5
6
|
// ════════════════════════════════════════════════════════════
|
|
6
7
|
// PERMISSIONS SECTION
|
|
@@ -350,7 +351,10 @@ export function PermissionsSection(props) {
|
|
|
350
351
|
|
|
351
352
|
var soulCard = h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
352
353
|
h('div', { className: 'card-header', style: { cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center', userSelect: 'none' }, onClick: function() { setSoulOpen(!soulOpen); } },
|
|
353
|
-
h('span',
|
|
354
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Role Templates', h(HelpButton, { label: 'Role Templates' },
|
|
355
|
+
h('p', null, 'Pre-configured agent personas with identity, personality, skills, and permissions bundled together. Applying a template sets up the agent for a specific role in one click.'),
|
|
356
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Role templates are a great starting point. You can always customize individual settings after applying one.')
|
|
357
|
+
)),
|
|
354
358
|
h('span', { style: { fontSize: 11, color: 'var(--text-muted)', display: 'flex', alignItems: 'center', gap: 6 } },
|
|
355
359
|
h('span', null, Object.values(soulCategories).reduce(function(sum, arr) { return sum + arr.length; }, 0) + ' templates'),
|
|
356
360
|
h('span', { style: { transition: 'transform 0.2s', transform: soulOpen ? 'rotate(180deg)' : 'rotate(0deg)', display: 'inline-block', lineHeight: 1 } },
|
|
@@ -393,7 +397,14 @@ export function PermissionsSection(props) {
|
|
|
393
397
|
|
|
394
398
|
// Preset selector card (always visible)
|
|
395
399
|
var presetCard = h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
396
|
-
h('div', { className: 'card-header' }, h('span',
|
|
400
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Apply a Permission Preset', h(HelpButton, { label: 'Permission Presets' },
|
|
401
|
+
h('p', null, 'Quick permission profiles that configure risk levels, blocked actions, rate limits, and approval requirements. Presets replace the current permission profile entirely.'),
|
|
402
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
403
|
+
h('li', null, h('strong', null, 'Restrictive'), ' — Low risk, many blocked actions, approval required.'),
|
|
404
|
+
h('li', null, h('strong', null, 'Standard'), ' — Balanced defaults for most agents.'),
|
|
405
|
+
h('li', null, h('strong', null, 'Permissive'), ' — High autonomy, fewer restrictions.')
|
|
406
|
+
)
|
|
407
|
+
))),
|
|
397
408
|
h('div', { className: 'card-body' },
|
|
398
409
|
h('p', { style: { fontSize: 12, color: 'var(--text-muted)', marginBottom: 12 } }, 'Select a preset to quickly configure this agent\'s permissions. This will replace the current profile.'),
|
|
399
410
|
presets.length > 0
|
|
@@ -459,7 +470,9 @@ export function PermissionsSection(props) {
|
|
|
459
470
|
// ─── Current Profile + Edit Button ──────────────────
|
|
460
471
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
461
472
|
h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
462
|
-
h('span',
|
|
473
|
+
h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Current Permission Profile', h(HelpButton, { label: 'Permission Profile' },
|
|
474
|
+
h('p', null, 'The active permission profile controls what this agent can do. It defines the maximum risk level, blocked side effects, sandbox mode, and approval requirements.')
|
|
475
|
+
)),
|
|
463
476
|
h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit')
|
|
464
477
|
),
|
|
465
478
|
h('div', { className: 'card-body' },
|
|
@@ -484,7 +497,9 @@ export function PermissionsSection(props) {
|
|
|
484
497
|
|
|
485
498
|
// ─── Approval Settings Card ─────────────────────────
|
|
486
499
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
487
|
-
h('div', { className: 'card-header' }, h('span',
|
|
500
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Approval Settings', h(HelpButton, { label: 'Approval Settings' },
|
|
501
|
+
h('p', null, 'When enabled, the agent must get human approval before performing risky actions. You can configure which risk levels and side effects trigger approval, and how long to wait before timing out.')
|
|
502
|
+
))),
|
|
488
503
|
h('div', { className: 'card-body' },
|
|
489
504
|
h('div', { style: { display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 } },
|
|
490
505
|
h('span', { style: { fontSize: 13, color: 'var(--text-secondary)' } }, 'Approval Required:'),
|
|
@@ -514,7 +529,9 @@ export function PermissionsSection(props) {
|
|
|
514
529
|
|
|
515
530
|
// ─── Rate Limits Card ───────────────────────────────
|
|
516
531
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
517
|
-
h('div', { className: 'card-header' }, h('span',
|
|
532
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Rate Limits', h(HelpButton, { label: 'Rate Limits' },
|
|
533
|
+
h('p', null, 'Controls how many tool calls the agent can make per time period. Prevents runaway behavior and controls costs. External actions (email, messaging) have a separate limit.')
|
|
534
|
+
))),
|
|
518
535
|
h('div', { className: 'card-body' },
|
|
519
536
|
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
520
537
|
h('div', { style: { padding: 12, background: 'var(--bg-tertiary)', borderRadius: 8 } }, h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4 } }, 'Calls / Minute'), h('div', { style: { fontSize: 20, fontWeight: 700 } }, String(callsPerMin || 'Unlimited'))),
|
|
@@ -527,7 +544,9 @@ export function PermissionsSection(props) {
|
|
|
527
544
|
|
|
528
545
|
// ─── Constraints Card ───────────────────────────────
|
|
529
546
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
530
|
-
h('div', { className: 'card-header' }, h('span',
|
|
547
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Constraints', h(HelpButton, { label: 'Constraints' },
|
|
548
|
+
h('p', null, 'Operational limits for concurrent tasks, session duration, sandbox mode, and IP allowlisting. These prevent the agent from consuming excessive resources.')
|
|
549
|
+
))),
|
|
531
550
|
h('div', { className: 'card-body' },
|
|
532
551
|
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
533
552
|
h('div', null, h('div', { style: { fontSize: 12, color: 'var(--text-muted)', marginBottom: 4 } }, 'Max Concurrent Tasks'), h('div', { style: { fontSize: 14, fontWeight: 600 } }, String(maxConcurrent))),
|
|
@@ -555,7 +574,9 @@ export function PermissionsSection(props) {
|
|
|
555
574
|
|
|
556
575
|
// ─── Applicable Policies Table ──────────────────────
|
|
557
576
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
558
|
-
h('div', { className: 'card-header' }, h('span',
|
|
577
|
+
h('div', { className: 'card-header' }, h('span', { style: { display: 'flex', alignItems: 'center' } }, 'Applicable Policies', h(HelpButton, { label: 'Applicable Policies' },
|
|
578
|
+
h('p', null, 'Organization-level policies that apply to this agent. Policies define rules of conduct, data handling requirements, brand voice guidelines, and escalation procedures. Mandatory policies are enforced; recommended and informational policies are advisory.')
|
|
579
|
+
))),
|
|
559
580
|
policies.length > 0
|
|
560
581
|
? h('div', { className: 'card-body-flush' },
|
|
561
582
|
h('table', { className: 'data-table' },
|
|
@@ -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 { TimezoneSelect } from '../../components/timezones.js';
|
|
5
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
5
6
|
import { CULTURES, LANGUAGES, DEFAULT_TRAITS, computeAge, PersonaForm } from '../../components/persona-fields.js';
|
|
6
7
|
import { TagInput } from '../../components/tag-input.js';
|
|
7
8
|
import { Badge, StatCard, formatTime } from './shared.js?v=4';
|
|
@@ -143,7 +144,22 @@ export function PersonalDetailsSection(props) {
|
|
|
143
144
|
return h(Fragment, null,
|
|
144
145
|
// Header with Edit button
|
|
145
146
|
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
146
|
-
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Personal Details'
|
|
147
|
+
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600, display: 'flex', alignItems: 'center' } }, 'Personal Details',
|
|
148
|
+
h(HelpButton, { label: 'Personal Details' },
|
|
149
|
+
h('p', null, 'Define who this agent is — its name, role, personality, and how it presents itself to the world.'),
|
|
150
|
+
h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, 'Fields'),
|
|
151
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
152
|
+
h('li', null, h('strong', null, 'Name'), ' — The agent\'s display name. Used in emails, chat messages, and team interactions.'),
|
|
153
|
+
h('li', null, h('strong', null, 'Role'), ' — Job title or function (e.g., "Sales Rep", "Support Agent"). Helps the agent understand its responsibilities.'),
|
|
154
|
+
h('li', null, h('strong', null, 'Timezone'), ' — Used for scheduling, work hours, and time-aware responses.'),
|
|
155
|
+
h('li', null, h('strong', null, 'Avatar'), ' — Profile image shown in chat, emails, and the dashboard.'),
|
|
156
|
+
h('li', null, h('strong', null, 'Personality Traits'), ' — Adjectives that shape the agent\'s tone and style (e.g., "professional", "friendly", "concise").'),
|
|
157
|
+
h('li', null, h('strong', null, 'Communication Style'), ' — How the agent writes: formal, casual, technical, etc.'),
|
|
158
|
+
h('li', null, h('strong', null, 'Backstory'), ' — Optional narrative context that enriches the agent\'s persona.')
|
|
159
|
+
),
|
|
160
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Personality traits have a real impact on output quality. Agents with clear traits produce more consistent, on-brand communications.')
|
|
161
|
+
)
|
|
162
|
+
),
|
|
147
163
|
h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit Details')
|
|
148
164
|
),
|
|
149
165
|
|
|
@@ -2,6 +2,7 @@ import { h, useState, useEffect, Fragment, useApp, apiCall } from '../../compone
|
|
|
2
2
|
import { I } from '../../components/icons.js';
|
|
3
3
|
import { E } from '../../assets/icons/emoji-icons.js';
|
|
4
4
|
import { Badge, StatCard, EmptyState } from './shared.js?v=5';
|
|
5
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
5
6
|
|
|
6
7
|
export function AgentSecurityTab(props) {
|
|
7
8
|
var agentId = props.agentId;
|
|
@@ -178,7 +179,14 @@ export function AgentSecurityTab(props) {
|
|
|
178
179
|
return h('div', null,
|
|
179
180
|
h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 24 } },
|
|
180
181
|
h('div', null,
|
|
181
|
-
h('h2', { style: { fontSize: 18, fontWeight: 700, margin: 0 } }, 'Agent Security Settings'
|
|
182
|
+
h('h2', { style: { fontSize: 18, fontWeight: 700, margin: 0, display: 'flex', alignItems: 'center' } }, 'Agent Security Settings', h(HelpButton, { label: 'Agent Security' },
|
|
183
|
+
h('p', null, 'Configure security defenses specific to this agent. Each section can use the global (organization-wide) settings or be customized with agent-specific overrides.'),
|
|
184
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
185
|
+
h('li', null, h('strong', null, 'GLOBAL badge'), ' — Using organization defaults. Toggle the switch to customize.'),
|
|
186
|
+
h('li', null, h('strong', null, 'Custom'), ' — Agent-specific override is active.')
|
|
187
|
+
),
|
|
188
|
+
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 for agents that need different security levels. For most agents, the global defaults are sufficient.')
|
|
189
|
+
)),
|
|
182
190
|
h('p', { style: { fontSize: 14, color: 'var(--text-muted)', margin: '4px 0 0' } }, 'Configure security overrides specific to this agent')
|
|
183
191
|
),
|
|
184
192
|
h('button', {
|
|
@@ -191,7 +199,9 @@ export function AgentSecurityTab(props) {
|
|
|
191
199
|
|
|
192
200
|
// Prompt Injection Defense
|
|
193
201
|
h('div', { style: _cardStyle },
|
|
194
|
-
h('div', { style: _cardTitleStyle }, I.shield(), 'Prompt Injection Defense'
|
|
202
|
+
h('div', { style: _cardTitleStyle }, I.shield(), 'Prompt Injection Defense', h(HelpButton, { label: 'Prompt Injection Defense' },
|
|
203
|
+
h('p', null, 'Detects and prevents prompt injection attacks — where malicious input tries to override the agent\'s instructions. Choose between monitoring (log only), sanitizing (strip dangerous content), or blocking (reject entirely).')
|
|
204
|
+
)),
|
|
195
205
|
h('p', { style: _cardDescStyle }, 'Multi-layer detection and prevention of prompt injection attacks'),
|
|
196
206
|
h(GlobalToggle, { section: 'promptInjection', label: 'Prompt Injection Defense' }),
|
|
197
207
|
!useGlobal.promptInjection && (function() {
|
|
@@ -236,7 +246,9 @@ export function AgentSecurityTab(props) {
|
|
|
236
246
|
|
|
237
247
|
// SQL Injection Prevention
|
|
238
248
|
h('div', { style: _cardStyle },
|
|
239
|
-
h('div', { style: _cardTitleStyle }, I.shield(), 'SQL Injection Prevention'
|
|
249
|
+
h('div', { style: _cardTitleStyle }, I.shield(), 'SQL Injection Prevention', h(HelpButton, { label: 'SQL Injection Prevention' },
|
|
250
|
+
h('p', null, 'Scans tool arguments and API requests for SQL injection patterns. Prevents agents from being tricked into executing malicious database queries.')
|
|
251
|
+
)),
|
|
240
252
|
h('p', { style: _cardDescStyle }, 'Detect and block SQL injection attempts'),
|
|
241
253
|
h(GlobalToggle, { section: 'sqlInjection', label: 'SQL Injection Prevention' }),
|
|
242
254
|
!useGlobal.sqlInjection && (function() {
|
|
@@ -287,7 +299,9 @@ export function AgentSecurityTab(props) {
|
|
|
287
299
|
|
|
288
300
|
// Output Filtering
|
|
289
301
|
h('div', { style: _cardStyle },
|
|
290
|
-
h('div', { style: _cardTitleStyle }, I.shield(), 'Output Filtering'
|
|
302
|
+
h('div', { style: _cardTitleStyle }, I.shield(), 'Output Filtering', h(HelpButton, { label: 'Output Filtering' },
|
|
303
|
+
h('p', null, 'Scans agent responses for leaked secrets (API keys, passwords) and personally identifiable information (PII). Can monitor, redact, or block outputs containing sensitive data.')
|
|
304
|
+
)),
|
|
291
305
|
h('p', { style: _cardDescStyle }, 'Scan agent outputs for secrets and personal information'),
|
|
292
306
|
h(GlobalToggle, { section: 'outputFiltering', label: 'Output Filtering' }),
|
|
293
307
|
!useGlobal.outputFiltering && (function() {
|
|
@@ -339,7 +353,9 @@ export function AgentSecurityTab(props) {
|
|
|
339
353
|
|
|
340
354
|
// Security Audit Log
|
|
341
355
|
h('div', { style: _cardStyle },
|
|
342
|
-
h('div', { style: _cardTitleStyle }, I.journal(), 'Security Audit Log'
|
|
356
|
+
h('div', { style: _cardTitleStyle }, I.journal(), 'Security Audit Log', h(HelpButton, { label: 'Security Audit Log' },
|
|
357
|
+
h('p', null, 'Controls what security events are logged for this agent. Enable comprehensive logging for high-risk agents, or keep minimal logging for routine agents to reduce storage.')
|
|
358
|
+
)),
|
|
343
359
|
h('p', { style: _cardDescStyle }, 'Agent-specific security logging settings'),
|
|
344
360
|
h(GlobalToggle, { section: 'auditSecurity', label: 'Security Audit Log' }),
|
|
345
361
|
!useGlobal.auditSecurity && (function() {
|
|
@@ -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 { Badge, EmptyState } from './shared.js?v=4';
|
|
5
|
+
import { HelpButton } from '../../components/help-button.js';
|
|
5
6
|
|
|
6
7
|
// ════════════════════════════════════════════════════════════
|
|
7
8
|
// SKILLS SECTION — View and manage agent skills
|
|
@@ -127,7 +128,14 @@ export function SkillsSection(props) {
|
|
|
127
128
|
// View mode
|
|
128
129
|
return h(Fragment, null,
|
|
129
130
|
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
130
|
-
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Skills & Capabilities'
|
|
131
|
+
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600, display: 'flex', alignItems: 'center' } }, 'Skills & Capabilities', h(HelpButton, { label: 'Skills & Capabilities' },
|
|
132
|
+
h('p', null, 'Skills are packages of tools and capabilities that an agent can use. Each skill unlocks specific functionality like email management, web browsing, or calendar access.'),
|
|
133
|
+
h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
|
|
134
|
+
h('li', null, h('strong', null, 'Suites'), ' — Pre-built bundles of related skills (e.g., Google Workspace suite includes Gmail, Calendar, Drive).'),
|
|
135
|
+
h('li', null, h('strong', null, 'Individual Skills'), ' — Toggle specific capabilities on or off for fine-grained control.')
|
|
136
|
+
),
|
|
137
|
+
h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Start with a suite, then remove individual skills you don\'t need. Changes apply immediately if the agent is running (hot-update).')
|
|
138
|
+
)),
|
|
131
139
|
h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
|
|
132
140
|
h('span', { className: 'badge badge-primary' }, currentSkills.length + ' skills'),
|
|
133
141
|
h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit Skills')
|
|
@@ -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
|
)
|