@agenticmail/enterprise 0.5.31 → 0.5.32

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.
@@ -0,0 +1,47 @@
1
+ import {
2
+ AgentRuntime,
3
+ EmailChannel,
4
+ FollowUpScheduler,
5
+ SessionManager,
6
+ SubAgentManager,
7
+ ToolRegistry,
8
+ callLLM,
9
+ createAgentRuntime,
10
+ createNoopHooks,
11
+ createRuntimeHooks,
12
+ estimateMessageTokens,
13
+ estimateTokens,
14
+ executeTool,
15
+ runAgentLoop,
16
+ toolsToDefinitions
17
+ } from "./chunk-LOBSAUF5.js";
18
+ import "./chunk-TYW5XTOW.js";
19
+ import "./chunk-JLSQOQ5L.js";
20
+ import {
21
+ PROVIDER_REGISTRY,
22
+ listAllProviders,
23
+ resolveApiKeyForProvider,
24
+ resolveProvider
25
+ } from "./chunk-67KZYSLU.js";
26
+ import "./chunk-KFQGP6VL.js";
27
+ export {
28
+ AgentRuntime,
29
+ EmailChannel,
30
+ FollowUpScheduler,
31
+ PROVIDER_REGISTRY,
32
+ SessionManager,
33
+ SubAgentManager,
34
+ ToolRegistry,
35
+ callLLM,
36
+ createAgentRuntime,
37
+ createNoopHooks,
38
+ createRuntimeHooks,
39
+ estimateMessageTokens,
40
+ estimateTokens,
41
+ executeTool,
42
+ listAllProviders,
43
+ resolveApiKeyForProvider,
44
+ resolveProvider,
45
+ runAgentLoop,
46
+ toolsToDefinitions
47
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-34DU32QS.js";
4
+ import "./chunk-3SMTCIR4.js";
5
+ import "./chunk-JLSQOQ5L.js";
6
+ import "./chunk-RO537U6H.js";
7
+ import "./chunk-DRXMYYKN.js";
8
+ import "./chunk-67KZYSLU.js";
9
+ import "./chunk-KFQGP6VL.js";
10
+ export {
11
+ createServer
12
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-DZMAZ763.js";
10
+ import "./chunk-ZMZCLNTY.js";
11
+ import "./chunk-KFQGP6VL.js";
12
+ export {
13
+ promptCompanyInfo,
14
+ promptDatabase,
15
+ promptDeployment,
16
+ promptDomain,
17
+ promptRegistration,
18
+ provision,
19
+ runSetupWizard
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.31",
3
+ "version": "0.5.32",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2837,6 +2837,355 @@ function GuardrailsSection(props) {
2837
2837
  );
2838
2838
  }
2839
2839
 
2840
+ // ════════════════════════════════════════════════════════════
2841
+ // CONFIGURATION SECTION — Model, Description, Soul, General
2842
+ // ════════════════════════════════════════════════════════════
2843
+
2844
+ function ConfigurationSection(props) {
2845
+ var agentId = props.agentId;
2846
+ var engineAgent = props.engineAgent;
2847
+ var reload = props.reload;
2848
+ var toast = useApp().toast;
2849
+
2850
+ var ea = engineAgent || {};
2851
+ var config = ea.config || {};
2852
+ var identity = config.identity || {};
2853
+ var modelObj = typeof config.model === 'object' ? config.model : {};
2854
+ var modelStr = typeof config.model === 'string' ? config.model : null;
2855
+
2856
+ var _editing = useState(false);
2857
+ var editing = _editing[0]; var setEditing = _editing[1];
2858
+ var _saving = useState(false);
2859
+ var saving = _saving[0]; var setSaving = _saving[1];
2860
+ var _form = useState({});
2861
+ var form = _form[0]; var setForm = _form[1];
2862
+ var _providers = useState([]);
2863
+ var providers = _providers[0]; var setProviders = _providers[1];
2864
+ var _providerModels = useState([]);
2865
+ var providerModels = _providerModels[0]; var setProviderModels = _providerModels[1];
2866
+
2867
+ useEffect(function() {
2868
+ apiCall('/providers').then(function(d) { setProviders(d.providers || []); }).catch(function() {});
2869
+ }, []);
2870
+
2871
+ // Load models when provider changes in edit mode
2872
+ useEffect(function() {
2873
+ if (!editing || !form.provider) return;
2874
+ apiCall('/providers/' + form.provider + '/models').then(function(d) {
2875
+ setProviderModels(d.models || []);
2876
+ }).catch(function() { setProviderModels([]); });
2877
+ }, [editing, form.provider]);
2878
+
2879
+ var startEdit = function() {
2880
+ setForm({
2881
+ provider: modelObj.provider || '',
2882
+ modelId: modelStr || modelObj.modelId || '',
2883
+ thinkingLevel: modelObj.thinkingLevel || 'medium',
2884
+ description: identity.description || config.description || '',
2885
+ soulId: config.soulId || '',
2886
+ });
2887
+ setEditing(true);
2888
+ // Trigger model load
2889
+ if (modelObj.provider) {
2890
+ apiCall('/providers/' + modelObj.provider + '/models').then(function(d) { setProviderModels(d.models || []); }).catch(function() {});
2891
+ }
2892
+ };
2893
+
2894
+ var set = function(k, v) { setForm(function(f) { var n = Object.assign({}, f); n[k] = v; return n; }); };
2895
+
2896
+ var save = function() {
2897
+ setSaving(true);
2898
+ var updates = {
2899
+ model: { provider: form.provider, modelId: form.modelId, thinkingLevel: form.thinkingLevel },
2900
+ description: form.description,
2901
+ soulId: form.soulId || null,
2902
+ identity: Object.assign({}, identity, { description: form.description }),
2903
+ };
2904
+ var isRunning = ea.state === 'running' || ea.state === 'active' || ea.state === 'degraded';
2905
+ var endpoint = isRunning ? '/agents/' + agentId + '/hot-update' : '/agents/' + agentId + '/config';
2906
+ var method = isRunning ? 'POST' : 'PATCH';
2907
+ engineCall(endpoint, { method: method, body: JSON.stringify({ updates: updates, updatedBy: 'dashboard' }) })
2908
+ .then(function() { toast('Configuration saved', 'success'); setEditing(false); setSaving(false); reload(); })
2909
+ .catch(function(err) { toast('Failed to save: ' + err.message, 'error'); setSaving(false); });
2910
+ };
2911
+
2912
+ var configuredProviders = providers.filter(function(p) { return p.configured; });
2913
+
2914
+ var labelStyle = { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 };
2915
+ var inputStyle = { width: '100%', padding: '8px 10px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--bg-secondary)', color: 'var(--text-primary)', fontSize: 13 };
2916
+ var fieldGroupStyle = { marginBottom: 16 };
2917
+ var rowStyle = { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 };
2918
+
2919
+ if (editing) {
2920
+ return h(Fragment, null,
2921
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
2922
+ h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Edit Configuration'),
2923
+ h('div', { style: { display: 'flex', gap: 8 } },
2924
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { setEditing(false); } }, 'Cancel'),
2925
+ h('button', { className: 'btn btn-primary btn-sm', disabled: saving, onClick: save }, saving ? 'Saving...' : 'Save Changes')
2926
+ )
2927
+ ),
2928
+
2929
+ // Model Settings
2930
+ h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
2931
+ h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'LLM Model'),
2932
+ h('div', { style: rowStyle },
2933
+ h('div', { style: fieldGroupStyle },
2934
+ h('label', { style: labelStyle }, 'Provider'),
2935
+ h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.provider, onChange: function(e) {
2936
+ set('provider', e.target.value);
2937
+ // Reset model when provider changes
2938
+ set('modelId', '');
2939
+ } },
2940
+ h('option', { value: '' }, '-- Select provider --'),
2941
+ configuredProviders.length > 0
2942
+ ? configuredProviders.map(function(p) { return h('option', { key: p.id, value: p.id }, p.name + (p.isLocal ? ' (Local)' : '')); })
2943
+ : providers.map(function(p) { return h('option', { key: p.id, value: p.id }, p.name); })
2944
+ )
2945
+ ),
2946
+ h('div', { style: fieldGroupStyle },
2947
+ h('label', { style: labelStyle }, 'Model'),
2948
+ providerModels.length > 0
2949
+ ? h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.modelId, onChange: function(e) { set('modelId', e.target.value); } },
2950
+ h('option', { value: '' }, '-- Select model --'),
2951
+ providerModels.map(function(m) { return h('option', { key: m.id, value: m.id }, m.name || m.id); }),
2952
+ h('option', { value: '_custom' }, 'Custom (enter manually)')
2953
+ )
2954
+ : h('input', { style: inputStyle, value: form.modelId, onChange: function(e) { set('modelId', e.target.value); }, placeholder: 'Enter model ID' })
2955
+ )
2956
+ ),
2957
+ h('div', { style: rowStyle },
2958
+ h('div', { style: fieldGroupStyle },
2959
+ h('label', { style: labelStyle }, 'Thinking Level'),
2960
+ h('select', { style: Object.assign({}, inputStyle, { cursor: 'pointer' }), value: form.thinkingLevel, onChange: function(e) { set('thinkingLevel', e.target.value); } },
2961
+ h('option', { value: 'none' }, 'None'),
2962
+ h('option', { value: 'low' }, 'Low'),
2963
+ h('option', { value: 'medium' }, 'Medium'),
2964
+ h('option', { value: 'high' }, 'High')
2965
+ )
2966
+ ),
2967
+ form.modelId === '_custom' && h('div', { style: fieldGroupStyle },
2968
+ h('label', { style: labelStyle }, 'Custom Model ID'),
2969
+ h('input', { style: inputStyle, value: form.customModelId || '', onChange: function(e) { set('customModelId', e.target.value); }, placeholder: 'my-fine-tuned-model-v2' })
2970
+ )
2971
+ )
2972
+ ),
2973
+
2974
+ // Description
2975
+ h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
2976
+ h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Description'),
2977
+ h('div', { style: fieldGroupStyle },
2978
+ h('label', { style: labelStyle }, 'Agent Description'),
2979
+ h('textarea', { style: Object.assign({}, inputStyle, { minHeight: 80, resize: 'vertical' }), value: form.description, onChange: function(e) { set('description', e.target.value); }, placeholder: 'What does this agent do? What are its responsibilities?' })
2980
+ )
2981
+ ),
2982
+
2983
+ // Soul ID
2984
+ config.soulId && h('div', { className: 'card', style: { padding: 20 } },
2985
+ h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Role Template'),
2986
+ h('div', { style: fieldGroupStyle },
2987
+ h('label', { style: labelStyle }, 'Soul Template ID'),
2988
+ h('input', { style: inputStyle, value: form.soulId || '', onChange: function(e) { set('soulId', e.target.value); } })
2989
+ )
2990
+ )
2991
+ );
2992
+ }
2993
+
2994
+ // View mode
2995
+ var displayProvider = modelObj.provider || 'Not set';
2996
+ var displayModel = modelStr || modelObj.modelId || 'Not set';
2997
+ var displayThinking = modelObj.thinkingLevel || 'medium';
2998
+ var displayDescription = identity.description || config.description || '';
2999
+ var displaySoulId = config.soulId || '';
3000
+
3001
+ var fieldView = function(label, value) {
3002
+ return h('div', { style: fieldGroupStyle },
3003
+ h('div', { style: labelStyle }, label),
3004
+ h('div', { style: { fontSize: 14, color: 'var(--text-primary)' } }, value || '\u2014')
3005
+ );
3006
+ };
3007
+
3008
+ return h(Fragment, null,
3009
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
3010
+ h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Configuration'),
3011
+ h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit Configuration')
3012
+ ),
3013
+
3014
+ // Model Card
3015
+ h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
3016
+ h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'LLM Model'),
3017
+ h('div', { style: rowStyle },
3018
+ fieldView('Provider', h('span', { style: { textTransform: 'capitalize' } }, displayProvider)),
3019
+ fieldView('Model ID', h('span', { style: { fontFamily: 'var(--font-mono, monospace)', fontSize: 13 } }, displayModel))
3020
+ ),
3021
+ h('div', { style: rowStyle },
3022
+ fieldView('Thinking Level', h('span', { className: 'badge badge-' + (displayThinking === 'high' ? 'primary' : displayThinking === 'medium' ? 'info' : displayThinking === 'low' ? 'neutral' : 'neutral'), style: { textTransform: 'capitalize' } }, displayThinking)),
3023
+ h('div')
3024
+ )
3025
+ ),
3026
+
3027
+ // Description Card
3028
+ h('div', { className: 'card', style: { padding: 20, marginBottom: 20 } },
3029
+ h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Description'),
3030
+ h('div', { style: { fontSize: 14, color: displayDescription ? 'var(--text-primary)' : 'var(--text-muted)', lineHeight: 1.6 } }, displayDescription || 'No description set.')
3031
+ ),
3032
+
3033
+ // Soul Template Card
3034
+ displaySoulId && h('div', { className: 'card', style: { padding: 20 } },
3035
+ h('h4', { style: { margin: '0 0 16px', fontSize: 14, fontWeight: 600 } }, 'Role Template'),
3036
+ h('span', { className: 'badge badge-primary' }, displaySoulId.replace(/-/g, ' ').replace(/\b\w/g, function(c) { return c.toUpperCase(); }))
3037
+ )
3038
+ );
3039
+ }
3040
+
3041
+ // ════════════════════════════════════════════════════════════
3042
+ // SKILLS SECTION — View and manage agent skills
3043
+ // ════════════════════════════════════════════════════════════
3044
+
3045
+ function SkillsSection(props) {
3046
+ var agentId = props.agentId;
3047
+ var engineAgent = props.engineAgent;
3048
+ var reload = props.reload;
3049
+ var toast = useApp().toast;
3050
+
3051
+ var ea = engineAgent || {};
3052
+ var config = ea.config || {};
3053
+ var currentSkills = Array.isArray(config.skills) ? config.skills : [];
3054
+
3055
+ var _editing = useState(false);
3056
+ var editing = _editing[0]; var setEditing = _editing[1];
3057
+ var _saving = useState(false);
3058
+ var saving = _saving[0]; var setSaving = _saving[1];
3059
+ var _selectedSkills = useState(currentSkills);
3060
+ var selectedSkills = _selectedSkills[0]; var setSelectedSkills = _selectedSkills[1];
3061
+ var _allSkills = useState({});
3062
+ var allSkills = _allSkills[0]; var setAllSkills = _allSkills[1];
3063
+ var _suites = useState([]);
3064
+ var suites = _suites[0]; var setSuites = _suites[1];
3065
+ var _skillSearch = useState('');
3066
+ var skillSearch = _skillSearch[0]; var setSkillSearch = _skillSearch[1];
3067
+
3068
+ useEffect(function() {
3069
+ engineCall('/skills/by-category').then(function(d) { setAllSkills(d.categories || {}); }).catch(function() {});
3070
+ engineCall('/skills/suites').then(function(d) { setSuites(d.suites || []); }).catch(function() {});
3071
+ }, []);
3072
+
3073
+ // Reset selected skills when entering edit mode
3074
+ var startEdit = function() {
3075
+ setSelectedSkills(Array.isArray(config.skills) ? config.skills.slice() : []);
3076
+ setEditing(true);
3077
+ };
3078
+
3079
+ var toggleSkill = function(id) {
3080
+ setSelectedSkills(function(prev) {
3081
+ return prev.includes(id) ? prev.filter(function(s) { return s !== id; }) : prev.concat([id]);
3082
+ });
3083
+ };
3084
+
3085
+ var toggleSuite = function(suite) {
3086
+ setSelectedSkills(function(prev) {
3087
+ var allIn = suite.skills.every(function(id) { return prev.includes(id); });
3088
+ if (allIn) return prev.filter(function(id) { return !suite.skills.includes(id); });
3089
+ var merged = prev.slice();
3090
+ suite.skills.forEach(function(id) { if (!merged.includes(id)) merged.push(id); });
3091
+ return merged;
3092
+ });
3093
+ };
3094
+
3095
+ var save = function() {
3096
+ setSaving(true);
3097
+ var updates = { skills: selectedSkills };
3098
+ var isRunning = ea.state === 'running' || ea.state === 'active' || ea.state === 'degraded';
3099
+ var endpoint = isRunning ? '/agents/' + agentId + '/hot-update' : '/agents/' + agentId + '/config';
3100
+ var method = isRunning ? 'POST' : 'PATCH';
3101
+ engineCall(endpoint, { method: method, body: JSON.stringify({ updates: updates, updatedBy: 'dashboard' }) })
3102
+ .then(function() { toast('Skills updated', 'success'); setEditing(false); setSaving(false); reload(); })
3103
+ .catch(function(err) { toast('Failed to save: ' + err.message, 'error'); setSaving(false); });
3104
+ };
3105
+
3106
+ if (editing) {
3107
+ return h(Fragment, null,
3108
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
3109
+ h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Edit Skills'),
3110
+ h('div', { style: { display: 'flex', gap: 8 } },
3111
+ h('span', { className: 'badge badge-primary' }, selectedSkills.length + ' selected'),
3112
+ selectedSkills.length > 0 && h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { setSelectedSkills([]); } }, 'Clear all'),
3113
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { setEditing(false); } }, 'Cancel'),
3114
+ h('button', { className: 'btn btn-primary btn-sm', disabled: saving, onClick: save }, saving ? 'Saving...' : 'Save Skills')
3115
+ )
3116
+ ),
3117
+
3118
+ // Suites
3119
+ suites.length > 0 && h('div', { style: { marginBottom: 24 } },
3120
+ h('h4', { style: { fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--text-muted)', marginBottom: 8 } }, 'Suites'),
3121
+ h('div', { className: 'suite-grid' }, suites.map(function(s) {
3122
+ var allIn = s.skills.every(function(id) { return selectedSkills.includes(id); });
3123
+ var someIn = s.skills.some(function(id) { return selectedSkills.includes(id); });
3124
+ return h('div', { key: s.id, className: 'suite-card' + (allIn ? ' selected' : someIn ? ' partial' : ''), onClick: function() { toggleSuite(s); }, style: { cursor: 'pointer' } },
3125
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 } },
3126
+ h('span', { style: { fontSize: 20 } }, s.icon),
3127
+ allIn && h('span', { style: { color: 'var(--accent)' } }, I.check())
3128
+ ),
3129
+ h('div', { className: 'suite-name' }, s.name),
3130
+ h('div', { className: 'suite-desc' }, s.skills.length + ' apps')
3131
+ );
3132
+ }))
3133
+ ),
3134
+
3135
+ // Search
3136
+ h('div', { style: { marginBottom: 14 } },
3137
+ h('input', { className: 'input', type: 'text', placeholder: 'Search skills...', value: skillSearch, onChange: function(e) { setSkillSearch(e.target.value); }, style: { maxWidth: 300 } })
3138
+ ),
3139
+
3140
+ // Skills by category
3141
+ Object.entries(allSkills).map(function(entry) {
3142
+ var cat = entry[0]; var skills = entry[1];
3143
+ var filtered = skillSearch ? skills.filter(function(s) { return s.name.toLowerCase().includes(skillSearch.toLowerCase()) || s.description.toLowerCase().includes(skillSearch.toLowerCase()); }) : skills;
3144
+ if (filtered.length === 0) return null;
3145
+ return h('div', { key: cat, style: { marginBottom: 20 } },
3146
+ h('h4', { style: { fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--text-muted)', marginBottom: 8 } }, cat.replace(/-/g, ' ')),
3147
+ h('div', { className: 'skill-grid' }, filtered.map(function(s) {
3148
+ var isSelected = selectedSkills.includes(s.id);
3149
+ return h('div', { key: s.id, className: 'skill-card' + (isSelected ? ' selected' : ''), onClick: function() { toggleSkill(s.id); }, style: { cursor: 'pointer' } },
3150
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
3151
+ h('span', { className: 'skill-name' }, (s.icon || '') + ' ' + s.name),
3152
+ isSelected && h('span', { style: { color: 'var(--accent)' } }, I.check())
3153
+ ),
3154
+ h('div', { className: 'skill-desc' }, s.description)
3155
+ );
3156
+ }))
3157
+ );
3158
+ })
3159
+ );
3160
+ }
3161
+
3162
+ // View mode
3163
+ return h(Fragment, null,
3164
+ h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
3165
+ h('h3', { style: { margin: 0, fontSize: 16, fontWeight: 600 } }, 'Skills & Capabilities'),
3166
+ h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
3167
+ h('span', { className: 'badge badge-primary' }, currentSkills.length + ' skills'),
3168
+ h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, I.journal(), ' Edit Skills')
3169
+ )
3170
+ ),
3171
+
3172
+ currentSkills.length > 0
3173
+ ? h('div', { className: 'card', style: { padding: 20 } },
3174
+ h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 8 } },
3175
+ currentSkills.map(function(skillId) {
3176
+ return h('div', { key: skillId, style: { display: 'flex', alignItems: 'center', gap: 6, padding: '8px 14px', borderRadius: 8, background: 'var(--accent-soft)', border: '1px solid var(--accent)', fontSize: 13, fontWeight: 500, color: 'var(--accent-text)' } },
3177
+ h('span', null, skillId.replace(/-/g, ' ').replace(/\b\w/g, function(c) { return c.toUpperCase(); }))
3178
+ );
3179
+ })
3180
+ )
3181
+ )
3182
+ : h('div', { className: 'card', style: { padding: 40, textAlign: 'center' } },
3183
+ h('div', { style: { color: 'var(--text-muted)', marginBottom: 12 } }, 'No skills assigned to this agent.'),
3184
+ h('button', { className: 'btn btn-primary btn-sm', onClick: startEdit }, 'Add Skills')
3185
+ )
3186
+ );
3187
+ }
3188
+
2840
3189
  // ════════════════════════════════════════════════════════════
2841
3190
  // DEPLOYMENT SECTION
2842
3191
  // ════════════════════════════════════════════════════════════
@@ -2882,6 +3231,57 @@ function DeploymentSection(props) {
2882
3231
  var deploymentTarget = deployment.target || config.deploymentTarget || '-';
2883
3232
  var modelDisplay = typeof config.model === 'string' ? config.model : (config.model ? (config.model.modelId || config.model.provider || '-') : '-');
2884
3233
 
3234
+ // ─── Deployment Edit State ──────────────────────────────
3235
+ var _editingDeploy = useState(false);
3236
+ var editingDeploy = _editingDeploy[0]; var setEditingDeploy = _editingDeploy[1];
3237
+ var _savingDeploy = useState(false);
3238
+ var savingDeploy = _savingDeploy[0]; var setSavingDeploy = _savingDeploy[1];
3239
+ var _deployForm = useState({});
3240
+ var deployForm = _deployForm[0]; var setDeployForm = _deployForm[1];
3241
+
3242
+ var startDeployEdit = function() {
3243
+ setDeployForm({
3244
+ target: deployment.target || 'docker',
3245
+ region: deployment.region || 'iad',
3246
+ imageTag: (deployment.config?.docker?.tag) || deployment.imageTag || 'latest',
3247
+ memory: (deployment.config?.docker?.memory) || deployment.memory || '512m',
3248
+ cpu: (deployment.config?.docker?.cpu) || deployment.cpu || '0.5',
3249
+ ports: (deployment.config?.docker?.ports || [3000]).join(', '),
3250
+ });
3251
+ setEditingDeploy(true);
3252
+ };
3253
+
3254
+ var saveDeploy = function() {
3255
+ setSavingDeploy(true);
3256
+ var updates = {
3257
+ deployment: {
3258
+ target: deployForm.target,
3259
+ region: deployForm.region,
3260
+ imageTag: deployForm.imageTag,
3261
+ memory: deployForm.memory,
3262
+ cpu: deployForm.cpu,
3263
+ config: {
3264
+ docker: {
3265
+ image: 'agenticmail/agent',
3266
+ tag: deployForm.imageTag,
3267
+ ports: deployForm.ports.split(',').map(function(p) { return parseInt(p.trim()) || 3000; }),
3268
+ memory: deployForm.memory,
3269
+ cpu: deployForm.cpu,
3270
+ restart: 'unless-stopped',
3271
+ }
3272
+ }
3273
+ }
3274
+ };
3275
+ var isRunning = ea.state === 'running' || ea.state === 'active' || ea.state === 'degraded';
3276
+ var endpoint = isRunning ? '/agents/' + agentId + '/hot-update' : '/agents/' + agentId + '/config';
3277
+ var method = isRunning ? 'POST' : 'PATCH';
3278
+ engineCall(endpoint, { method: method, body: JSON.stringify({ updates: updates, updatedBy: 'dashboard' }) })
3279
+ .then(function() { toast('Deployment config saved', 'success'); setEditingDeploy(false); setSavingDeploy(false); reload(); })
3280
+ .catch(function(err) { toast('Failed to save: ' + err.message, 'error'); setSavingDeploy(false); });
3281
+ };
3282
+
3283
+ var setDf = function(k, v) { setDeployForm(function(f) { var n = Object.assign({}, f); n[k] = v; return n; }); };
3284
+
2885
3285
  // ─── Actions ────────────────────────────────────────────
2886
3286
 
2887
3287
  var deploy = function() {
@@ -2923,9 +3323,66 @@ function DeploymentSection(props) {
2923
3323
 
2924
3324
  return h(Fragment, null,
2925
3325
 
3326
+ // ─── Deployment Edit Card ─────────────────────────────
3327
+ editingDeploy && h('div', { className: 'card', style: { marginBottom: 20, border: '2px solid var(--accent)' } },
3328
+ h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
3329
+ h('span', null, 'Edit Deployment Configuration'),
3330
+ h('div', { style: { display: 'flex', gap: 8 } },
3331
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: function() { setEditingDeploy(false); } }, 'Cancel'),
3332
+ h('button', { className: 'btn btn-primary btn-sm', disabled: savingDeploy, onClick: saveDeploy }, savingDeploy ? 'Saving...' : 'Save')
3333
+ )
3334
+ ),
3335
+ h('div', { className: 'card-body' },
3336
+ h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 16 } },
3337
+ h('div', { className: 'form-group' },
3338
+ h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Target'),
3339
+ h('select', { className: 'input', value: deployForm.target, onChange: function(e) { setDf('target', e.target.value); } },
3340
+ h('option', { value: 'fly' }, 'Fly.io'),
3341
+ h('option', { value: 'docker' }, 'Docker'),
3342
+ h('option', { value: 'railway' }, 'Railway'),
3343
+ h('option', { value: 'vps' }, 'VPS / Server'),
3344
+ h('option', { value: 'local' }, 'Local')
3345
+ )
3346
+ ),
3347
+ (deployForm.target === 'fly' || deployForm.target === 'railway') && h('div', { className: 'form-group' },
3348
+ h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
3349
+ h('select', { className: 'input', value: deployForm.region, onChange: function(e) { setDf('region', e.target.value); } },
3350
+ h('option', { value: 'iad' }, 'Ashburn (iad)'),
3351
+ h('option', { value: 'ord' }, 'Chicago (ord)'),
3352
+ h('option', { value: 'lax' }, 'Los Angeles (lax)'),
3353
+ h('option', { value: 'lhr' }, 'London (lhr)'),
3354
+ h('option', { value: 'ams' }, 'Amsterdam (ams)'),
3355
+ h('option', { value: 'nrt' }, 'Tokyo (nrt)')
3356
+ )
3357
+ )
3358
+ ),
3359
+ (deployForm.target === 'docker' || deployForm.target === 'fly') && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 16 } },
3360
+ h('div', { className: 'form-group' },
3361
+ h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Image Tag'),
3362
+ h('input', { className: 'input', value: deployForm.imageTag, onChange: function(e) { setDf('imageTag', e.target.value); } })
3363
+ ),
3364
+ h('div', { className: 'form-group' },
3365
+ h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Memory'),
3366
+ h('input', { className: 'input', value: deployForm.memory, onChange: function(e) { setDf('memory', e.target.value); }, placeholder: '512m' })
3367
+ ),
3368
+ h('div', { className: 'form-group' },
3369
+ h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'CPU'),
3370
+ h('input', { className: 'input', value: deployForm.cpu, onChange: function(e) { setDf('cpu', e.target.value); }, placeholder: '0.5' })
3371
+ ),
3372
+ h('div', { className: 'form-group' },
3373
+ h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Ports'),
3374
+ h('input', { className: 'input', value: deployForm.ports, onChange: function(e) { setDf('ports', e.target.value); }, placeholder: '3000' })
3375
+ )
3376
+ )
3377
+ )
3378
+ ),
3379
+
2926
3380
  // ─── Deployment Status Card ─────────────────────────
2927
3381
  h('div', { className: 'card', style: { marginBottom: 20 } },
2928
- h('div', { className: 'card-header' }, h('span', null, 'Deployment Status')),
3382
+ h('div', { className: 'card-header', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
3383
+ h('span', null, 'Deployment Status'),
3384
+ !editingDeploy && h('button', { className: 'btn btn-ghost btn-sm', onClick: startDeployEdit }, I.journal(), ' Edit')
3385
+ ),
2929
3386
  h('div', { className: 'card-body' },
2930
3387
  h('div', { style: { display: 'flex', alignItems: 'center', gap: 16, marginBottom: 16, flexWrap: 'wrap' } },
2931
3388
  h('span', { className: 'status-dot ' + state }),
@@ -3440,7 +3897,7 @@ function AgentDetailPage(props) {
3440
3897
  var _agents = useState([]);
3441
3898
  var agents = _agents[0]; var setAgents = _agents[1];
3442
3899
 
3443
- var TABS = ['overview', 'personal', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
3900
+ var TABS = ['overview', 'personal', 'configuration', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
3444
3901
  var TAB_LABELS = { 'tool-security': 'Tool Security' };
3445
3902
 
3446
3903
  var load = function() {
@@ -3562,6 +4019,8 @@ function AgentDetailPage(props) {
3562
4019
  // ─── Tab Content ────────────────────────────────────
3563
4020
  tab === 'overview' && h(OverviewSection, { agentId: agentId, agent: agent, engineAgent: engineAgent, profile: profile, reload: load, agents: agents, onBack: onBack }),
3564
4021
  tab === 'personal' && h(PersonalDetailsSection, { agentId: agentId, agent: agent, engineAgent: engineAgent, reload: load }),
4022
+ tab === 'configuration' && h(ConfigurationSection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
4023
+ tab === 'skills' && h(SkillsSection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
3565
4024
  tab === 'permissions' && h(PermissionsSection, { agentId: agentId, profile: profile, reload: load }),
3566
4025
  tab === 'activity' && h(ActivitySection, { agentId: agentId }),
3567
4026
  tab === 'communication' && h(CommunicationSection, { agentId: agentId, agents: agents }),
@@ -447,8 +447,13 @@ export function CreateAgentWizard({ onClose, onCreated, toast }) {
447
447
  displayName: form.name,
448
448
  email: form.email || form.name.toLowerCase().replace(/\s+/g, '.') + '@agenticmail.local',
449
449
  role: form.role,
450
+ description: form.description || '',
451
+ soulId: form.soulId || null,
450
452
  model: { provider: form.provider || 'anthropic', modelId: form.model === 'custom' ? (form.customModelId || form.model) : form.model },
451
453
  deployment: { target: form.deployTarget },
454
+ deployTarget: form.deployTarget,
455
+ skills: form.skills || [],
456
+ knowledgeBases: form.knowledgeBases || [],
452
457
  presetName: form.preset || undefined,
453
458
  permissions: {
454
459
  maxRiskLevel: form.maxRiskLevel,
@@ -470,6 +475,8 @@ export function CreateAgentWizard({ onClose, onCreated, toast }) {
470
475
  maritalStatus: form.maritalStatus || undefined,
471
476
  culturalBackground: form.culturalBackground || undefined,
472
477
  language: form.language,
478
+ personality: form.personality || undefined,
479
+ description: form.description || undefined,
473
480
  traits: form.traits,
474
481
  },
475
482
  }) });