9.4 KiB
v0.18.0 Phase 3 — Frontend UI Changes Guide
Overview
Phase 3 adds the user-facing memory management UI:
- Settings → Memory tab: view, search, edit, approve/reject memories
- Admin → AI → Memory: review pipeline for auto-extracted memories
- Persona forms: memory_enabled toggle + custom extraction prompt
- Admin → System → Settings: memory extraction toggle
New Files (drop in place)
| File | Lines | Description |
|---|---|---|
src/js/memory-ui.js |
~310 | Memory UI module — settings panel, admin panel, persona form fields |
src/css/memory.css |
~230 | Styles for memory cards, badges, toolbar, edit forms |
Existing File Modifications
1. src/index.html — Add Memory Tab + Admin Section
A. Settings Modal — Add Memory Tab Button
After the Knowledge tab button (~line 389):
<button class=\"settings-tab\" data-stab=\"memory\" onclick=\"UI.switchSettingsTab('memory')\" id=\"settingsMemoryTabBtn\">Memory</button>
B. Settings Modal — Add Memory Tab Content
After the Knowledge Bases tab content block (after settingsKnowledgeBasesTab div, ~line 552):
<!-- Memory Tab (v0.18.0) -->
<div class=\"settings-tab-content\" id=\"settingsMemoryTab\" style=\"display:none\">
<section class=\"settings-section\">
<h3 style=\"font-size:14px;margin-bottom:4px\">My Memories</h3>
<p class=\"section-hint\" style=\"margin-bottom:8px\">Facts and preferences learned from your conversations. Memories help AI provide more personalized responses.</p>
<div id=\"settingsMemoryContent\"></div>
</section>
</div>
C. Admin Panel — Add Memory Section
In the admin sections HTML, after the adminPresetsTab block (~line 790),
add a new admin section:
<div class=\"admin-section-content\" id=\"adminMemoryTab\" style=\"display:none\">
<div id=\"adminMemoryContent\"></div>
</div>
D. Admin Settings — Add Memory Extraction Toggle
In adminSettingsTab, after the Auto-Compaction section (~line 908):
<section class=\"settings-section\">
<h3>Memory Extraction</h3>
<label class=\"checkbox-label\"><input type=\"checkbox\" id=\"adminMemoryExtractionEnabled\"> Enable automatic memory extraction</label>
<p class=\"section-hint\">When enabled, the system automatically extracts memorable facts from conversations using the utility model. Extracted memories require admin approval before becoming active. Requires a utility model role.</p>
<div id=\"memoryExtractionConfigFields\" style=\"display:none;margin-top:8px\">
<label class=\"checkbox-label\"><input type=\"checkbox\" id=\"adminMemoryAutoApprove\"> Auto-approve extracted memories</label>
<p class=\"section-hint\">Skip the review pipeline and activate extracted memories immediately. Not recommended for sensitive environments.</p>
</div>
</section>
E. Script + CSS Include
In the <head> section, add the CSS:
<link rel=\"stylesheet\" href=\"css/memory.css\">
In the script block at the bottom (after knowledge-ui.js):
<script src=\"js/memory-ui.js\"></script>
2. src/js/api.js — Memory API Client Methods
Add after the user presets section (~line 310):
// Memory (v0.18.0)
listMemories(status, query) {
const params = new URLSearchParams();
if (status) params.set('status', status);
if (query) params.set('query', query);
return this._get('/api/v1/memories?' + params.toString());
},
getMemoryCount() { return this._get('/api/v1/memories/count'); },
updateMemory(id, data) { return this._put(`/api/v1/memories/${id}`, data); },
deleteMemory(id) { return this._del(`/api/v1/memories/${id}`); },
approveMemory(id) { return this._post(`/api/v1/memories/${id}/approve`); },
rejectMemory(id) { return this._post(`/api/v1/memories/${id}/reject`); },
bulkApproveMemories(ids) { return this._post('/api/v1/admin/memories/bulk-approve', { ids }); },
adminListPendingMemories() { return this._get('/api/v1/admin/memories/pending'); },
3. src/js/ui-core.js — Wire Memory Tab into Settings
In switchSettingsTab() (~line 932), add after the knowledgeBases case:
if (tab === 'memory') {
if (typeof MemoryUI !== 'undefined') {
MemoryUI.openSettingsPanel();
}
}
4. src/js/ui-admin.js — Register Memory in Admin Panel
A. Add "memory" to ADMIN_SECTIONS (~line 9)
const ADMIN_SECTIONS = {
people: ['users', 'teams', 'groups'],
ai: ['providers', 'models', 'presets', 'roles', 'knowledgeBases', 'memory'],
system: ['settings', 'storage', 'extensions'],
monitoring: ['usage', 'audit', 'stats'],
};
B. Add label (~line 18)
In ADMIN_LABELS, add:
memory: 'Memory',
C. Add loader (~line 37)
In ADMIN_LOADERS, add:
memory: () => {
if (typeof MemoryUI === 'undefined') {
console.error('[Admin] MemoryUI not loaded');
return;
}
MemoryUI.openAdminPanel();
},
5. src/js/ui-admin.js — Load/Save Memory Extraction Settings
A. In loadAdminSettings() (~after compaction config loading)
Add after the compaction threshold/cooldown block:
// Memory Extraction (v0.18.0)
const memCfg = getSetting('memory_extraction', {}) || {};
const memExtractionEl = document.getElementById('adminMemoryExtractionEnabled');
if (memExtractionEl) {
memExtractionEl.checked = !!memCfg.enabled;
document.getElementById('memoryExtractionConfigFields').style.display =
memCfg.enabled ? '' : 'none';
}
const memAutoApproveEl = document.getElementById('adminMemoryAutoApprove');
if (memAutoApproveEl) memAutoApproveEl.checked = !!memCfg.auto_approve;
B. Wire toggle visibility
Add in _initAdminListeners() or inline:
document.getElementById('adminMemoryExtractionEnabled')?.addEventListener('change', function() {
document.getElementById('memoryExtractionConfigFields').style.display =
this.checked ? '' : 'none';
});
6. src/js/settings-handlers.js — Save Memory Extraction Config
In handleSaveAdminSettings(), before the final toast (~line 252):
// Memory Extraction config (v0.18.0)
const memExtractionEnabled = document.getElementById('adminMemoryExtractionEnabled')?.checked || false;
const memAutoApprove = document.getElementById('adminMemoryAutoApprove')?.checked || false;
await API.adminUpdateSetting('memory_extraction', { value: {
enabled: memExtractionEnabled,
auto_approve: memAutoApprove,
}});
await API.adminUpdateSetting('memory_extraction_enabled', { value: memExtractionEnabled });
7. src/js/ui-core.js — Persona Form Memory Fields
For admin persona forms, in the function that initializes the admin preset
form (after renderPresetForm call), add:
if (typeof MemoryUI !== 'undefined') {
MemoryUI.appendMemoryFields(container, prefix);
}
And in the submit handler, merge memory values:
const values = form.getValues();
if (typeof MemoryUI !== 'undefined') {
Object.assign(values, MemoryUI.getMemoryValues(prefix));
}
When editing an existing persona, call:
if (typeof MemoryUI !== 'undefined') {
MemoryUI.setMemoryValues(prefix, persona);
}
Testing Checklist
- Settings → Memory tab — click tab, verify memory list loads
- Memory search — type in search box, verify filtering works
- Memory status filter — switch between Active/Pending/Archived
- Edit memory — click pencil icon, modify key/value, save
- Delete memory — click trash icon, confirm, verify removal
- Approve/Reject — with pending memories, verify buttons work
- Approve All — bulk approve pending memories
- Admin → AI → Memory — navigate to admin memory panel
- Admin pending review — verify pending memories show with approve/reject
- Admin bulk approve — verify bulk action works
- Admin Settings → Memory Extraction — toggle on/off, verify checkbox persists
- Persona form — create new persona, verify memory section appears
- Persona memory toggle — uncheck, verify it persists on save
- Mobile responsive — test all memory views on narrow viewport
- Empty states — verify graceful display when no memories exist
CSS Variable Dependencies
The memory styles reference these existing CSS variables:
--bg-1,--bg-2,--bg-3— background layers--text-1,--text-2,--text-3— text colors--border— border color--accent,--accent-dim,--accent-text— accent colors--success,--warning,--danger— status colors
All are defined in the existing styles.css theme system.
Architecture Notes
MemoryUIfollows the same pattern asKnowledgeUI— standalone module that integrates viatypeof MemoryUI !== 'undefined'guards- No build step required — vanilla JS module loaded via
<script>tag - Admin memory section registered in
ADMIN_SECTIONSandADMIN_LOADERSmaps following the existing convention - Persona memory fields are appended dynamically via
appendMemoryFields()rather than embedded inrenderPresetForm()to avoid modifying the shared form builder - Debounce on search input prevents excessive API calls
- Memory cards use inline edit — no modal, same pattern as note inline editing
- CSS uses existing theme variables for consistent dark/light mode support