@agenticmail/enterprise 0.5.163 → 0.5.165

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.
@@ -1998,13 +1998,37 @@ function MemorySection(props) {
1998
1998
  var filterCategory = _filterCat[0]; var setFilterCategory = _filterCat[1];
1999
1999
  var _filterImp = useState('');
2000
2000
  var filterImportance = _filterImp[0]; var setFilterImportance = _filterImp[1];
2001
+ var _dateFrom = useState('');
2002
+ var dateFrom = _dateFrom[0]; var setDateFrom = _dateFrom[1];
2003
+ var _dateTo = useState('');
2004
+ var dateTo = _dateTo[0]; var setDateTo = _dateTo[1];
2005
+ var _page = useState(1);
2006
+ var page = _page[0]; var setPage = _page[1];
2007
+ var _expanded = useState(null);
2008
+ var expandedId = _expanded[0]; var setExpandedId = _expanded[1];
2001
2009
  var _showCreate = useState(false);
2002
2010
  var showCreateModal = _showCreate[0]; var setShowCreateModal = _showCreate[1];
2003
2011
  var _form = useState({ title: '', content: '', category: 'org_knowledge', importance: 'normal', tags: '' });
2004
2012
  var createForm = _form[0]; var setCreateForm = _form[1];
2005
2013
 
2014
+ var PAGE_SIZE = 10;
2015
+
2016
+ var MEMORY_CATEGORIES = [
2017
+ { value: 'org_knowledge', label: 'Org Knowledge' },
2018
+ { value: 'preference', label: 'Preference' },
2019
+ { value: 'interaction_pattern', label: 'Interaction Pattern' },
2020
+ { value: 'context', label: 'Context' },
2021
+ { value: 'skill', label: 'Skill' },
2022
+ { value: 'processed_email', label: 'Processed Email' },
2023
+ { value: 'procedure', label: 'Procedure' },
2024
+ { value: 'relationship', label: 'Relationship' },
2025
+ { value: 'reflection', label: 'Reflection' },
2026
+ { value: 'domain_expertise', label: 'Domain Expertise' },
2027
+ { value: 'error_pattern', label: 'Error Pattern' }
2028
+ ];
2029
+
2006
2030
  var buildQueryParams = function() {
2007
- var params = '?limit=50';
2031
+ var params = '?limit=200';
2008
2032
  if (searchQuery) params += '&search=' + encodeURIComponent(searchQuery);
2009
2033
  if (filterCategory) params += '&category=' + filterCategory;
2010
2034
  if (filterImportance) params += '&importance=' + filterImportance;
@@ -2012,50 +2036,35 @@ function MemorySection(props) {
2012
2036
  };
2013
2037
 
2014
2038
  var loadMemories = function() {
2015
- var params = buildQueryParams();
2016
- engineCall('/memory/agent/' + agentId + params)
2017
- .then(function(d) { setMemories(d.memories || []); })
2039
+ engineCall('/memory/agent/' + agentId + buildQueryParams())
2040
+ .then(function(d) { setMemories(d.memories || []); setPage(1); })
2018
2041
  .catch(function() {});
2019
2042
  };
2020
2043
 
2021
2044
  var loadStats = function() {
2022
2045
  engineCall('/memory/agent/' + agentId + '/stats')
2023
- .then(function(d) { setMemoryStats(d); })
2046
+ .then(function(d) { setMemoryStats(d.stats || d); })
2024
2047
  .catch(function() {});
2025
2048
  };
2026
2049
 
2027
- var loadAll = function() {
2028
- loadMemories();
2029
- loadStats();
2030
- };
2050
+ var loadAll = function() { loadMemories(); loadStats(); };
2031
2051
 
2032
- useEffect(loadAll, []);
2052
+ useEffect(function() { loadAll(); }, [agentId]);
2033
2053
  useEffect(function() { loadMemories(); }, [filterCategory, filterImportance]);
2034
2054
 
2035
- var handleSearch = function() {
2036
- loadMemories();
2037
- };
2055
+ var handleSearch = function() { loadMemories(); };
2038
2056
 
2039
2057
  var createMemory = function() {
2040
- if (!createForm.title || !createForm.content) { toast('Title and content are required', 'error'); return; }
2041
- var tagsArray = createForm.tags ? createForm.tags.split(',').map(function(s) { return s.trim(); }).filter(Boolean) : [];
2042
2058
  var body = {
2043
2059
  agentId: agentId,
2044
- orgId: getOrgId(),
2045
2060
  title: createForm.title,
2046
2061
  content: createForm.content,
2047
2062
  category: createForm.category,
2048
2063
  importance: createForm.importance,
2049
- source: 'admin',
2050
- tags: tagsArray
2064
+ tags: createForm.tags ? createForm.tags.split(',').map(function(t) { return t.trim(); }).filter(Boolean) : []
2051
2065
  };
2052
2066
  engineCall('/memory', { method: 'POST', body: JSON.stringify(body) })
2053
- .then(function() {
2054
- toast('Memory created', 'success');
2055
- setShowCreateModal(false);
2056
- setCreateForm({ title: '', content: '', category: 'org_knowledge', importance: 'normal', tags: '' });
2057
- loadAll();
2058
- })
2067
+ .then(function() { toast('Memory created', 'success'); setShowCreateModal(false); setCreateForm({ title: '', content: '', category: 'org_knowledge', importance: 'normal', tags: '' }); loadAll(); })
2059
2068
  .catch(function(e) { toast(e.message, 'error'); });
2060
2069
  };
2061
2070
 
@@ -2063,7 +2072,7 @@ function MemorySection(props) {
2063
2072
  showConfirm({
2064
2073
  title: 'Delete Memory',
2065
2074
  message: 'Are you sure you want to delete this memory entry? This action cannot be undone.',
2066
- danger: true,
2075
+ warning: true,
2067
2076
  confirmText: 'Delete'
2068
2077
  }).then(function(confirmed) {
2069
2078
  if (!confirmed) return;
@@ -2076,13 +2085,13 @@ function MemorySection(props) {
2076
2085
  var pruneStale = function() {
2077
2086
  showConfirm({
2078
2087
  title: 'Prune Stale Memories',
2079
- message: 'This will remove expired and stale memory entries for this agent. This action cannot be undone.',
2088
+ message: 'This will remove expired and stale memory entries for this agent.',
2080
2089
  warning: true,
2081
2090
  confirmText: 'Prune'
2082
2091
  }).then(function(confirmed) {
2083
2092
  if (!confirmed) return;
2084
2093
  engineCall('/memory/agent/' + agentId + '/prune', { method: 'POST' })
2085
- .then(function(d) { toast('Pruned ' + (d.pruned || 0) + ' entries', 'success'); loadAll(); })
2094
+ .then(function(d) { toast('Pruned ' + (d.deleted || 0) + ' entries', 'success'); loadAll(); })
2086
2095
  .catch(function(e) { toast(e.message, 'error'); });
2087
2096
  });
2088
2097
  };
@@ -2090,7 +2099,7 @@ function MemorySection(props) {
2090
2099
  var runDecay = function() {
2091
2100
  showConfirm({
2092
2101
  title: 'Run Confidence Decay',
2093
- message: 'This will reduce the confidence score of memories that have not been accessed recently. Decay rate: 10%.',
2102
+ message: 'This will reduce confidence of memories not accessed recently. Decay rate: 10%.',
2094
2103
  warning: true,
2095
2104
  confirmText: 'Run Decay'
2096
2105
  }).then(function(confirmed) {
@@ -2101,116 +2110,161 @@ function MemorySection(props) {
2101
2110
  });
2102
2111
  };
2103
2112
 
2104
- // Derive stats values
2113
+ // Date filter client-side
2114
+ var filtered = memories;
2115
+ if (dateFrom) {
2116
+ var fromTs = new Date(dateFrom).getTime();
2117
+ filtered = filtered.filter(function(m) { return m.createdAt && new Date(m.createdAt).getTime() >= fromTs; });
2118
+ }
2119
+ if (dateTo) {
2120
+ var toTs = new Date(dateTo + 'T23:59:59').getTime();
2121
+ filtered = filtered.filter(function(m) { return m.createdAt && new Date(m.createdAt).getTime() <= toTs; });
2122
+ }
2123
+
2124
+ var totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
2125
+ var paged = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2126
+
2127
+ // Stats
2105
2128
  var totalMemories = memoryStats ? (memoryStats.totalEntries || memoryStats.total || 0) : 0;
2106
2129
  var categoriesUsed = memoryStats && memoryStats.byCategory ? Object.keys(memoryStats.byCategory).length : 0;
2107
2130
  var avgConfidence = memoryStats && memoryStats.avgConfidence != null ? ((memoryStats.avgConfidence * 100).toFixed(0) + '%') : '-';
2108
2131
  var sourcesCount = memoryStats && memoryStats.bySource ? Object.keys(memoryStats.bySource).length : 0;
2109
2132
 
2133
+ var catColor = function(c) {
2134
+ var m = { preference: '#8b5cf6', interaction_pattern: '#ec4899', context: '#3b82f6', skill: '#10b981', processed_email: '#6366f1', org_knowledge: '#f59e0b', procedure: '#14b8a6', relationship: '#f43f5e', reflection: '#a855f7', domain_expertise: '#0ea5e9', error_pattern: '#ef4444' };
2135
+ return m[c] || '#64748b';
2136
+ };
2137
+ var impColor = function(i) {
2138
+ var m = { critical: '#ef4444', high: '#f43f5e', normal: '#3b82f6', low: '#64748b' };
2139
+ return m[i] || '#64748b';
2140
+ };
2141
+
2142
+ var fmtDate = function(d) { if (!d) return '-'; var dt = new Date(d); return dt.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }); };
2143
+ var fmtTime = function(d) { if (!d) return ''; var dt = new Date(d); return dt.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' }); };
2144
+
2110
2145
  return h('div', { className: 'card' },
2111
2146
  h('div', { className: 'card-header', style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' } },
2112
2147
  h('h3', { style: { margin: 0, fontSize: 15, fontWeight: 600 } }, 'Memory'),
2113
- h('button', { className: 'btn btn-ghost btn-sm', onClick: loadAll }, I.refresh(), ' Refresh')
2148
+ h('div', { style: { display: 'flex', gap: 6 } },
2149
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: pruneStale, title: 'Prune stale entries' }, I.trash()),
2150
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: runDecay, title: 'Run confidence decay' }, I.clock()),
2151
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: loadAll }, I.refresh()),
2152
+ h('button', { className: 'btn btn-primary btn-sm', onClick: function() { setShowCreateModal(true); } }, I.plus(), ' Add')
2153
+ )
2114
2154
  ),
2115
- h('div', { className: 'card-body' },
2116
-
2117
- // Stats Row
2118
- h('div', { className: 'stat-grid', style: { marginBottom: 16 } },
2119
- h('div', { className: 'stat-card' },
2120
- h('div', { className: 'stat-value' }, totalMemories),
2121
- h('div', { className: 'stat-label' }, 'Total Memories')
2122
- ),
2123
- h('div', { className: 'stat-card' },
2124
- h('div', { className: 'stat-value' }, categoriesUsed),
2125
- h('div', { className: 'stat-label' }, 'Categories Used')
2126
- ),
2127
- h('div', { className: 'stat-card' },
2128
- h('div', { className: 'stat-value' }, avgConfidence),
2129
- h('div', { className: 'stat-label' }, 'Avg Confidence')
2130
- ),
2131
- h('div', { className: 'stat-card' },
2132
- h('div', { className: 'stat-value' }, sourcesCount),
2133
- h('div', { className: 'stat-label' }, 'Sources')
2134
- )
2155
+ h('div', { className: 'card-body', style: { padding: 0 } },
2156
+
2157
+ // Compact stats bar
2158
+ h('div', { style: { display: 'flex', gap: 24, padding: '10px 16px', borderBottom: '1px solid var(--border)', fontSize: 13 } },
2159
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Total: ', h('strong', null, totalMemories)),
2160
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Categories: ', h('strong', null, categoriesUsed)),
2161
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Avg Conf: ', h('strong', null, avgConfidence)),
2162
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Sources: ', h('strong', null, sourcesCount)),
2163
+ h('div', { style: { flex: 1 } }),
2164
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Showing ', h('strong', null, filtered.length), ' of ', totalMemories)
2135
2165
  ),
2136
2166
 
2137
- // Filter Bar
2138
- h('div', { style: { display: 'flex', gap: 8, marginBottom: 16, flexWrap: 'wrap', alignItems: 'center' } },
2139
- h('div', { style: { position: 'relative', flex: 1, minWidth: 180 } },
2140
- h('input', {
2141
- className: 'input',
2142
- placeholder: 'Search memories...',
2143
- value: searchQuery,
2144
- onChange: function(e) { setSearchQuery(e.target.value); },
2145
- onKeyDown: function(e) { if (e.key === 'Enter') handleSearch(); }
2146
- })
2147
- ),
2148
- h('button', { className: 'btn btn-ghost btn-sm', onClick: handleSearch }, I.search()),
2149
- h('select', { className: 'input', style: { maxWidth: 170 }, value: filterCategory, onChange: function(e) { setFilterCategory(e.target.value); } },
2167
+ // Filter row
2168
+ h('div', { style: { display: 'flex', gap: 6, padding: '8px 16px', borderBottom: '1px solid var(--border)', flexWrap: 'wrap', alignItems: 'center' } },
2169
+ h('input', {
2170
+ className: 'input', style: { flex: 1, minWidth: 140, height: 30, fontSize: 12 },
2171
+ placeholder: 'Search...', value: searchQuery,
2172
+ onChange: function(e) { setSearchQuery(e.target.value); },
2173
+ onKeyDown: function(e) { if (e.key === 'Enter') handleSearch(); }
2174
+ }),
2175
+ h('select', { className: 'input', style: { width: 130, height: 30, fontSize: 12 }, value: filterCategory, onChange: function(e) { setFilterCategory(e.target.value); } },
2150
2176
  h('option', { value: '' }, 'All Categories'),
2151
2177
  MEMORY_CATEGORIES.map(function(c) { return h('option', { key: c.value, value: c.value }, c.label); })
2152
2178
  ),
2153
- h('select', { className: 'input', style: { maxWidth: 150 }, value: filterImportance, onChange: function(e) { setFilterImportance(e.target.value); } },
2154
- h('option', { value: '' }, 'All Importance'),
2179
+ h('select', { className: 'input', style: { width: 110, height: 30, fontSize: 12 }, value: filterImportance, onChange: function(e) { setFilterImportance(e.target.value); } },
2180
+ h('option', { value: '' }, 'All Levels'),
2155
2181
  h('option', { value: 'critical' }, 'Critical'),
2156
2182
  h('option', { value: 'high' }, 'High'),
2157
2183
  h('option', { value: 'normal' }, 'Normal'),
2158
2184
  h('option', { value: 'low' }, 'Low')
2159
2185
  ),
2160
- h('div', { style: { flex: '0 0 auto' } }),
2161
- h('button', { className: 'btn btn-primary btn-sm', onClick: function() { setShowCreateModal(true); } }, I.plus(), ' Create Memory'),
2162
- h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--warning)' }, onClick: pruneStale }, I.trash(), ' Prune Stale'),
2163
- h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--warning)' }, onClick: runDecay }, I.clock(), ' Run Decay')
2186
+ h('input', { type: 'date', className: 'input', style: { width: 120, height: 30, fontSize: 12 }, value: dateFrom, onChange: function(e) { setDateFrom(e.target.value); setPage(1); }, title: 'From date' }),
2187
+ h('span', { style: { fontSize: 11, color: 'var(--text-muted)' } }, ''),
2188
+ h('input', { type: 'date', className: 'input', style: { width: 120, height: 30, fontSize: 12 }, value: dateTo, onChange: function(e) { setDateTo(e.target.value); setPage(1); }, title: 'To date' }),
2189
+ (dateFrom || dateTo) && h('button', { className: 'btn btn-ghost btn-sm', style: { height: 30, fontSize: 11 }, onClick: function() { setDateFrom(''); setDateTo(''); } }, 'Clear')
2164
2190
  ),
2165
2191
 
2166
- // Memory Cards List
2167
- memories.length === 0
2168
- ? h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } }, 'No memories found for this agent')
2169
- : h('div', { style: { display: 'grid', gap: 10 } },
2170
- memories.map(function(m) {
2171
- var truncatedContent = m.content && m.content.length > 200 ? m.content.substring(0, 200) + '...' : (m.content || '');
2172
- var tags = m.tags || [];
2173
- var confidence = m.confidence != null ? ((m.confidence * 100).toFixed(0) + '%') : '-';
2174
- var created = m.createdAt ? new Date(m.createdAt).toLocaleDateString() : '-';
2175
- var lastAccessed = m.lastAccessedAt ? new Date(m.lastAccessedAt).toLocaleDateString() : '-';
2176
-
2177
- return h('div', { key: m.id, style: { padding: '14px 18px', background: 'var(--bg-tertiary)', borderRadius: 8, border: '1px solid var(--border)' } },
2178
- // Title
2179
- h('div', { style: { fontWeight: 600, fontSize: 14, marginBottom: 6 } }, m.title || 'Untitled'),
2180
-
2181
- // Category + Importance + Source badges row
2182
- h('div', { style: { display: 'flex', gap: 6, marginBottom: 8, flexWrap: 'wrap' } },
2183
- h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600, color: '#fff', background: memCatColor(m.category) } }, memCatLabel(m.category)),
2184
- h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600, color: '#fff', background: importanceBadgeColor(m.importance) } }, m.importance || 'normal'),
2185
- m.source && h('span', { className: 'badge badge-neutral' }, m.source)
2192
+ // Table-style compact list
2193
+ filtered.length === 0
2194
+ ? h('div', { style: { padding: 32, textAlign: 'center', color: 'var(--text-muted)', fontSize: 13 } }, 'No memories found')
2195
+ : h(Fragment, null,
2196
+ // Header row
2197
+ h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 100px 70px 60px 70px 36px', gap: 8, padding: '6px 16px', borderBottom: '1px solid var(--border)', fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.5px' } },
2198
+ h('span', null, 'Memory'),
2199
+ h('span', null, 'Category'),
2200
+ h('span', null, 'Level'),
2201
+ h('span', null, 'Conf'),
2202
+ h('span', null, 'Date'),
2203
+ h('span', null, '')
2204
+ ),
2205
+ // Rows
2206
+ paged.map(function(m) {
2207
+ var isExpanded = expandedId === m.id;
2208
+ var conf = m.confidence != null ? Math.round(m.confidence * 100) : 0;
2209
+ var confBar = conf >= 80 ? 'var(--success)' : conf >= 50 ? 'var(--warning)' : 'var(--danger)';
2210
+ return h('div', { key: m.id },
2211
+ // Compact row
2212
+ h('div', {
2213
+ style: { display: 'grid', gridTemplateColumns: '1fr 100px 70px 60px 70px 36px', gap: 8, padding: '8px 16px', borderBottom: '1px solid var(--border)', cursor: 'pointer', fontSize: 13, alignItems: 'center', transition: 'background 0.1s', background: isExpanded ? 'var(--bg-tertiary)' : 'transparent' },
2214
+ onClick: function() { setExpandedId(isExpanded ? null : m.id); },
2215
+ onMouseEnter: function(e) { if (!isExpanded) e.currentTarget.style.background = 'var(--bg-secondary)'; },
2216
+ onMouseLeave: function(e) { if (!isExpanded) e.currentTarget.style.background = 'transparent'; }
2217
+ },
2218
+ // Title + preview
2219
+ h('div', { style: { overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' } },
2220
+ h('span', { style: { fontWeight: 500 } }, m.title || 'Untitled'),
2221
+ m.content && h('span', { style: { color: 'var(--text-muted)', marginLeft: 8, fontSize: 12 } }, m.content.substring(0, 60) + (m.content.length > 60 ? '...' : ''))
2186
2222
  ),
2187
-
2188
- // Content (truncated)
2189
- h('div', { style: { fontSize: 13, color: 'var(--text-muted)', marginBottom: 8, lineHeight: 1.5, overflow: 'hidden', textOverflow: 'ellipsis' } }, truncatedContent),
2190
-
2191
- // Tags row
2192
- tags.length > 0 && h('div', { style: { display: 'flex', gap: 4, marginBottom: 8, flexWrap: 'wrap' } },
2193
- tags.map(function(tag, ti) {
2194
- return h('span', { key: ti, className: 'badge badge-neutral', style: { fontSize: 10 } }, tag);
2195
- })
2223
+ // Category badge
2224
+ h('span', { style: { display: 'inline-block', padding: '1px 6px', borderRadius: 3, fontSize: 10, fontWeight: 600, color: '#fff', background: catColor(m.category), whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, (m.category || '').replace(/_/g, ' ')),
2225
+ // Importance
2226
+ h('span', { style: { fontSize: 11, color: impColor(m.importance), fontWeight: 500 } }, m.importance || 'normal'),
2227
+ // Confidence bar
2228
+ h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
2229
+ h('div', { style: { flex: 1, height: 4, borderRadius: 2, background: 'var(--border)' } },
2230
+ h('div', { style: { width: conf + '%', height: '100%', borderRadius: 2, background: confBar } })
2231
+ ),
2232
+ h('span', { style: { fontSize: 10, color: 'var(--text-muted)', minWidth: 24 } }, conf + '%')
2196
2233
  ),
2197
-
2198
- // Meta row: confidence, created, last accessed, delete button
2199
- h('div', { style: { display: 'flex', alignItems: 'center', gap: 16, fontSize: 11, color: 'var(--text-muted)' } },
2200
- h('span', null, 'Confidence: ', h('strong', null, confidence)),
2201
- h('span', null, 'Created: ', created),
2202
- h('span', null, 'Last accessed: ', lastAccessed),
2234
+ // Date
2235
+ h('span', { style: { fontSize: 11, color: 'var(--text-muted)', whiteSpace: 'nowrap' } }, fmtDate(m.createdAt)),
2236
+ // Expand indicator
2237
+ h('span', { style: { fontSize: 10, color: 'var(--text-muted)', textAlign: 'center' } }, isExpanded ? '▲' : '▼')
2238
+ ),
2239
+ // Expanded detail
2240
+ isExpanded && h('div', { style: { padding: '10px 16px 12px', background: 'var(--bg-tertiary)', borderBottom: '1px solid var(--border)', fontSize: 12, lineHeight: 1.6 } },
2241
+ h('div', { style: { color: 'var(--text)', marginBottom: 8, whiteSpace: 'pre-wrap', maxHeight: 200, overflow: 'auto' } }, m.content || '(empty)'),
2242
+ h('div', { style: { display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center', fontSize: 11, color: 'var(--text-muted)' } },
2243
+ h('span', null, 'Source: ', h('strong', null, m.source || '-')),
2244
+ h('span', null, 'Created: ', h('strong', null, fmtDate(m.createdAt)), ' ', fmtTime(m.createdAt)),
2245
+ m.lastAccessedAt && h('span', null, 'Last accessed: ', h('strong', null, fmtDate(m.lastAccessedAt))),
2246
+ m.tags && m.tags.length > 0 && h('span', null, 'Tags: ', m.tags.join(', ')),
2203
2247
  h('div', { style: { flex: 1 } }),
2204
- h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--danger)' }, onClick: function() { deleteMemory(m.id); } }, I.trash(), ' Delete')
2248
+ h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--danger)', height: 24, fontSize: 11 }, onClick: function(e) { e.stopPropagation(); deleteMemory(m.id); } }, I.trash(), ' Delete')
2205
2249
  )
2206
- );
2207
- })
2250
+ )
2251
+ );
2252
+ }),
2253
+
2254
+ // Pagination
2255
+ totalPages > 1 && h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4, padding: '10px 16px', borderTop: '1px solid var(--border)' } },
2256
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page <= 1, onClick: function() { setPage(1); }, style: { fontSize: 11, height: 28 } }, '«'),
2257
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page <= 1, onClick: function() { setPage(page - 1); }, style: { fontSize: 11, height: 28 } }, '‹'),
2258
+ h('span', { style: { fontSize: 12, color: 'var(--text-muted)', padding: '0 8px' } }, 'Page ', h('strong', null, page), ' of ', h('strong', null, totalPages)),
2259
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page >= totalPages, onClick: function() { setPage(page + 1); }, style: { fontSize: 11, height: 28 } }, '›'),
2260
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page >= totalPages, onClick: function() { setPage(totalPages); }, style: { fontSize: 11, height: 28 } }, '»')
2208
2261
  )
2262
+ )
2209
2263
  ),
2210
2264
 
2211
2265
  // Create Memory Modal
2212
2266
  showCreateModal && h('div', { className: 'modal-overlay', onClick: function() { setShowCreateModal(false); } },
2213
- h('div', { className: 'modal', style: { maxWidth: 540 }, onClick: function(e) { e.stopPropagation(); } },
2267
+ h('div', { className: 'modal', style: { maxWidth: 500 }, onClick: function(e) { e.stopPropagation(); } },
2214
2268
  h('div', { className: 'modal-header' },
2215
2269
  h('h2', null, 'Create Memory'),
2216
2270
  h('button', { className: 'btn btn-ghost btn-icon', onClick: function() { setShowCreateModal(false); } }, I.x())
@@ -2222,7 +2276,7 @@ function MemorySection(props) {
2222
2276
  ),
2223
2277
  h('div', { className: 'form-group' },
2224
2278
  h('label', { className: 'form-label' }, 'Content *'),
2225
- h('textarea', { className: 'input', style: { minHeight: 120 }, placeholder: 'Memory content...', value: createForm.content, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { content: e.target.value })); } })
2279
+ h('textarea', { className: 'input', style: { minHeight: 100 }, placeholder: 'Memory content...', value: createForm.content, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { content: e.target.value })); } })
2226
2280
  ),
2227
2281
  h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 } },
2228
2282
  h('div', { className: 'form-group' },
@@ -2243,12 +2297,12 @@ function MemorySection(props) {
2243
2297
  ),
2244
2298
  h('div', { className: 'form-group' },
2245
2299
  h('label', { className: 'form-label' }, 'Tags (comma-separated)'),
2246
- h('input', { className: 'input', placeholder: 'tag1, tag2, tag3', value: createForm.tags, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { tags: e.target.value })); } })
2300
+ h('input', { className: 'input', placeholder: 'tag1, tag2', value: createForm.tags, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { tags: e.target.value })); } })
2247
2301
  )
2248
2302
  ),
2249
2303
  h('div', { className: 'modal-footer' },
2250
2304
  h('button', { className: 'btn btn-ghost', onClick: function() { setShowCreateModal(false); } }, 'Cancel'),
2251
- h('button', { className: 'btn btn-primary', onClick: createMemory }, 'Create Memory')
2305
+ h('button', { className: 'btn btn-primary', onClick: createMemory }, 'Create')
2252
2306
  )
2253
2307
  )
2254
2308
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.163",
3
+ "version": "0.5.165",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1998,13 +1998,37 @@ function MemorySection(props) {
1998
1998
  var filterCategory = _filterCat[0]; var setFilterCategory = _filterCat[1];
1999
1999
  var _filterImp = useState('');
2000
2000
  var filterImportance = _filterImp[0]; var setFilterImportance = _filterImp[1];
2001
+ var _dateFrom = useState('');
2002
+ var dateFrom = _dateFrom[0]; var setDateFrom = _dateFrom[1];
2003
+ var _dateTo = useState('');
2004
+ var dateTo = _dateTo[0]; var setDateTo = _dateTo[1];
2005
+ var _page = useState(1);
2006
+ var page = _page[0]; var setPage = _page[1];
2007
+ var _expanded = useState(null);
2008
+ var expandedId = _expanded[0]; var setExpandedId = _expanded[1];
2001
2009
  var _showCreate = useState(false);
2002
2010
  var showCreateModal = _showCreate[0]; var setShowCreateModal = _showCreate[1];
2003
2011
  var _form = useState({ title: '', content: '', category: 'org_knowledge', importance: 'normal', tags: '' });
2004
2012
  var createForm = _form[0]; var setCreateForm = _form[1];
2005
2013
 
2014
+ var PAGE_SIZE = 10;
2015
+
2016
+ var MEMORY_CATEGORIES = [
2017
+ { value: 'org_knowledge', label: 'Org Knowledge' },
2018
+ { value: 'preference', label: 'Preference' },
2019
+ { value: 'interaction_pattern', label: 'Interaction Pattern' },
2020
+ { value: 'context', label: 'Context' },
2021
+ { value: 'skill', label: 'Skill' },
2022
+ { value: 'processed_email', label: 'Processed Email' },
2023
+ { value: 'procedure', label: 'Procedure' },
2024
+ { value: 'relationship', label: 'Relationship' },
2025
+ { value: 'reflection', label: 'Reflection' },
2026
+ { value: 'domain_expertise', label: 'Domain Expertise' },
2027
+ { value: 'error_pattern', label: 'Error Pattern' }
2028
+ ];
2029
+
2006
2030
  var buildQueryParams = function() {
2007
- var params = '?limit=50';
2031
+ var params = '?limit=200';
2008
2032
  if (searchQuery) params += '&search=' + encodeURIComponent(searchQuery);
2009
2033
  if (filterCategory) params += '&category=' + filterCategory;
2010
2034
  if (filterImportance) params += '&importance=' + filterImportance;
@@ -2012,50 +2036,35 @@ function MemorySection(props) {
2012
2036
  };
2013
2037
 
2014
2038
  var loadMemories = function() {
2015
- var params = buildQueryParams();
2016
- engineCall('/memory/agent/' + agentId + params)
2017
- .then(function(d) { setMemories(d.memories || []); })
2039
+ engineCall('/memory/agent/' + agentId + buildQueryParams())
2040
+ .then(function(d) { setMemories(d.memories || []); setPage(1); })
2018
2041
  .catch(function() {});
2019
2042
  };
2020
2043
 
2021
2044
  var loadStats = function() {
2022
2045
  engineCall('/memory/agent/' + agentId + '/stats')
2023
- .then(function(d) { setMemoryStats(d); })
2046
+ .then(function(d) { setMemoryStats(d.stats || d); })
2024
2047
  .catch(function() {});
2025
2048
  };
2026
2049
 
2027
- var loadAll = function() {
2028
- loadMemories();
2029
- loadStats();
2030
- };
2050
+ var loadAll = function() { loadMemories(); loadStats(); };
2031
2051
 
2032
- useEffect(loadAll, []);
2052
+ useEffect(function() { loadAll(); }, [agentId]);
2033
2053
  useEffect(function() { loadMemories(); }, [filterCategory, filterImportance]);
2034
2054
 
2035
- var handleSearch = function() {
2036
- loadMemories();
2037
- };
2055
+ var handleSearch = function() { loadMemories(); };
2038
2056
 
2039
2057
  var createMemory = function() {
2040
- if (!createForm.title || !createForm.content) { toast('Title and content are required', 'error'); return; }
2041
- var tagsArray = createForm.tags ? createForm.tags.split(',').map(function(s) { return s.trim(); }).filter(Boolean) : [];
2042
2058
  var body = {
2043
2059
  agentId: agentId,
2044
- orgId: getOrgId(),
2045
2060
  title: createForm.title,
2046
2061
  content: createForm.content,
2047
2062
  category: createForm.category,
2048
2063
  importance: createForm.importance,
2049
- source: 'admin',
2050
- tags: tagsArray
2064
+ tags: createForm.tags ? createForm.tags.split(',').map(function(t) { return t.trim(); }).filter(Boolean) : []
2051
2065
  };
2052
2066
  engineCall('/memory', { method: 'POST', body: JSON.stringify(body) })
2053
- .then(function() {
2054
- toast('Memory created', 'success');
2055
- setShowCreateModal(false);
2056
- setCreateForm({ title: '', content: '', category: 'org_knowledge', importance: 'normal', tags: '' });
2057
- loadAll();
2058
- })
2067
+ .then(function() { toast('Memory created', 'success'); setShowCreateModal(false); setCreateForm({ title: '', content: '', category: 'org_knowledge', importance: 'normal', tags: '' }); loadAll(); })
2059
2068
  .catch(function(e) { toast(e.message, 'error'); });
2060
2069
  };
2061
2070
 
@@ -2063,7 +2072,7 @@ function MemorySection(props) {
2063
2072
  showConfirm({
2064
2073
  title: 'Delete Memory',
2065
2074
  message: 'Are you sure you want to delete this memory entry? This action cannot be undone.',
2066
- danger: true,
2075
+ warning: true,
2067
2076
  confirmText: 'Delete'
2068
2077
  }).then(function(confirmed) {
2069
2078
  if (!confirmed) return;
@@ -2076,13 +2085,13 @@ function MemorySection(props) {
2076
2085
  var pruneStale = function() {
2077
2086
  showConfirm({
2078
2087
  title: 'Prune Stale Memories',
2079
- message: 'This will remove expired and stale memory entries for this agent. This action cannot be undone.',
2088
+ message: 'This will remove expired and stale memory entries for this agent.',
2080
2089
  warning: true,
2081
2090
  confirmText: 'Prune'
2082
2091
  }).then(function(confirmed) {
2083
2092
  if (!confirmed) return;
2084
2093
  engineCall('/memory/agent/' + agentId + '/prune', { method: 'POST' })
2085
- .then(function(d) { toast('Pruned ' + (d.pruned || 0) + ' entries', 'success'); loadAll(); })
2094
+ .then(function(d) { toast('Pruned ' + (d.deleted || 0) + ' entries', 'success'); loadAll(); })
2086
2095
  .catch(function(e) { toast(e.message, 'error'); });
2087
2096
  });
2088
2097
  };
@@ -2090,7 +2099,7 @@ function MemorySection(props) {
2090
2099
  var runDecay = function() {
2091
2100
  showConfirm({
2092
2101
  title: 'Run Confidence Decay',
2093
- message: 'This will reduce the confidence score of memories that have not been accessed recently. Decay rate: 10%.',
2102
+ message: 'This will reduce confidence of memories not accessed recently. Decay rate: 10%.',
2094
2103
  warning: true,
2095
2104
  confirmText: 'Run Decay'
2096
2105
  }).then(function(confirmed) {
@@ -2101,116 +2110,161 @@ function MemorySection(props) {
2101
2110
  });
2102
2111
  };
2103
2112
 
2104
- // Derive stats values
2113
+ // Date filter client-side
2114
+ var filtered = memories;
2115
+ if (dateFrom) {
2116
+ var fromTs = new Date(dateFrom).getTime();
2117
+ filtered = filtered.filter(function(m) { return m.createdAt && new Date(m.createdAt).getTime() >= fromTs; });
2118
+ }
2119
+ if (dateTo) {
2120
+ var toTs = new Date(dateTo + 'T23:59:59').getTime();
2121
+ filtered = filtered.filter(function(m) { return m.createdAt && new Date(m.createdAt).getTime() <= toTs; });
2122
+ }
2123
+
2124
+ var totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
2125
+ var paged = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2126
+
2127
+ // Stats
2105
2128
  var totalMemories = memoryStats ? (memoryStats.totalEntries || memoryStats.total || 0) : 0;
2106
2129
  var categoriesUsed = memoryStats && memoryStats.byCategory ? Object.keys(memoryStats.byCategory).length : 0;
2107
2130
  var avgConfidence = memoryStats && memoryStats.avgConfidence != null ? ((memoryStats.avgConfidence * 100).toFixed(0) + '%') : '-';
2108
2131
  var sourcesCount = memoryStats && memoryStats.bySource ? Object.keys(memoryStats.bySource).length : 0;
2109
2132
 
2133
+ var catColor = function(c) {
2134
+ var m = { preference: '#8b5cf6', interaction_pattern: '#ec4899', context: '#3b82f6', skill: '#10b981', processed_email: '#6366f1', org_knowledge: '#f59e0b', procedure: '#14b8a6', relationship: '#f43f5e', reflection: '#a855f7', domain_expertise: '#0ea5e9', error_pattern: '#ef4444' };
2135
+ return m[c] || '#64748b';
2136
+ };
2137
+ var impColor = function(i) {
2138
+ var m = { critical: '#ef4444', high: '#f43f5e', normal: '#3b82f6', low: '#64748b' };
2139
+ return m[i] || '#64748b';
2140
+ };
2141
+
2142
+ var fmtDate = function(d) { if (!d) return '-'; var dt = new Date(d); return dt.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }); };
2143
+ var fmtTime = function(d) { if (!d) return ''; var dt = new Date(d); return dt.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' }); };
2144
+
2110
2145
  return h('div', { className: 'card' },
2111
2146
  h('div', { className: 'card-header', style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' } },
2112
2147
  h('h3', { style: { margin: 0, fontSize: 15, fontWeight: 600 } }, 'Memory'),
2113
- h('button', { className: 'btn btn-ghost btn-sm', onClick: loadAll }, I.refresh(), ' Refresh')
2148
+ h('div', { style: { display: 'flex', gap: 6 } },
2149
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: pruneStale, title: 'Prune stale entries' }, I.trash()),
2150
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: runDecay, title: 'Run confidence decay' }, I.clock()),
2151
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: loadAll }, I.refresh()),
2152
+ h('button', { className: 'btn btn-primary btn-sm', onClick: function() { setShowCreateModal(true); } }, I.plus(), ' Add')
2153
+ )
2114
2154
  ),
2115
- h('div', { className: 'card-body' },
2116
-
2117
- // Stats Row
2118
- h('div', { className: 'stat-grid', style: { marginBottom: 16 } },
2119
- h('div', { className: 'stat-card' },
2120
- h('div', { className: 'stat-value' }, totalMemories),
2121
- h('div', { className: 'stat-label' }, 'Total Memories')
2122
- ),
2123
- h('div', { className: 'stat-card' },
2124
- h('div', { className: 'stat-value' }, categoriesUsed),
2125
- h('div', { className: 'stat-label' }, 'Categories Used')
2126
- ),
2127
- h('div', { className: 'stat-card' },
2128
- h('div', { className: 'stat-value' }, avgConfidence),
2129
- h('div', { className: 'stat-label' }, 'Avg Confidence')
2130
- ),
2131
- h('div', { className: 'stat-card' },
2132
- h('div', { className: 'stat-value' }, sourcesCount),
2133
- h('div', { className: 'stat-label' }, 'Sources')
2134
- )
2155
+ h('div', { className: 'card-body', style: { padding: 0 } },
2156
+
2157
+ // Compact stats bar
2158
+ h('div', { style: { display: 'flex', gap: 24, padding: '10px 16px', borderBottom: '1px solid var(--border)', fontSize: 13 } },
2159
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Total: ', h('strong', null, totalMemories)),
2160
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Categories: ', h('strong', null, categoriesUsed)),
2161
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Avg Conf: ', h('strong', null, avgConfidence)),
2162
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Sources: ', h('strong', null, sourcesCount)),
2163
+ h('div', { style: { flex: 1 } }),
2164
+ h('span', { style: { color: 'var(--text-muted)' } }, 'Showing ', h('strong', null, filtered.length), ' of ', totalMemories)
2135
2165
  ),
2136
2166
 
2137
- // Filter Bar
2138
- h('div', { style: { display: 'flex', gap: 8, marginBottom: 16, flexWrap: 'wrap', alignItems: 'center' } },
2139
- h('div', { style: { position: 'relative', flex: 1, minWidth: 180 } },
2140
- h('input', {
2141
- className: 'input',
2142
- placeholder: 'Search memories...',
2143
- value: searchQuery,
2144
- onChange: function(e) { setSearchQuery(e.target.value); },
2145
- onKeyDown: function(e) { if (e.key === 'Enter') handleSearch(); }
2146
- })
2147
- ),
2148
- h('button', { className: 'btn btn-ghost btn-sm', onClick: handleSearch }, I.search()),
2149
- h('select', { className: 'input', style: { maxWidth: 170 }, value: filterCategory, onChange: function(e) { setFilterCategory(e.target.value); } },
2167
+ // Filter row
2168
+ h('div', { style: { display: 'flex', gap: 6, padding: '8px 16px', borderBottom: '1px solid var(--border)', flexWrap: 'wrap', alignItems: 'center' } },
2169
+ h('input', {
2170
+ className: 'input', style: { flex: 1, minWidth: 140, height: 30, fontSize: 12 },
2171
+ placeholder: 'Search...', value: searchQuery,
2172
+ onChange: function(e) { setSearchQuery(e.target.value); },
2173
+ onKeyDown: function(e) { if (e.key === 'Enter') handleSearch(); }
2174
+ }),
2175
+ h('select', { className: 'input', style: { width: 130, height: 30, fontSize: 12 }, value: filterCategory, onChange: function(e) { setFilterCategory(e.target.value); } },
2150
2176
  h('option', { value: '' }, 'All Categories'),
2151
2177
  MEMORY_CATEGORIES.map(function(c) { return h('option', { key: c.value, value: c.value }, c.label); })
2152
2178
  ),
2153
- h('select', { className: 'input', style: { maxWidth: 150 }, value: filterImportance, onChange: function(e) { setFilterImportance(e.target.value); } },
2154
- h('option', { value: '' }, 'All Importance'),
2179
+ h('select', { className: 'input', style: { width: 110, height: 30, fontSize: 12 }, value: filterImportance, onChange: function(e) { setFilterImportance(e.target.value); } },
2180
+ h('option', { value: '' }, 'All Levels'),
2155
2181
  h('option', { value: 'critical' }, 'Critical'),
2156
2182
  h('option', { value: 'high' }, 'High'),
2157
2183
  h('option', { value: 'normal' }, 'Normal'),
2158
2184
  h('option', { value: 'low' }, 'Low')
2159
2185
  ),
2160
- h('div', { style: { flex: '0 0 auto' } }),
2161
- h('button', { className: 'btn btn-primary btn-sm', onClick: function() { setShowCreateModal(true); } }, I.plus(), ' Create Memory'),
2162
- h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--warning)' }, onClick: pruneStale }, I.trash(), ' Prune Stale'),
2163
- h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--warning)' }, onClick: runDecay }, I.clock(), ' Run Decay')
2186
+ h('input', { type: 'date', className: 'input', style: { width: 120, height: 30, fontSize: 12 }, value: dateFrom, onChange: function(e) { setDateFrom(e.target.value); setPage(1); }, title: 'From date' }),
2187
+ h('span', { style: { fontSize: 11, color: 'var(--text-muted)' } }, ''),
2188
+ h('input', { type: 'date', className: 'input', style: { width: 120, height: 30, fontSize: 12 }, value: dateTo, onChange: function(e) { setDateTo(e.target.value); setPage(1); }, title: 'To date' }),
2189
+ (dateFrom || dateTo) && h('button', { className: 'btn btn-ghost btn-sm', style: { height: 30, fontSize: 11 }, onClick: function() { setDateFrom(''); setDateTo(''); } }, 'Clear')
2164
2190
  ),
2165
2191
 
2166
- // Memory Cards List
2167
- memories.length === 0
2168
- ? h('div', { style: { padding: 40, textAlign: 'center', color: 'var(--text-muted)' } }, 'No memories found for this agent')
2169
- : h('div', { style: { display: 'grid', gap: 10 } },
2170
- memories.map(function(m) {
2171
- var truncatedContent = m.content && m.content.length > 200 ? m.content.substring(0, 200) + '...' : (m.content || '');
2172
- var tags = m.tags || [];
2173
- var confidence = m.confidence != null ? ((m.confidence * 100).toFixed(0) + '%') : '-';
2174
- var created = m.createdAt ? new Date(m.createdAt).toLocaleDateString() : '-';
2175
- var lastAccessed = m.lastAccessedAt ? new Date(m.lastAccessedAt).toLocaleDateString() : '-';
2176
-
2177
- return h('div', { key: m.id, style: { padding: '14px 18px', background: 'var(--bg-tertiary)', borderRadius: 8, border: '1px solid var(--border)' } },
2178
- // Title
2179
- h('div', { style: { fontWeight: 600, fontSize: 14, marginBottom: 6 } }, m.title || 'Untitled'),
2180
-
2181
- // Category + Importance + Source badges row
2182
- h('div', { style: { display: 'flex', gap: 6, marginBottom: 8, flexWrap: 'wrap' } },
2183
- h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600, color: '#fff', background: memCatColor(m.category) } }, memCatLabel(m.category)),
2184
- h('span', { style: { display: 'inline-block', padding: '2px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600, color: '#fff', background: importanceBadgeColor(m.importance) } }, m.importance || 'normal'),
2185
- m.source && h('span', { className: 'badge badge-neutral' }, m.source)
2192
+ // Table-style compact list
2193
+ filtered.length === 0
2194
+ ? h('div', { style: { padding: 32, textAlign: 'center', color: 'var(--text-muted)', fontSize: 13 } }, 'No memories found')
2195
+ : h(Fragment, null,
2196
+ // Header row
2197
+ h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 100px 70px 60px 70px 36px', gap: 8, padding: '6px 16px', borderBottom: '1px solid var(--border)', fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.5px' } },
2198
+ h('span', null, 'Memory'),
2199
+ h('span', null, 'Category'),
2200
+ h('span', null, 'Level'),
2201
+ h('span', null, 'Conf'),
2202
+ h('span', null, 'Date'),
2203
+ h('span', null, '')
2204
+ ),
2205
+ // Rows
2206
+ paged.map(function(m) {
2207
+ var isExpanded = expandedId === m.id;
2208
+ var conf = m.confidence != null ? Math.round(m.confidence * 100) : 0;
2209
+ var confBar = conf >= 80 ? 'var(--success)' : conf >= 50 ? 'var(--warning)' : 'var(--danger)';
2210
+ return h('div', { key: m.id },
2211
+ // Compact row
2212
+ h('div', {
2213
+ style: { display: 'grid', gridTemplateColumns: '1fr 100px 70px 60px 70px 36px', gap: 8, padding: '8px 16px', borderBottom: '1px solid var(--border)', cursor: 'pointer', fontSize: 13, alignItems: 'center', transition: 'background 0.1s', background: isExpanded ? 'var(--bg-tertiary)' : 'transparent' },
2214
+ onClick: function() { setExpandedId(isExpanded ? null : m.id); },
2215
+ onMouseEnter: function(e) { if (!isExpanded) e.currentTarget.style.background = 'var(--bg-secondary)'; },
2216
+ onMouseLeave: function(e) { if (!isExpanded) e.currentTarget.style.background = 'transparent'; }
2217
+ },
2218
+ // Title + preview
2219
+ h('div', { style: { overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' } },
2220
+ h('span', { style: { fontWeight: 500 } }, m.title || 'Untitled'),
2221
+ m.content && h('span', { style: { color: 'var(--text-muted)', marginLeft: 8, fontSize: 12 } }, m.content.substring(0, 60) + (m.content.length > 60 ? '...' : ''))
2186
2222
  ),
2187
-
2188
- // Content (truncated)
2189
- h('div', { style: { fontSize: 13, color: 'var(--text-muted)', marginBottom: 8, lineHeight: 1.5, overflow: 'hidden', textOverflow: 'ellipsis' } }, truncatedContent),
2190
-
2191
- // Tags row
2192
- tags.length > 0 && h('div', { style: { display: 'flex', gap: 4, marginBottom: 8, flexWrap: 'wrap' } },
2193
- tags.map(function(tag, ti) {
2194
- return h('span', { key: ti, className: 'badge badge-neutral', style: { fontSize: 10 } }, tag);
2195
- })
2223
+ // Category badge
2224
+ h('span', { style: { display: 'inline-block', padding: '1px 6px', borderRadius: 3, fontSize: 10, fontWeight: 600, color: '#fff', background: catColor(m.category), whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, (m.category || '').replace(/_/g, ' ')),
2225
+ // Importance
2226
+ h('span', { style: { fontSize: 11, color: impColor(m.importance), fontWeight: 500 } }, m.importance || 'normal'),
2227
+ // Confidence bar
2228
+ h('div', { style: { display: 'flex', alignItems: 'center', gap: 4 } },
2229
+ h('div', { style: { flex: 1, height: 4, borderRadius: 2, background: 'var(--border)' } },
2230
+ h('div', { style: { width: conf + '%', height: '100%', borderRadius: 2, background: confBar } })
2231
+ ),
2232
+ h('span', { style: { fontSize: 10, color: 'var(--text-muted)', minWidth: 24 } }, conf + '%')
2196
2233
  ),
2197
-
2198
- // Meta row: confidence, created, last accessed, delete button
2199
- h('div', { style: { display: 'flex', alignItems: 'center', gap: 16, fontSize: 11, color: 'var(--text-muted)' } },
2200
- h('span', null, 'Confidence: ', h('strong', null, confidence)),
2201
- h('span', null, 'Created: ', created),
2202
- h('span', null, 'Last accessed: ', lastAccessed),
2234
+ // Date
2235
+ h('span', { style: { fontSize: 11, color: 'var(--text-muted)', whiteSpace: 'nowrap' } }, fmtDate(m.createdAt)),
2236
+ // Expand indicator
2237
+ h('span', { style: { fontSize: 10, color: 'var(--text-muted)', textAlign: 'center' } }, isExpanded ? '▲' : '▼')
2238
+ ),
2239
+ // Expanded detail
2240
+ isExpanded && h('div', { style: { padding: '10px 16px 12px', background: 'var(--bg-tertiary)', borderBottom: '1px solid var(--border)', fontSize: 12, lineHeight: 1.6 } },
2241
+ h('div', { style: { color: 'var(--text)', marginBottom: 8, whiteSpace: 'pre-wrap', maxHeight: 200, overflow: 'auto' } }, m.content || '(empty)'),
2242
+ h('div', { style: { display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center', fontSize: 11, color: 'var(--text-muted)' } },
2243
+ h('span', null, 'Source: ', h('strong', null, m.source || '-')),
2244
+ h('span', null, 'Created: ', h('strong', null, fmtDate(m.createdAt)), ' ', fmtTime(m.createdAt)),
2245
+ m.lastAccessedAt && h('span', null, 'Last accessed: ', h('strong', null, fmtDate(m.lastAccessedAt))),
2246
+ m.tags && m.tags.length > 0 && h('span', null, 'Tags: ', m.tags.join(', ')),
2203
2247
  h('div', { style: { flex: 1 } }),
2204
- h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--danger)' }, onClick: function() { deleteMemory(m.id); } }, I.trash(), ' Delete')
2248
+ h('button', { className: 'btn btn-ghost btn-sm', style: { color: 'var(--danger)', height: 24, fontSize: 11 }, onClick: function(e) { e.stopPropagation(); deleteMemory(m.id); } }, I.trash(), ' Delete')
2205
2249
  )
2206
- );
2207
- })
2250
+ )
2251
+ );
2252
+ }),
2253
+
2254
+ // Pagination
2255
+ totalPages > 1 && h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4, padding: '10px 16px', borderTop: '1px solid var(--border)' } },
2256
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page <= 1, onClick: function() { setPage(1); }, style: { fontSize: 11, height: 28 } }, '«'),
2257
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page <= 1, onClick: function() { setPage(page - 1); }, style: { fontSize: 11, height: 28 } }, '‹'),
2258
+ h('span', { style: { fontSize: 12, color: 'var(--text-muted)', padding: '0 8px' } }, 'Page ', h('strong', null, page), ' of ', h('strong', null, totalPages)),
2259
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page >= totalPages, onClick: function() { setPage(page + 1); }, style: { fontSize: 11, height: 28 } }, '›'),
2260
+ h('button', { className: 'btn btn-ghost btn-sm', disabled: page >= totalPages, onClick: function() { setPage(totalPages); }, style: { fontSize: 11, height: 28 } }, '»')
2208
2261
  )
2262
+ )
2209
2263
  ),
2210
2264
 
2211
2265
  // Create Memory Modal
2212
2266
  showCreateModal && h('div', { className: 'modal-overlay', onClick: function() { setShowCreateModal(false); } },
2213
- h('div', { className: 'modal', style: { maxWidth: 540 }, onClick: function(e) { e.stopPropagation(); } },
2267
+ h('div', { className: 'modal', style: { maxWidth: 500 }, onClick: function(e) { e.stopPropagation(); } },
2214
2268
  h('div', { className: 'modal-header' },
2215
2269
  h('h2', null, 'Create Memory'),
2216
2270
  h('button', { className: 'btn btn-ghost btn-icon', onClick: function() { setShowCreateModal(false); } }, I.x())
@@ -2222,7 +2276,7 @@ function MemorySection(props) {
2222
2276
  ),
2223
2277
  h('div', { className: 'form-group' },
2224
2278
  h('label', { className: 'form-label' }, 'Content *'),
2225
- h('textarea', { className: 'input', style: { minHeight: 120 }, placeholder: 'Memory content...', value: createForm.content, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { content: e.target.value })); } })
2279
+ h('textarea', { className: 'input', style: { minHeight: 100 }, placeholder: 'Memory content...', value: createForm.content, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { content: e.target.value })); } })
2226
2280
  ),
2227
2281
  h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 } },
2228
2282
  h('div', { className: 'form-group' },
@@ -2243,12 +2297,12 @@ function MemorySection(props) {
2243
2297
  ),
2244
2298
  h('div', { className: 'form-group' },
2245
2299
  h('label', { className: 'form-label' }, 'Tags (comma-separated)'),
2246
- h('input', { className: 'input', placeholder: 'tag1, tag2, tag3', value: createForm.tags, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { tags: e.target.value })); } })
2300
+ h('input', { className: 'input', placeholder: 'tag1, tag2', value: createForm.tags, onChange: function(e) { setCreateForm(Object.assign({}, createForm, { tags: e.target.value })); } })
2247
2301
  )
2248
2302
  ),
2249
2303
  h('div', { className: 'modal-footer' },
2250
2304
  h('button', { className: 'btn btn-ghost', onClick: function() { setShowCreateModal(false); } }, 'Cancel'),
2251
- h('button', { className: 'btn btn-primary', onClick: createMemory }, 'Create Memory')
2305
+ h('button', { className: 'btn btn-primary', onClick: createMemory }, 'Create')
2252
2306
  )
2253
2307
  )
2254
2308
  )