@agenticmail/enterprise 0.5.42 → 0.5.44
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.
|
@@ -219,6 +219,9 @@ function OverviewSection(props) {
|
|
|
219
219
|
var createdAt = engineAgent?.createdAt || engineAgent?.created_at || agent?.createdAt;
|
|
220
220
|
var agentState = engineAgent?.state || engineAgent?.status || agent?.status || 'unknown';
|
|
221
221
|
var stateColor = { running: 'success', active: 'success', deploying: 'info', starting: 'info', ready: 'primary', degraded: 'warning', error: 'danger', stopped: 'neutral', draft: 'neutral' }[agentState] || 'neutral';
|
|
222
|
+
var resolvedMgr = resolveManager(config, props.agents);
|
|
223
|
+
var managerName = resolvedMgr ? resolvedMgr.name : null;
|
|
224
|
+
var managerEmail = resolvedMgr && resolvedMgr.type === 'external' ? resolvedMgr.email : null;
|
|
222
225
|
|
|
223
226
|
// Personality traits — can be object (keyed) or array
|
|
224
227
|
var rawTraits = identity.personality_traits || identity.traits || config.personality_traits || {};
|
|
@@ -239,7 +242,7 @@ function OverviewSection(props) {
|
|
|
239
242
|
// ─── Agent Summary Card ─────────────────────────────
|
|
240
243
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
241
244
|
h('div', { className: 'card-body' },
|
|
242
|
-
h('div', { style: { display: 'grid', gridTemplateColumns: '
|
|
245
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 16 } },
|
|
243
246
|
h('div', null,
|
|
244
247
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Status'),
|
|
245
248
|
h('span', { className: 'badge badge-' + stateColor, style: { textTransform: 'capitalize' } }, agentState)
|
|
@@ -252,6 +255,15 @@ function OverviewSection(props) {
|
|
|
252
255
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Model'),
|
|
253
256
|
h('span', { style: { fontSize: 13, fontWeight: 500, fontFamily: 'var(--font-mono, monospace)' } }, agentModel)
|
|
254
257
|
),
|
|
258
|
+
h('div', null,
|
|
259
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Reports To'),
|
|
260
|
+
managerName
|
|
261
|
+
? h('span', null,
|
|
262
|
+
h('span', { style: { fontSize: 13, fontWeight: 500, color: 'var(--primary)', cursor: 'pointer' }, onClick: function() { if (resolvedMgr && resolvedMgr.type === 'internal') { /* navigate */ } } }, managerName),
|
|
263
|
+
managerEmail && h('div', { style: { fontSize: 11, color: 'var(--text-muted)', fontFamily: 'var(--font-mono, monospace)' } }, managerEmail)
|
|
264
|
+
)
|
|
265
|
+
: h('span', { style: { fontSize: 13, color: 'var(--text-muted)' } }, 'No manager')
|
|
266
|
+
),
|
|
255
267
|
h('div', null,
|
|
256
268
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Created'),
|
|
257
269
|
h('span', { style: { fontSize: 13, fontWeight: 500 } }, createdAt ? new Date(createdAt).toLocaleDateString() : '—')
|
|
@@ -3038,6 +3050,263 @@ function ConfigurationSection(props) {
|
|
|
3038
3050
|
);
|
|
3039
3051
|
}
|
|
3040
3052
|
|
|
3053
|
+
// ════════════════════════════════════════════════════════════
|
|
3054
|
+
// MANAGER & DAILY CATCH-UP SECTION
|
|
3055
|
+
// ════════════════════════════════════════════════════════════
|
|
3056
|
+
|
|
3057
|
+
var COMMON_TIMEZONES = [
|
|
3058
|
+
'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles',
|
|
3059
|
+
'America/Toronto', 'America/Vancouver', 'America/Sao_Paulo', 'America/Mexico_City',
|
|
3060
|
+
'Europe/London', 'Europe/Paris', 'Europe/Berlin', 'Europe/Amsterdam', 'Europe/Madrid',
|
|
3061
|
+
'Europe/Rome', 'Europe/Zurich', 'Europe/Stockholm', 'Europe/Warsaw', 'Europe/Istanbul',
|
|
3062
|
+
'Africa/Lagos', 'Africa/Cairo', 'Africa/Johannesburg', 'Africa/Nairobi',
|
|
3063
|
+
'Asia/Dubai', 'Asia/Kolkata', 'Asia/Singapore', 'Asia/Tokyo', 'Asia/Shanghai',
|
|
3064
|
+
'Asia/Seoul', 'Asia/Hong_Kong', 'Asia/Bangkok', 'Asia/Jakarta',
|
|
3065
|
+
'Australia/Sydney', 'Australia/Melbourne', 'Pacific/Auckland'
|
|
3066
|
+
];
|
|
3067
|
+
|
|
3068
|
+
function resolveManager(config, allAgents) {
|
|
3069
|
+
var mgr = config.manager || {};
|
|
3070
|
+
// Legacy: managerId at top level
|
|
3071
|
+
var legacyId = config.managerId;
|
|
3072
|
+
if (mgr.type === 'external') {
|
|
3073
|
+
return { type: 'external', name: mgr.name || '', email: mgr.email || '' };
|
|
3074
|
+
}
|
|
3075
|
+
var internalId = mgr.agentId || legacyId;
|
|
3076
|
+
if (internalId) {
|
|
3077
|
+
var found = (allAgents || []).find(function(a) { return a.id === internalId; });
|
|
3078
|
+
return { type: 'internal', agentId: internalId, name: found ? (found.config?.identity?.name || found.config?.displayName || found.name || internalId) : internalId };
|
|
3079
|
+
}
|
|
3080
|
+
return null;
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
function ManagerCatchUpSection(props) {
|
|
3084
|
+
var agentId = props.agentId;
|
|
3085
|
+
var engineAgent = props.engineAgent;
|
|
3086
|
+
var allAgents = props.agents || [];
|
|
3087
|
+
var reload = props.reload;
|
|
3088
|
+
var toast = useApp().toast;
|
|
3089
|
+
|
|
3090
|
+
var ea = engineAgent || {};
|
|
3091
|
+
var config = ea.config || {};
|
|
3092
|
+
var catchUp = config.dailyCatchUp || {};
|
|
3093
|
+
|
|
3094
|
+
var resolved = resolveManager(config, allAgents);
|
|
3095
|
+
|
|
3096
|
+
var _editing = useState(false);
|
|
3097
|
+
var editing = _editing[0]; var setEditing = _editing[1];
|
|
3098
|
+
var _saving = useState(false);
|
|
3099
|
+
var saving = _saving[0]; var setSaving = _saving[1];
|
|
3100
|
+
var _form = useState({});
|
|
3101
|
+
var form = _form[0]; var setForm = _form[1];
|
|
3102
|
+
|
|
3103
|
+
var startEdit = function() {
|
|
3104
|
+
setForm({
|
|
3105
|
+
managerType: resolved ? resolved.type : 'none',
|
|
3106
|
+
managerAgentId: resolved && resolved.type === 'internal' ? resolved.agentId : '',
|
|
3107
|
+
managerName: resolved && resolved.type === 'external' ? resolved.name : '',
|
|
3108
|
+
managerEmail: resolved && resolved.type === 'external' ? resolved.email : '',
|
|
3109
|
+
catchUpEnabled: catchUp.enabled !== false && (catchUp.enabled || catchUp.time),
|
|
3110
|
+
catchUpTime: catchUp.time || '09:00',
|
|
3111
|
+
catchUpTimezone: catchUp.timezone || 'America/New_York',
|
|
3112
|
+
});
|
|
3113
|
+
setEditing(true);
|
|
3114
|
+
};
|
|
3115
|
+
|
|
3116
|
+
var set = function(k, v) { setForm(function(f) { var n = Object.assign({}, f); n[k] = v; return n; }); };
|
|
3117
|
+
|
|
3118
|
+
var save = function() {
|
|
3119
|
+
setSaving(true);
|
|
3120
|
+
var updates = {};
|
|
3121
|
+
|
|
3122
|
+
// Build manager object
|
|
3123
|
+
if (form.managerType === 'external') {
|
|
3124
|
+
if (!form.managerName || !form.managerEmail) {
|
|
3125
|
+
toast('Manager name and email are required', 'error');
|
|
3126
|
+
setSaving(false);
|
|
3127
|
+
return;
|
|
3128
|
+
}
|
|
3129
|
+
updates.manager = { type: 'external', name: form.managerName, email: form.managerEmail };
|
|
3130
|
+
updates.managerId = null; // clear legacy
|
|
3131
|
+
} else if (form.managerType === 'internal') {
|
|
3132
|
+
if (!form.managerAgentId) {
|
|
3133
|
+
toast('Select an agent', 'error');
|
|
3134
|
+
setSaving(false);
|
|
3135
|
+
return;
|
|
3136
|
+
}
|
|
3137
|
+
updates.manager = { type: 'internal', agentId: form.managerAgentId };
|
|
3138
|
+
updates.managerId = form.managerAgentId; // keep legacy compat
|
|
3139
|
+
} else {
|
|
3140
|
+
updates.manager = null;
|
|
3141
|
+
updates.managerId = null;
|
|
3142
|
+
}
|
|
3143
|
+
|
|
3144
|
+
// Build dailyCatchUp
|
|
3145
|
+
if (form.catchUpEnabled) {
|
|
3146
|
+
updates.dailyCatchUp = {
|
|
3147
|
+
enabled: true,
|
|
3148
|
+
time: form.catchUpTime,
|
|
3149
|
+
timezone: form.catchUpTimezone,
|
|
3150
|
+
};
|
|
3151
|
+
} else {
|
|
3152
|
+
updates.dailyCatchUp = { enabled: false };
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
var isRunning = ea.state === 'running' || ea.state === 'active' || ea.state === 'degraded';
|
|
3156
|
+
var endpoint = isRunning ? '/agents/' + agentId + '/hot-update' : '/agents/' + agentId + '/config';
|
|
3157
|
+
var method = isRunning ? 'POST' : 'PATCH';
|
|
3158
|
+
|
|
3159
|
+
engineCall(endpoint, { method: method, body: JSON.stringify({ updates: updates, updatedBy: 'dashboard' }) })
|
|
3160
|
+
.then(function() { toast('Manager & catch-up saved', 'success'); setEditing(false); setSaving(false); reload(); })
|
|
3161
|
+
.catch(function(err) { toast('Failed to save: ' + err.message, 'error'); setSaving(false); });
|
|
3162
|
+
};
|
|
3163
|
+
|
|
3164
|
+
var labelStyle = { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 };
|
|
3165
|
+
var inputStyle = { width: '100%', padding: '8px 10px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', fontSize: 13 };
|
|
3166
|
+
var fieldGroupStyle = { marginBottom: 16 };
|
|
3167
|
+
var rowStyle = { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 };
|
|
3168
|
+
|
|
3169
|
+
// Other agents this agent could report to (exclude self)
|
|
3170
|
+
var otherAgents = allAgents.filter(function(a) { return a.id !== agentId; });
|
|
3171
|
+
|
|
3172
|
+
if (editing) {
|
|
3173
|
+
return h(Fragment, null,
|
|
3174
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
3175
|
+
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Edit Manager & Daily Catch-Up'),
|
|
3176
|
+
h('div', { style: { display: 'flex', gap: 8 } },
|
|
3177
|
+
h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { setEditing(false); } }, 'Cancel'),
|
|
3178
|
+
h('button', { className: 'btn btn-primary btn-sm', disabled: saving, onClick: save }, saving ? 'Saving...' : 'Save Changes')
|
|
3179
|
+
)
|
|
3180
|
+
),
|
|
3181
|
+
|
|
3182
|
+
// Manager Card
|
|
3183
|
+
h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
|
|
3184
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Manager'),
|
|
3185
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)', marginTop: 0, marginBottom: 16 } }, 'Assign a manager this agent reports to. Can be another agent in the system or an external person (name + email).'),
|
|
3186
|
+
|
|
3187
|
+
h('div', { style: fieldGroupStyle },
|
|
3188
|
+
h('label', { style: labelStyle }, 'Manager Type'),
|
|
3189
|
+
h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.managerType, onChange: function(e) {
|
|
3190
|
+
set('managerType', e.target.value);
|
|
3191
|
+
if (e.target.value === 'none') { set('managerAgentId', ''); set('managerName', ''); set('managerEmail', ''); }
|
|
3192
|
+
} },
|
|
3193
|
+
h('option', { value: 'none' }, 'No manager'),
|
|
3194
|
+
h('option', { value: 'internal' }, 'Another agent in this organization'),
|
|
3195
|
+
h('option', { value: 'external' }, 'External person (name + email)')
|
|
3196
|
+
)
|
|
3197
|
+
),
|
|
3198
|
+
|
|
3199
|
+
form.managerType === 'internal' && h('div', { style: fieldGroupStyle },
|
|
3200
|
+
h('label', { style: labelStyle }, 'Select Agent'),
|
|
3201
|
+
h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.managerAgentId, onChange: function(e) { set('managerAgentId', e.target.value); } },
|
|
3202
|
+
h('option', { value: '' }, '-- Select agent --'),
|
|
3203
|
+
otherAgents.map(function(a) {
|
|
3204
|
+
var name = a.config?.identity?.name || a.config?.displayName || a.name || a.id;
|
|
3205
|
+
var role = a.config?.identity?.role || a.config?.role || '';
|
|
3206
|
+
return h('option', { key: a.id, value: a.id }, name + (role ? ' (' + role + ')' : ''));
|
|
3207
|
+
})
|
|
3208
|
+
)
|
|
3209
|
+
),
|
|
3210
|
+
|
|
3211
|
+
form.managerType === 'external' && h(Fragment, null,
|
|
3212
|
+
h('div', { style: rowStyle },
|
|
3213
|
+
h('div', { style: fieldGroupStyle },
|
|
3214
|
+
h('label', { style: labelStyle }, 'Manager Name'),
|
|
3215
|
+
h('input', { style: inputStyle, type: 'text', value: form.managerName, placeholder: 'e.g. Sarah Johnson', onChange: function(e) { set('managerName', e.target.value); } })
|
|
3216
|
+
),
|
|
3217
|
+
h('div', { style: fieldGroupStyle },
|
|
3218
|
+
h('label', { style: labelStyle }, 'Manager Email'),
|
|
3219
|
+
h('input', { style: inputStyle, type: 'email', value: form.managerEmail, placeholder: 'e.g. sarah@company.com', onChange: function(e) { set('managerEmail', e.target.value); } })
|
|
3220
|
+
)
|
|
3221
|
+
),
|
|
3222
|
+
h('p', { style: { fontSize: 12, color: 'var(--text-muted)', marginTop: 0, marginBottom: 0 } }, 'The agent will email this person for daily catch-ups, status reports, and escalations.')
|
|
3223
|
+
)
|
|
3224
|
+
),
|
|
3225
|
+
|
|
3226
|
+
// Daily Catch-Up Card
|
|
3227
|
+
h('div', { className: 'card', style: { padding: 20 } },
|
|
3228
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Daily Catch-Up'),
|
|
3229
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)', marginTop: 0, marginBottom: 16 } }, 'When enabled, the agent sends a daily status email to its manager with goals, progress, and blockers.'),
|
|
3230
|
+
|
|
3231
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 } },
|
|
3232
|
+
h('label', { style: { display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', fontSize: 13, fontWeight: 600 } },
|
|
3233
|
+
h('input', { type: 'checkbox', checked: form.catchUpEnabled, onChange: function(e) { set('catchUpEnabled', e.target.checked); } }),
|
|
3234
|
+
'Enable daily catch-up'
|
|
3235
|
+
)
|
|
3236
|
+
),
|
|
3237
|
+
|
|
3238
|
+
form.catchUpEnabled && h('div', { style: rowStyle },
|
|
3239
|
+
h('div', { style: fieldGroupStyle },
|
|
3240
|
+
h('label', { style: labelStyle }, 'Time'),
|
|
3241
|
+
h('input', { style: inputStyle, type: 'time', value: form.catchUpTime, onChange: function(e) { set('catchUpTime', e.target.value); } })
|
|
3242
|
+
),
|
|
3243
|
+
h('div', { style: fieldGroupStyle },
|
|
3244
|
+
h('label', { style: labelStyle }, 'Timezone'),
|
|
3245
|
+
h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.catchUpTimezone, onChange: function(e) { set('catchUpTimezone', e.target.value); } },
|
|
3246
|
+
COMMON_TIMEZONES.map(function(tz) { return h('option', { key: tz, value: tz }, tz.replace(/_/g, ' ')); })
|
|
3247
|
+
)
|
|
3248
|
+
)
|
|
3249
|
+
),
|
|
3250
|
+
|
|
3251
|
+
form.catchUpEnabled && !form.managerType !== 'none' && form.managerType === 'none' && h('div', {
|
|
3252
|
+
style: { padding: '10px 14px', background: 'var(--warning-soft, #fff3cd)', borderRadius: 6, fontSize: 13, color: 'var(--warning-text, #856404)', marginTop: 12 }
|
|
3253
|
+
}, 'Note: Catch-up is enabled but no manager is assigned. The agent won\'t have anyone to report to.')
|
|
3254
|
+
)
|
|
3255
|
+
);
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3258
|
+
// View mode
|
|
3259
|
+
var catchUpEnabled = catchUp.enabled || catchUp.time;
|
|
3260
|
+
var catchUpTime = catchUp.time || '09:00';
|
|
3261
|
+
var catchUpTz = catchUp.timezone || 'America/New_York';
|
|
3262
|
+
|
|
3263
|
+
return h(Fragment, null,
|
|
3264
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
3265
|
+
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Manager & Daily Catch-Up'),
|
|
3266
|
+
h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit')
|
|
3267
|
+
),
|
|
3268
|
+
|
|
3269
|
+
// Manager Card
|
|
3270
|
+
h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
|
|
3271
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Reports To'),
|
|
3272
|
+
resolved
|
|
3273
|
+
? h('div', { style: { display: 'flex', alignItems: 'center', gap: 12 } },
|
|
3274
|
+
h('div', { style: {
|
|
3275
|
+
width: 40, height: 40, borderRadius: '50%', background: resolved.type === 'external' ? 'var(--accent)' : 'var(--primary)',
|
|
3276
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16, fontWeight: 700, color: '#fff', flexShrink: 0
|
|
3277
|
+
} }, (resolved.name || '?').charAt(0).toUpperCase()),
|
|
3278
|
+
h('div', null,
|
|
3279
|
+
h('div', { style: { fontSize: 14, fontWeight: 600 } }, resolved.name),
|
|
3280
|
+
resolved.type === 'external'
|
|
3281
|
+
? h('div', { style: { fontSize: 13, color: 'var(--text-muted)', fontFamily: 'var(--font-mono, monospace)' } }, resolved.email)
|
|
3282
|
+
: h('span', { className: 'badge badge-neutral', style: { fontSize: 11 } }, 'Internal Agent')
|
|
3283
|
+
)
|
|
3284
|
+
)
|
|
3285
|
+
: h('div', { style: { fontSize: 14, color: 'var(--text-muted)' } }, 'No manager assigned')
|
|
3286
|
+
),
|
|
3287
|
+
|
|
3288
|
+
// Daily Catch-Up Card
|
|
3289
|
+
h('div', { className: 'card', style: { padding: 20 } },
|
|
3290
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Daily Catch-Up'),
|
|
3291
|
+
catchUpEnabled
|
|
3292
|
+
? h('div', null,
|
|
3293
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 } },
|
|
3294
|
+
h('span', { style: { width: 8, height: 8, borderRadius: '50%', background: 'var(--success)', display: 'inline-block' } }),
|
|
3295
|
+
h('span', { style: { fontSize: 14, fontWeight: 600 } }, 'Active')
|
|
3296
|
+
),
|
|
3297
|
+
h('div', { style: { fontSize: 13, color: 'var(--text-secondary)' } },
|
|
3298
|
+
'Sends daily at ', h('strong', null, catchUpTime), ' ', catchUpTz.replace(/_/g, ' ')
|
|
3299
|
+
),
|
|
3300
|
+
!resolved && h('div', { style: { fontSize: 12, color: 'var(--warning-text, #856404)', marginTop: 8 } }, 'Warning: No manager assigned — catch-up emails have no recipient.')
|
|
3301
|
+
)
|
|
3302
|
+
: h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
3303
|
+
h('span', { style: { width: 8, height: 8, borderRadius: '50%', background: 'var(--text-muted)', display: 'inline-block' } }),
|
|
3304
|
+
h('span', { style: { fontSize: 14, color: 'var(--text-muted)' } }, 'Not configured')
|
|
3305
|
+
)
|
|
3306
|
+
)
|
|
3307
|
+
);
|
|
3308
|
+
}
|
|
3309
|
+
|
|
3041
3310
|
// ════════════════════════════════════════════════════════════
|
|
3042
3311
|
// SKILLS SECTION — View and manage agent skills
|
|
3043
3312
|
// ════════════════════════════════════════════════════════════
|
|
@@ -3897,8 +4166,8 @@ function AgentDetailPage(props) {
|
|
|
3897
4166
|
var _agents = useState([]);
|
|
3898
4167
|
var agents = _agents[0]; var setAgents = _agents[1];
|
|
3899
4168
|
|
|
3900
|
-
var TABS = ['overview', 'personal', 'configuration', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
|
|
3901
|
-
var TAB_LABELS = { 'tool-security': 'Tool Security' };
|
|
4169
|
+
var TABS = ['overview', 'personal', 'configuration', 'manager', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
|
|
4170
|
+
var TAB_LABELS = { 'tool-security': 'Tool Security', 'manager': 'Manager & Catch-Up' };
|
|
3902
4171
|
|
|
3903
4172
|
var load = function() {
|
|
3904
4173
|
setLoading(true);
|
|
@@ -4020,6 +4289,7 @@ function AgentDetailPage(props) {
|
|
|
4020
4289
|
tab === 'overview' && h(OverviewSection, { agentId: agentId, agent: agent, engineAgent: engineAgent, profile: profile, reload: load, agents: agents, onBack: onBack }),
|
|
4021
4290
|
tab === 'personal' && h(PersonalDetailsSection, { agentId: agentId, agent: agent, engineAgent: engineAgent, reload: load }),
|
|
4022
4291
|
tab === 'configuration' && h(ConfigurationSection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
|
|
4292
|
+
tab === 'manager' && h(ManagerCatchUpSection, { agentId: agentId, engineAgent: engineAgent, agents: agents, reload: load }),
|
|
4023
4293
|
tab === 'skills' && h(SkillsSection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
|
|
4024
4294
|
tab === 'permissions' && h(PermissionsSection, { agentId: agentId, profile: profile, reload: load }),
|
|
4025
4295
|
tab === 'activity' && h(ActivitySection, { agentId: agentId }),
|
|
@@ -211,6 +211,18 @@ export function SkillsPage() {
|
|
|
211
211
|
setConfigSaving(false);
|
|
212
212
|
};
|
|
213
213
|
|
|
214
|
+
// Install a builtin skill
|
|
215
|
+
var installBuiltinSkill = async function(skillId) {
|
|
216
|
+
try {
|
|
217
|
+
await engineCall('/community/skills/' + skillId + '/install', {
|
|
218
|
+
method: 'POST',
|
|
219
|
+
body: JSON.stringify({ orgId: getOrgId() })
|
|
220
|
+
});
|
|
221
|
+
toast('Skill installed', 'success');
|
|
222
|
+
loadInstalled();
|
|
223
|
+
} catch (e) { toast(e.message || 'Install failed', 'error'); }
|
|
224
|
+
};
|
|
225
|
+
|
|
214
226
|
// Computed
|
|
215
227
|
var allSkills = Object.entries(skills).flatMap(function(entry) {
|
|
216
228
|
return entry[1].map(function(s) { return Object.assign({}, s, { category: entry[0] }); });
|
|
@@ -246,11 +258,26 @@ export function SkillsPage() {
|
|
|
246
258
|
return h('div', { key: cat, style: { marginBottom: 24 } },
|
|
247
259
|
h('h3', { style: { fontSize: 13, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--text-muted)', marginBottom: 10 } }, cat.replace(/-/g, ' ')),
|
|
248
260
|
h('div', { className: 'skill-grid' }, list.map(function(s) {
|
|
261
|
+
var isInstalled = installed.some(function(i) { return i.skillId === s.id; });
|
|
249
262
|
return h('div', { key: s.id, className: 'skill-card' },
|
|
250
263
|
h('div', { className: 'skill-cat' }, s.category || cat),
|
|
251
264
|
h('div', { className: 'skill-name' }, s.name),
|
|
252
265
|
h('div', { className: 'skill-desc' }, s.description),
|
|
253
|
-
s.tools && h('div', { style: { marginTop: 6, fontSize: 11, color: 'var(--text-muted)' } }, s.tools.length + ' tools')
|
|
266
|
+
s.tools && h('div', { style: { marginTop: 6, fontSize: 11, color: 'var(--text-muted)' } }, s.tools.length + ' tools'),
|
|
267
|
+
h('div', { style: { marginTop: 8, display: 'flex', gap: 6 } },
|
|
268
|
+
isInstalled
|
|
269
|
+
? h('span', { style: { fontSize: 11, color: 'var(--success)', fontWeight: 600 } }, '\u2713 Installed')
|
|
270
|
+
: h('button', {
|
|
271
|
+
className: 'btn btn-primary btn-sm',
|
|
272
|
+
style: { fontSize: 11, padding: '3px 10px' },
|
|
273
|
+
onClick: function() { installBuiltinSkill(s.id); }
|
|
274
|
+
}, 'Install'),
|
|
275
|
+
!isInstalled && h('button', {
|
|
276
|
+
className: 'btn btn-secondary btn-sm',
|
|
277
|
+
style: { fontSize: 11, padding: '3px 10px' },
|
|
278
|
+
onClick: function() { setTokenModal({ skillId: s.id, skillName: s.name }); }
|
|
279
|
+
}, 'Add Token')
|
|
280
|
+
)
|
|
254
281
|
);
|
|
255
282
|
}))
|
|
256
283
|
);
|
package/package.json
CHANGED
|
@@ -219,6 +219,9 @@ function OverviewSection(props) {
|
|
|
219
219
|
var createdAt = engineAgent?.createdAt || engineAgent?.created_at || agent?.createdAt;
|
|
220
220
|
var agentState = engineAgent?.state || engineAgent?.status || agent?.status || 'unknown';
|
|
221
221
|
var stateColor = { running: 'success', active: 'success', deploying: 'info', starting: 'info', ready: 'primary', degraded: 'warning', error: 'danger', stopped: 'neutral', draft: 'neutral' }[agentState] || 'neutral';
|
|
222
|
+
var resolvedMgr = resolveManager(config, props.agents);
|
|
223
|
+
var managerName = resolvedMgr ? resolvedMgr.name : null;
|
|
224
|
+
var managerEmail = resolvedMgr && resolvedMgr.type === 'external' ? resolvedMgr.email : null;
|
|
222
225
|
|
|
223
226
|
// Personality traits — can be object (keyed) or array
|
|
224
227
|
var rawTraits = identity.personality_traits || identity.traits || config.personality_traits || {};
|
|
@@ -239,7 +242,7 @@ function OverviewSection(props) {
|
|
|
239
242
|
// ─── Agent Summary Card ─────────────────────────────
|
|
240
243
|
h('div', { className: 'card', style: { marginBottom: 20 } },
|
|
241
244
|
h('div', { className: 'card-body' },
|
|
242
|
-
h('div', { style: { display: 'grid', gridTemplateColumns: '
|
|
245
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 16 } },
|
|
243
246
|
h('div', null,
|
|
244
247
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Status'),
|
|
245
248
|
h('span', { className: 'badge badge-' + stateColor, style: { textTransform: 'capitalize' } }, agentState)
|
|
@@ -252,6 +255,15 @@ function OverviewSection(props) {
|
|
|
252
255
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Model'),
|
|
253
256
|
h('span', { style: { fontSize: 13, fontWeight: 500, fontFamily: 'var(--font-mono, monospace)' } }, agentModel)
|
|
254
257
|
),
|
|
258
|
+
h('div', null,
|
|
259
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Reports To'),
|
|
260
|
+
managerName
|
|
261
|
+
? h('span', null,
|
|
262
|
+
h('span', { style: { fontSize: 13, fontWeight: 500, color: 'var(--primary)', cursor: 'pointer' }, onClick: function() { if (resolvedMgr && resolvedMgr.type === 'internal') { /* navigate */ } } }, managerName),
|
|
263
|
+
managerEmail && h('div', { style: { fontSize: 11, color: 'var(--text-muted)', fontFamily: 'var(--font-mono, monospace)' } }, managerEmail)
|
|
264
|
+
)
|
|
265
|
+
: h('span', { style: { fontSize: 13, color: 'var(--text-muted)' } }, 'No manager')
|
|
266
|
+
),
|
|
255
267
|
h('div', null,
|
|
256
268
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 600 } }, 'Created'),
|
|
257
269
|
h('span', { style: { fontSize: 13, fontWeight: 500 } }, createdAt ? new Date(createdAt).toLocaleDateString() : '—')
|
|
@@ -3038,6 +3050,263 @@ function ConfigurationSection(props) {
|
|
|
3038
3050
|
);
|
|
3039
3051
|
}
|
|
3040
3052
|
|
|
3053
|
+
// ════════════════════════════════════════════════════════════
|
|
3054
|
+
// MANAGER & DAILY CATCH-UP SECTION
|
|
3055
|
+
// ════════════════════════════════════════════════════════════
|
|
3056
|
+
|
|
3057
|
+
var COMMON_TIMEZONES = [
|
|
3058
|
+
'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles',
|
|
3059
|
+
'America/Toronto', 'America/Vancouver', 'America/Sao_Paulo', 'America/Mexico_City',
|
|
3060
|
+
'Europe/London', 'Europe/Paris', 'Europe/Berlin', 'Europe/Amsterdam', 'Europe/Madrid',
|
|
3061
|
+
'Europe/Rome', 'Europe/Zurich', 'Europe/Stockholm', 'Europe/Warsaw', 'Europe/Istanbul',
|
|
3062
|
+
'Africa/Lagos', 'Africa/Cairo', 'Africa/Johannesburg', 'Africa/Nairobi',
|
|
3063
|
+
'Asia/Dubai', 'Asia/Kolkata', 'Asia/Singapore', 'Asia/Tokyo', 'Asia/Shanghai',
|
|
3064
|
+
'Asia/Seoul', 'Asia/Hong_Kong', 'Asia/Bangkok', 'Asia/Jakarta',
|
|
3065
|
+
'Australia/Sydney', 'Australia/Melbourne', 'Pacific/Auckland'
|
|
3066
|
+
];
|
|
3067
|
+
|
|
3068
|
+
function resolveManager(config, allAgents) {
|
|
3069
|
+
var mgr = config.manager || {};
|
|
3070
|
+
// Legacy: managerId at top level
|
|
3071
|
+
var legacyId = config.managerId;
|
|
3072
|
+
if (mgr.type === 'external') {
|
|
3073
|
+
return { type: 'external', name: mgr.name || '', email: mgr.email || '' };
|
|
3074
|
+
}
|
|
3075
|
+
var internalId = mgr.agentId || legacyId;
|
|
3076
|
+
if (internalId) {
|
|
3077
|
+
var found = (allAgents || []).find(function(a) { return a.id === internalId; });
|
|
3078
|
+
return { type: 'internal', agentId: internalId, name: found ? (found.config?.identity?.name || found.config?.displayName || found.name || internalId) : internalId };
|
|
3079
|
+
}
|
|
3080
|
+
return null;
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
function ManagerCatchUpSection(props) {
|
|
3084
|
+
var agentId = props.agentId;
|
|
3085
|
+
var engineAgent = props.engineAgent;
|
|
3086
|
+
var allAgents = props.agents || [];
|
|
3087
|
+
var reload = props.reload;
|
|
3088
|
+
var toast = useApp().toast;
|
|
3089
|
+
|
|
3090
|
+
var ea = engineAgent || {};
|
|
3091
|
+
var config = ea.config || {};
|
|
3092
|
+
var catchUp = config.dailyCatchUp || {};
|
|
3093
|
+
|
|
3094
|
+
var resolved = resolveManager(config, allAgents);
|
|
3095
|
+
|
|
3096
|
+
var _editing = useState(false);
|
|
3097
|
+
var editing = _editing[0]; var setEditing = _editing[1];
|
|
3098
|
+
var _saving = useState(false);
|
|
3099
|
+
var saving = _saving[0]; var setSaving = _saving[1];
|
|
3100
|
+
var _form = useState({});
|
|
3101
|
+
var form = _form[0]; var setForm = _form[1];
|
|
3102
|
+
|
|
3103
|
+
var startEdit = function() {
|
|
3104
|
+
setForm({
|
|
3105
|
+
managerType: resolved ? resolved.type : 'none',
|
|
3106
|
+
managerAgentId: resolved && resolved.type === 'internal' ? resolved.agentId : '',
|
|
3107
|
+
managerName: resolved && resolved.type === 'external' ? resolved.name : '',
|
|
3108
|
+
managerEmail: resolved && resolved.type === 'external' ? resolved.email : '',
|
|
3109
|
+
catchUpEnabled: catchUp.enabled !== false && (catchUp.enabled || catchUp.time),
|
|
3110
|
+
catchUpTime: catchUp.time || '09:00',
|
|
3111
|
+
catchUpTimezone: catchUp.timezone || 'America/New_York',
|
|
3112
|
+
});
|
|
3113
|
+
setEditing(true);
|
|
3114
|
+
};
|
|
3115
|
+
|
|
3116
|
+
var set = function(k, v) { setForm(function(f) { var n = Object.assign({}, f); n[k] = v; return n; }); };
|
|
3117
|
+
|
|
3118
|
+
var save = function() {
|
|
3119
|
+
setSaving(true);
|
|
3120
|
+
var updates = {};
|
|
3121
|
+
|
|
3122
|
+
// Build manager object
|
|
3123
|
+
if (form.managerType === 'external') {
|
|
3124
|
+
if (!form.managerName || !form.managerEmail) {
|
|
3125
|
+
toast('Manager name and email are required', 'error');
|
|
3126
|
+
setSaving(false);
|
|
3127
|
+
return;
|
|
3128
|
+
}
|
|
3129
|
+
updates.manager = { type: 'external', name: form.managerName, email: form.managerEmail };
|
|
3130
|
+
updates.managerId = null; // clear legacy
|
|
3131
|
+
} else if (form.managerType === 'internal') {
|
|
3132
|
+
if (!form.managerAgentId) {
|
|
3133
|
+
toast('Select an agent', 'error');
|
|
3134
|
+
setSaving(false);
|
|
3135
|
+
return;
|
|
3136
|
+
}
|
|
3137
|
+
updates.manager = { type: 'internal', agentId: form.managerAgentId };
|
|
3138
|
+
updates.managerId = form.managerAgentId; // keep legacy compat
|
|
3139
|
+
} else {
|
|
3140
|
+
updates.manager = null;
|
|
3141
|
+
updates.managerId = null;
|
|
3142
|
+
}
|
|
3143
|
+
|
|
3144
|
+
// Build dailyCatchUp
|
|
3145
|
+
if (form.catchUpEnabled) {
|
|
3146
|
+
updates.dailyCatchUp = {
|
|
3147
|
+
enabled: true,
|
|
3148
|
+
time: form.catchUpTime,
|
|
3149
|
+
timezone: form.catchUpTimezone,
|
|
3150
|
+
};
|
|
3151
|
+
} else {
|
|
3152
|
+
updates.dailyCatchUp = { enabled: false };
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
var isRunning = ea.state === 'running' || ea.state === 'active' || ea.state === 'degraded';
|
|
3156
|
+
var endpoint = isRunning ? '/agents/' + agentId + '/hot-update' : '/agents/' + agentId + '/config';
|
|
3157
|
+
var method = isRunning ? 'POST' : 'PATCH';
|
|
3158
|
+
|
|
3159
|
+
engineCall(endpoint, { method: method, body: JSON.stringify({ updates: updates, updatedBy: 'dashboard' }) })
|
|
3160
|
+
.then(function() { toast('Manager & catch-up saved', 'success'); setEditing(false); setSaving(false); reload(); })
|
|
3161
|
+
.catch(function(err) { toast('Failed to save: ' + err.message, 'error'); setSaving(false); });
|
|
3162
|
+
};
|
|
3163
|
+
|
|
3164
|
+
var labelStyle = { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 };
|
|
3165
|
+
var inputStyle = { width: '100%', padding: '8px 10px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', fontSize: 13 };
|
|
3166
|
+
var fieldGroupStyle = { marginBottom: 16 };
|
|
3167
|
+
var rowStyle = { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 };
|
|
3168
|
+
|
|
3169
|
+
// Other agents this agent could report to (exclude self)
|
|
3170
|
+
var otherAgents = allAgents.filter(function(a) { return a.id !== agentId; });
|
|
3171
|
+
|
|
3172
|
+
if (editing) {
|
|
3173
|
+
return h(Fragment, null,
|
|
3174
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
3175
|
+
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Edit Manager & Daily Catch-Up'),
|
|
3176
|
+
h('div', { style: { display: 'flex', gap: 8 } },
|
|
3177
|
+
h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { setEditing(false); } }, 'Cancel'),
|
|
3178
|
+
h('button', { className: 'btn btn-primary btn-sm', disabled: saving, onClick: save }, saving ? 'Saving...' : 'Save Changes')
|
|
3179
|
+
)
|
|
3180
|
+
),
|
|
3181
|
+
|
|
3182
|
+
// Manager Card
|
|
3183
|
+
h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
|
|
3184
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Manager'),
|
|
3185
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)', marginTop: 0, marginBottom: 16 } }, 'Assign a manager this agent reports to. Can be another agent in the system or an external person (name + email).'),
|
|
3186
|
+
|
|
3187
|
+
h('div', { style: fieldGroupStyle },
|
|
3188
|
+
h('label', { style: labelStyle }, 'Manager Type'),
|
|
3189
|
+
h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.managerType, onChange: function(e) {
|
|
3190
|
+
set('managerType', e.target.value);
|
|
3191
|
+
if (e.target.value === 'none') { set('managerAgentId', ''); set('managerName', ''); set('managerEmail', ''); }
|
|
3192
|
+
} },
|
|
3193
|
+
h('option', { value: 'none' }, 'No manager'),
|
|
3194
|
+
h('option', { value: 'internal' }, 'Another agent in this organization'),
|
|
3195
|
+
h('option', { value: 'external' }, 'External person (name + email)')
|
|
3196
|
+
)
|
|
3197
|
+
),
|
|
3198
|
+
|
|
3199
|
+
form.managerType === 'internal' && h('div', { style: fieldGroupStyle },
|
|
3200
|
+
h('label', { style: labelStyle }, 'Select Agent'),
|
|
3201
|
+
h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.managerAgentId, onChange: function(e) { set('managerAgentId', e.target.value); } },
|
|
3202
|
+
h('option', { value: '' }, '-- Select agent --'),
|
|
3203
|
+
otherAgents.map(function(a) {
|
|
3204
|
+
var name = a.config?.identity?.name || a.config?.displayName || a.name || a.id;
|
|
3205
|
+
var role = a.config?.identity?.role || a.config?.role || '';
|
|
3206
|
+
return h('option', { key: a.id, value: a.id }, name + (role ? ' (' + role + ')' : ''));
|
|
3207
|
+
})
|
|
3208
|
+
)
|
|
3209
|
+
),
|
|
3210
|
+
|
|
3211
|
+
form.managerType === 'external' && h(Fragment, null,
|
|
3212
|
+
h('div', { style: rowStyle },
|
|
3213
|
+
h('div', { style: fieldGroupStyle },
|
|
3214
|
+
h('label', { style: labelStyle }, 'Manager Name'),
|
|
3215
|
+
h('input', { style: inputStyle, type: 'text', value: form.managerName, placeholder: 'e.g. Sarah Johnson', onChange: function(e) { set('managerName', e.target.value); } })
|
|
3216
|
+
),
|
|
3217
|
+
h('div', { style: fieldGroupStyle },
|
|
3218
|
+
h('label', { style: labelStyle }, 'Manager Email'),
|
|
3219
|
+
h('input', { style: inputStyle, type: 'email', value: form.managerEmail, placeholder: 'e.g. sarah@company.com', onChange: function(e) { set('managerEmail', e.target.value); } })
|
|
3220
|
+
)
|
|
3221
|
+
),
|
|
3222
|
+
h('p', { style: { fontSize: 12, color: 'var(--text-muted)', marginTop: 0, marginBottom: 0 } }, 'The agent will email this person for daily catch-ups, status reports, and escalations.')
|
|
3223
|
+
)
|
|
3224
|
+
),
|
|
3225
|
+
|
|
3226
|
+
// Daily Catch-Up Card
|
|
3227
|
+
h('div', { className: 'card', style: { padding: 20 } },
|
|
3228
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Daily Catch-Up'),
|
|
3229
|
+
h('p', { style: { fontSize: 13, color: 'var(--text-muted)', marginTop: 0, marginBottom: 16 } }, 'When enabled, the agent sends a daily status email to its manager with goals, progress, and blockers.'),
|
|
3230
|
+
|
|
3231
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 } },
|
|
3232
|
+
h('label', { style: { display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', fontSize: 13, fontWeight: 600 } },
|
|
3233
|
+
h('input', { type: 'checkbox', checked: form.catchUpEnabled, onChange: function(e) { set('catchUpEnabled', e.target.checked); } }),
|
|
3234
|
+
'Enable daily catch-up'
|
|
3235
|
+
)
|
|
3236
|
+
),
|
|
3237
|
+
|
|
3238
|
+
form.catchUpEnabled && h('div', { style: rowStyle },
|
|
3239
|
+
h('div', { style: fieldGroupStyle },
|
|
3240
|
+
h('label', { style: labelStyle }, 'Time'),
|
|
3241
|
+
h('input', { style: inputStyle, type: 'time', value: form.catchUpTime, onChange: function(e) { set('catchUpTime', e.target.value); } })
|
|
3242
|
+
),
|
|
3243
|
+
h('div', { style: fieldGroupStyle },
|
|
3244
|
+
h('label', { style: labelStyle }, 'Timezone'),
|
|
3245
|
+
h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.catchUpTimezone, onChange: function(e) { set('catchUpTimezone', e.target.value); } },
|
|
3246
|
+
COMMON_TIMEZONES.map(function(tz) { return h('option', { key: tz, value: tz }, tz.replace(/_/g, ' ')); })
|
|
3247
|
+
)
|
|
3248
|
+
)
|
|
3249
|
+
),
|
|
3250
|
+
|
|
3251
|
+
form.catchUpEnabled && !form.managerType !== 'none' && form.managerType === 'none' && h('div', {
|
|
3252
|
+
style: { padding: '10px 14px', background: 'var(--warning-soft, #fff3cd)', borderRadius: 6, fontSize: 13, color: 'var(--warning-text, #856404)', marginTop: 12 }
|
|
3253
|
+
}, 'Note: Catch-up is enabled but no manager is assigned. The agent won\'t have anyone to report to.')
|
|
3254
|
+
)
|
|
3255
|
+
);
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3258
|
+
// View mode
|
|
3259
|
+
var catchUpEnabled = catchUp.enabled || catchUp.time;
|
|
3260
|
+
var catchUpTime = catchUp.time || '09:00';
|
|
3261
|
+
var catchUpTz = catchUp.timezone || 'America/New_York';
|
|
3262
|
+
|
|
3263
|
+
return h(Fragment, null,
|
|
3264
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
|
|
3265
|
+
h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Manager & Daily Catch-Up'),
|
|
3266
|
+
h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit')
|
|
3267
|
+
),
|
|
3268
|
+
|
|
3269
|
+
// Manager Card
|
|
3270
|
+
h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
|
|
3271
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Reports To'),
|
|
3272
|
+
resolved
|
|
3273
|
+
? h('div', { style: { display: 'flex', alignItems: 'center', gap: 12 } },
|
|
3274
|
+
h('div', { style: {
|
|
3275
|
+
width: 40, height: 40, borderRadius: '50%', background: resolved.type === 'external' ? 'var(--accent)' : 'var(--primary)',
|
|
3276
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16, fontWeight: 700, color: '#fff', flexShrink: 0
|
|
3277
|
+
} }, (resolved.name || '?').charAt(0).toUpperCase()),
|
|
3278
|
+
h('div', null,
|
|
3279
|
+
h('div', { style: { fontSize: 14, fontWeight: 600 } }, resolved.name),
|
|
3280
|
+
resolved.type === 'external'
|
|
3281
|
+
? h('div', { style: { fontSize: 13, color: 'var(--text-muted)', fontFamily: 'var(--font-mono, monospace)' } }, resolved.email)
|
|
3282
|
+
: h('span', { className: 'badge badge-neutral', style: { fontSize: 11 } }, 'Internal Agent')
|
|
3283
|
+
)
|
|
3284
|
+
)
|
|
3285
|
+
: h('div', { style: { fontSize: 14, color: 'var(--text-muted)' } }, 'No manager assigned')
|
|
3286
|
+
),
|
|
3287
|
+
|
|
3288
|
+
// Daily Catch-Up Card
|
|
3289
|
+
h('div', { className: 'card', style: { padding: 20 } },
|
|
3290
|
+
h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Daily Catch-Up'),
|
|
3291
|
+
catchUpEnabled
|
|
3292
|
+
? h('div', null,
|
|
3293
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 } },
|
|
3294
|
+
h('span', { style: { width: 8, height: 8, borderRadius: '50%', background: 'var(--success)', display: 'inline-block' } }),
|
|
3295
|
+
h('span', { style: { fontSize: 14, fontWeight: 600 } }, 'Active')
|
|
3296
|
+
),
|
|
3297
|
+
h('div', { style: { fontSize: 13, color: 'var(--text-secondary)' } },
|
|
3298
|
+
'Sends daily at ', h('strong', null, catchUpTime), ' ', catchUpTz.replace(/_/g, ' ')
|
|
3299
|
+
),
|
|
3300
|
+
!resolved && h('div', { style: { fontSize: 12, color: 'var(--warning-text, #856404)', marginTop: 8 } }, 'Warning: No manager assigned — catch-up emails have no recipient.')
|
|
3301
|
+
)
|
|
3302
|
+
: h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
3303
|
+
h('span', { style: { width: 8, height: 8, borderRadius: '50%', background: 'var(--text-muted)', display: 'inline-block' } }),
|
|
3304
|
+
h('span', { style: { fontSize: 14, color: 'var(--text-muted)' } }, 'Not configured')
|
|
3305
|
+
)
|
|
3306
|
+
)
|
|
3307
|
+
);
|
|
3308
|
+
}
|
|
3309
|
+
|
|
3041
3310
|
// ════════════════════════════════════════════════════════════
|
|
3042
3311
|
// SKILLS SECTION — View and manage agent skills
|
|
3043
3312
|
// ════════════════════════════════════════════════════════════
|
|
@@ -3897,8 +4166,8 @@ function AgentDetailPage(props) {
|
|
|
3897
4166
|
var _agents = useState([]);
|
|
3898
4167
|
var agents = _agents[0]; var setAgents = _agents[1];
|
|
3899
4168
|
|
|
3900
|
-
var TABS = ['overview', 'personal', 'configuration', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
|
|
3901
|
-
var TAB_LABELS = { 'tool-security': 'Tool Security' };
|
|
4169
|
+
var TABS = ['overview', 'personal', 'configuration', 'manager', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
|
|
4170
|
+
var TAB_LABELS = { 'tool-security': 'Tool Security', 'manager': 'Manager & Catch-Up' };
|
|
3902
4171
|
|
|
3903
4172
|
var load = function() {
|
|
3904
4173
|
setLoading(true);
|
|
@@ -4020,6 +4289,7 @@ function AgentDetailPage(props) {
|
|
|
4020
4289
|
tab === 'overview' && h(OverviewSection, { agentId: agentId, agent: agent, engineAgent: engineAgent, profile: profile, reload: load, agents: agents, onBack: onBack }),
|
|
4021
4290
|
tab === 'personal' && h(PersonalDetailsSection, { agentId: agentId, agent: agent, engineAgent: engineAgent, reload: load }),
|
|
4022
4291
|
tab === 'configuration' && h(ConfigurationSection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
|
|
4292
|
+
tab === 'manager' && h(ManagerCatchUpSection, { agentId: agentId, engineAgent: engineAgent, agents: agents, reload: load }),
|
|
4023
4293
|
tab === 'skills' && h(SkillsSection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
|
|
4024
4294
|
tab === 'permissions' && h(PermissionsSection, { agentId: agentId, profile: profile, reload: load }),
|
|
4025
4295
|
tab === 'activity' && h(ActivitySection, { agentId: agentId }),
|
|
@@ -211,6 +211,18 @@ export function SkillsPage() {
|
|
|
211
211
|
setConfigSaving(false);
|
|
212
212
|
};
|
|
213
213
|
|
|
214
|
+
// Install a builtin skill
|
|
215
|
+
var installBuiltinSkill = async function(skillId) {
|
|
216
|
+
try {
|
|
217
|
+
await engineCall('/community/skills/' + skillId + '/install', {
|
|
218
|
+
method: 'POST',
|
|
219
|
+
body: JSON.stringify({ orgId: getOrgId() })
|
|
220
|
+
});
|
|
221
|
+
toast('Skill installed', 'success');
|
|
222
|
+
loadInstalled();
|
|
223
|
+
} catch (e) { toast(e.message || 'Install failed', 'error'); }
|
|
224
|
+
};
|
|
225
|
+
|
|
214
226
|
// Computed
|
|
215
227
|
var allSkills = Object.entries(skills).flatMap(function(entry) {
|
|
216
228
|
return entry[1].map(function(s) { return Object.assign({}, s, { category: entry[0] }); });
|
|
@@ -246,11 +258,26 @@ export function SkillsPage() {
|
|
|
246
258
|
return h('div', { key: cat, style: { marginBottom: 24 } },
|
|
247
259
|
h('h3', { style: { fontSize: 13, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--text-muted)', marginBottom: 10 } }, cat.replace(/-/g, ' ')),
|
|
248
260
|
h('div', { className: 'skill-grid' }, list.map(function(s) {
|
|
261
|
+
var isInstalled = installed.some(function(i) { return i.skillId === s.id; });
|
|
249
262
|
return h('div', { key: s.id, className: 'skill-card' },
|
|
250
263
|
h('div', { className: 'skill-cat' }, s.category || cat),
|
|
251
264
|
h('div', { className: 'skill-name' }, s.name),
|
|
252
265
|
h('div', { className: 'skill-desc' }, s.description),
|
|
253
|
-
s.tools && h('div', { style: { marginTop: 6, fontSize: 11, color: 'var(--text-muted)' } }, s.tools.length + ' tools')
|
|
266
|
+
s.tools && h('div', { style: { marginTop: 6, fontSize: 11, color: 'var(--text-muted)' } }, s.tools.length + ' tools'),
|
|
267
|
+
h('div', { style: { marginTop: 8, display: 'flex', gap: 6 } },
|
|
268
|
+
isInstalled
|
|
269
|
+
? h('span', { style: { fontSize: 11, color: 'var(--success)', fontWeight: 600 } }, '\u2713 Installed')
|
|
270
|
+
: h('button', {
|
|
271
|
+
className: 'btn btn-primary btn-sm',
|
|
272
|
+
style: { fontSize: 11, padding: '3px 10px' },
|
|
273
|
+
onClick: function() { installBuiltinSkill(s.id); }
|
|
274
|
+
}, 'Install'),
|
|
275
|
+
!isInstalled && h('button', {
|
|
276
|
+
className: 'btn btn-secondary btn-sm',
|
|
277
|
+
style: { fontSize: 11, padding: '3px 10px' },
|
|
278
|
+
onClick: function() { setTokenModal({ skillId: s.id, skillName: s.name }); }
|
|
279
|
+
}, 'Add Token')
|
|
280
|
+
)
|
|
254
281
|
);
|
|
255
282
|
}))
|
|
256
283
|
);
|