superlocalmemory 3.4.16 → 3.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/package.json +1 -3
- package/pyproject.toml +10 -1
- package/src/superlocalmemory/cli/setup_wizard.py +30 -0
- package/src/superlocalmemory/server/routes/entity.py +5 -9
- package/src/superlocalmemory/server/routes/helpers.py +120 -15
- package/src/superlocalmemory/server/routes/ingest.py +2 -3
- package/src/superlocalmemory/server/routes/v3_api.py +42 -2
- package/src/superlocalmemory/server/unified_daemon.py +21 -11
- package/src/superlocalmemory.egg-info/PKG-INFO +5 -2
- package/src/superlocalmemory.egg-info/requires.txt +3 -0
- package/docs/ARCHITECTURE.md +0 -149
- package/docs/api-reference.md +0 -284
- package/docs/auto-memory.md +0 -150
- package/docs/cli-reference.md +0 -327
- package/docs/cloud-backup.md +0 -174
- package/docs/compliance.md +0 -191
- package/docs/configuration.md +0 -182
- package/docs/getting-started.md +0 -102
- package/docs/ide-setup.md +0 -261
- package/docs/mcp-tools.md +0 -220
- package/docs/migration-from-v2.md +0 -170
- package/docs/profiles.md +0 -173
- package/docs/screenshots/01-dashboard-main.png +0 -0
- package/docs/screenshots/02-knowledge-graph.png +0 -0
- package/docs/screenshots/03-math-health.png +0 -0
- package/docs/screenshots/03-patterns-learning.png +0 -0
- package/docs/screenshots/04-learning-dashboard.png +0 -0
- package/docs/screenshots/04-recall-lab.png +0 -0
- package/docs/screenshots/05-behavioral-analysis.png +0 -0
- package/docs/screenshots/05-trust-dashboard.png +0 -0
- package/docs/screenshots/06-graph-communities.png +0 -0
- package/docs/screenshots/06-settings.png +0 -0
- package/docs/screenshots/07-memories-blurred.png +0 -0
- package/docs/skill-evolution.md +0 -256
- package/docs/troubleshooting.md +0 -310
- package/docs/v2-archive/ACCESSIBILITY.md +0 -291
- package/docs/v2-archive/ARCHITECTURE.md +0 -886
- package/docs/v2-archive/CLI-COMMANDS-REFERENCE.md +0 -425
- package/docs/v2-archive/COMPRESSION-README.md +0 -390
- package/docs/v2-archive/FRAMEWORK-INTEGRATIONS.md +0 -300
- package/docs/v2-archive/MCP-MANUAL-SETUP.md +0 -775
- package/docs/v2-archive/MCP-TROUBLESHOOTING.md +0 -787
- package/docs/v2-archive/PATTERN-LEARNING.md +0 -228
- package/docs/v2-archive/PROFILES-GUIDE.md +0 -453
- package/docs/v2-archive/RESET-GUIDE.md +0 -353
- package/docs/v2-archive/SEARCH-ENGINE-V2.2.0.md +0 -749
- package/docs/v2-archive/SEARCH-INTEGRATION-GUIDE.md +0 -502
- package/docs/v2-archive/UI-SERVER.md +0 -262
- package/docs/v2-archive/UNIVERSAL-INTEGRATION.md +0 -488
- package/docs/v2-archive/V2.2.0-OPTIONAL-SEARCH.md +0 -666
- package/docs/v2-archive/WINDOWS-INSTALL-README.txt +0 -34
- package/docs/v2-archive/WINDOWS-POST-INSTALL.txt +0 -45
- package/docs/v2-archive/example_graph_usage.py +0 -146
- package/ui/index.html +0 -1879
- package/ui/js/agents.js +0 -192
- package/ui/js/auto-settings.js +0 -399
- package/ui/js/behavioral.js +0 -276
- package/ui/js/clusters.js +0 -206
- package/ui/js/compliance.js +0 -252
- package/ui/js/core.js +0 -246
- package/ui/js/dashboard.js +0 -110
- package/ui/js/events.js +0 -178
- package/ui/js/fact-detail.js +0 -92
- package/ui/js/feedback.js +0 -333
- package/ui/js/graph-core.js +0 -447
- package/ui/js/graph-filters.js +0 -220
- package/ui/js/graph-interactions.js +0 -351
- package/ui/js/graph-ui.js +0 -214
- package/ui/js/ide-status.js +0 -102
- package/ui/js/init.js +0 -45
- package/ui/js/learning.js +0 -435
- package/ui/js/lifecycle.js +0 -298
- package/ui/js/math-health.js +0 -98
- package/ui/js/memories.js +0 -264
- package/ui/js/modal.js +0 -357
- package/ui/js/patterns.js +0 -93
- package/ui/js/profiles.js +0 -236
- package/ui/js/recall-lab.js +0 -292
- package/ui/js/search.js +0 -59
- package/ui/js/settings.js +0 -224
- package/ui/js/timeline.js +0 -32
- package/ui/js/trust-dashboard.js +0 -73
package/ui/js/recall-lab.js
DELETED
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
// SuperLocalMemory V3 — Recall Lab with Dual-Display + Pagination
|
|
2
|
-
// Part of Qualixar | https://superlocalmemory.com
|
|
3
|
-
|
|
4
|
-
var recallLabState = {
|
|
5
|
-
allResults: [],
|
|
6
|
-
page: 0,
|
|
7
|
-
perPage: 10,
|
|
8
|
-
query: '',
|
|
9
|
-
synthesis: '',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
document.getElementById('recall-lab-search')?.addEventListener('click', function() {
|
|
13
|
-
var query = document.getElementById('recall-lab-query').value.trim();
|
|
14
|
-
if (!query) return;
|
|
15
|
-
|
|
16
|
-
recallLabState.query = query;
|
|
17
|
-
recallLabState.page = 0;
|
|
18
|
-
var perPageEl = document.getElementById('recall-lab-per-page');
|
|
19
|
-
recallLabState.perPage = perPageEl ? parseInt(perPageEl.value) : 10;
|
|
20
|
-
var fetchLimit = Math.max(recallLabState.perPage * 5, 50);
|
|
21
|
-
|
|
22
|
-
var resultsDiv = document.getElementById('recall-lab-results');
|
|
23
|
-
var metaDiv = document.getElementById('recall-lab-meta');
|
|
24
|
-
resultsDiv.textContent = '';
|
|
25
|
-
var spinner = document.createElement('div');
|
|
26
|
-
spinner.className = 'text-center py-4';
|
|
27
|
-
var spinnerInner = document.createElement('div');
|
|
28
|
-
spinnerInner.className = 'spinner-border text-primary';
|
|
29
|
-
spinner.appendChild(spinnerInner);
|
|
30
|
-
resultsDiv.appendChild(spinner);
|
|
31
|
-
|
|
32
|
-
fetch('/api/v3/recall/trace', {
|
|
33
|
-
method: 'POST',
|
|
34
|
-
headers: {'Content-Type': 'application/json'},
|
|
35
|
-
body: JSON.stringify({query: query, limit: fetchLimit, synthesize: true})
|
|
36
|
-
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
37
|
-
if (data.error) {
|
|
38
|
-
resultsDiv.textContent = '';
|
|
39
|
-
var errDiv = document.createElement('div');
|
|
40
|
-
errDiv.className = 'alert alert-danger';
|
|
41
|
-
errDiv.textContent = data.error;
|
|
42
|
-
resultsDiv.appendChild(errDiv);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
metaDiv.textContent = '';
|
|
47
|
-
appendMetaField(metaDiv, 'Query type: ', data.query_type || 'unknown');
|
|
48
|
-
metaDiv.appendChild(document.createTextNode(' | '));
|
|
49
|
-
appendMetaField(metaDiv, 'Results: ', String((data.results || []).length));
|
|
50
|
-
metaDiv.appendChild(document.createTextNode(' | '));
|
|
51
|
-
appendMetaField(metaDiv, 'Time: ', (data.retrieval_time_ms || 0).toFixed(0) + 'ms');
|
|
52
|
-
|
|
53
|
-
recallLabState.allResults = data.results || [];
|
|
54
|
-
recallLabState.synthesis = data.synthesis || '';
|
|
55
|
-
|
|
56
|
-
if (recallLabState.allResults.length === 0) {
|
|
57
|
-
resultsDiv.textContent = '';
|
|
58
|
-
var infoDiv = document.createElement('div');
|
|
59
|
-
infoDiv.className = 'alert alert-info';
|
|
60
|
-
infoDiv.textContent = 'No results found.';
|
|
61
|
-
resultsDiv.appendChild(infoDiv);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
renderRecallPage();
|
|
66
|
-
}).catch(function(e) {
|
|
67
|
-
resultsDiv.textContent = '';
|
|
68
|
-
var errDiv = document.createElement('div');
|
|
69
|
-
errDiv.className = 'alert alert-danger';
|
|
70
|
-
errDiv.textContent = 'Error: ' + e.message;
|
|
71
|
-
resultsDiv.appendChild(errDiv);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
function renderRecallPage() {
|
|
76
|
-
var resultsDiv = document.getElementById('recall-lab-results');
|
|
77
|
-
resultsDiv.textContent = '';
|
|
78
|
-
|
|
79
|
-
var results = recallLabState.allResults;
|
|
80
|
-
var start = recallLabState.page * recallLabState.perPage;
|
|
81
|
-
var end = Math.min(start + recallLabState.perPage, results.length);
|
|
82
|
-
var pageResults = results.slice(start, end);
|
|
83
|
-
var totalPages = Math.ceil(results.length / recallLabState.perPage);
|
|
84
|
-
|
|
85
|
-
// Synthesis banner (Mode B/C only)
|
|
86
|
-
if (recallLabState.synthesis && recallLabState.page === 0) {
|
|
87
|
-
var synBanner = document.createElement('div');
|
|
88
|
-
synBanner.className = 'alert alert-light border-start border-4 border-primary mb-3';
|
|
89
|
-
var synTitle = document.createElement('strong');
|
|
90
|
-
synTitle.textContent = 'AI Summary';
|
|
91
|
-
synBanner.appendChild(synTitle);
|
|
92
|
-
synBanner.appendChild(document.createElement('br'));
|
|
93
|
-
var synText = document.createElement('span');
|
|
94
|
-
synText.textContent = recallLabState.synthesis;
|
|
95
|
-
synBanner.appendChild(synText);
|
|
96
|
-
resultsDiv.appendChild(synBanner);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
var listGroup = document.createElement('div');
|
|
100
|
-
listGroup.className = 'list-group';
|
|
101
|
-
|
|
102
|
-
pageResults.forEach(function(r, i) {
|
|
103
|
-
var globalIndex = start + i;
|
|
104
|
-
var channels = r.channel_scores || {};
|
|
105
|
-
var maxChannel = Math.max(channels.semantic || 0, channels.bm25 || 0, channels.entity_graph || 0, channels.temporal || 0) || 1;
|
|
106
|
-
var hasSource = r.source_content && r.source_content.length > 0;
|
|
107
|
-
var displayText = hasSource ? r.source_content : r.content;
|
|
108
|
-
|
|
109
|
-
var item = document.createElement('div');
|
|
110
|
-
item.className = 'list-group-item';
|
|
111
|
-
|
|
112
|
-
// Score badge row
|
|
113
|
-
var scoreRow = document.createElement('div');
|
|
114
|
-
scoreRow.className = 'd-flex justify-content-between align-items-center mb-1';
|
|
115
|
-
var numLabel = document.createElement('strong');
|
|
116
|
-
numLabel.textContent = '#' + (globalIndex + 1);
|
|
117
|
-
scoreRow.appendChild(numLabel);
|
|
118
|
-
var scoreBadges = document.createElement('div');
|
|
119
|
-
scoreBadges.innerHTML = '<span class="badge bg-primary me-1">Score: ' + r.score + '</span>' +
|
|
120
|
-
'<span class="badge bg-secondary me-1">Trust: ' + r.trust_score + '</span>' +
|
|
121
|
-
'<span class="badge bg-outline-info" style="border:1px solid #0dcaf0;color:#0dcaf0;">Conf: ' + r.confidence + '</span>';
|
|
122
|
-
scoreRow.appendChild(scoreBadges);
|
|
123
|
-
item.appendChild(scoreRow);
|
|
124
|
-
|
|
125
|
-
// Original memory text (primary display)
|
|
126
|
-
var contentDiv = document.createElement('div');
|
|
127
|
-
contentDiv.className = 'mb-2';
|
|
128
|
-
contentDiv.style.cssText = 'white-space:pre-wrap; line-height:1.5;';
|
|
129
|
-
var truncated = displayText.length > 500 ? displayText.substring(0, 500) + '...' : displayText;
|
|
130
|
-
contentDiv.textContent = truncated;
|
|
131
|
-
item.appendChild(contentDiv);
|
|
132
|
-
|
|
133
|
-
// Expandable atomic fact section (only if source differs from content)
|
|
134
|
-
if (hasSource && r.content !== r.source_content) {
|
|
135
|
-
var expandBtn = document.createElement('button');
|
|
136
|
-
expandBtn.className = 'btn btn-sm btn-outline-secondary mb-2';
|
|
137
|
-
expandBtn.textContent = 'Show matched fact + channels';
|
|
138
|
-
var factSection = document.createElement('div');
|
|
139
|
-
factSection.style.display = 'none';
|
|
140
|
-
factSection.className = 'border-top pt-2 mt-1';
|
|
141
|
-
|
|
142
|
-
var factLabel = document.createElement('small');
|
|
143
|
-
factLabel.className = 'text-muted d-block mb-1';
|
|
144
|
-
factLabel.textContent = 'Matched atomic fact:';
|
|
145
|
-
factSection.appendChild(factLabel);
|
|
146
|
-
|
|
147
|
-
var factContent = document.createElement('div');
|
|
148
|
-
factContent.className = 'small bg-light p-2 rounded mb-2';
|
|
149
|
-
factContent.textContent = r.content;
|
|
150
|
-
factSection.appendChild(factContent);
|
|
151
|
-
|
|
152
|
-
// Channel bars
|
|
153
|
-
factSection.appendChild(buildChannelBar('Semantic', channels.semantic || 0, maxChannel, 'primary'));
|
|
154
|
-
factSection.appendChild(buildChannelBar('BM25', channels.bm25 || 0, maxChannel, 'success'));
|
|
155
|
-
factSection.appendChild(buildChannelBar('Entity', channels.entity_graph || 0, maxChannel, 'info'));
|
|
156
|
-
factSection.appendChild(buildChannelBar('Temporal', channels.temporal || 0, maxChannel, 'warning'));
|
|
157
|
-
|
|
158
|
-
expandBtn.addEventListener('click', function() {
|
|
159
|
-
var visible = factSection.style.display !== 'none';
|
|
160
|
-
factSection.style.display = visible ? 'none' : 'block';
|
|
161
|
-
expandBtn.textContent = visible ? 'Show matched fact + channels' : 'Hide matched fact';
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
item.appendChild(expandBtn);
|
|
165
|
-
item.appendChild(factSection);
|
|
166
|
-
} else {
|
|
167
|
-
// No source_content — show channel bars inline
|
|
168
|
-
var barsDiv = document.createElement('div');
|
|
169
|
-
barsDiv.className = 'mt-1';
|
|
170
|
-
barsDiv.appendChild(buildChannelBar('Semantic', channels.semantic || 0, maxChannel, 'primary'));
|
|
171
|
-
barsDiv.appendChild(buildChannelBar('BM25', channels.bm25 || 0, maxChannel, 'success'));
|
|
172
|
-
barsDiv.appendChild(buildChannelBar('Entity', channels.entity_graph || 0, maxChannel, 'info'));
|
|
173
|
-
barsDiv.appendChild(buildChannelBar('Temporal', channels.temporal || 0, maxChannel, 'warning'));
|
|
174
|
-
item.appendChild(barsDiv);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Click for detail modal
|
|
178
|
-
item.style.cursor = 'pointer';
|
|
179
|
-
(function(result) {
|
|
180
|
-
contentDiv.addEventListener('click', function() {
|
|
181
|
-
if (typeof openMemoryDetail === 'function') {
|
|
182
|
-
openMemoryDetail({
|
|
183
|
-
id: result.fact_id,
|
|
184
|
-
memory_id: result.memory_id,
|
|
185
|
-
content: result.source_content || result.content,
|
|
186
|
-
score: result.score,
|
|
187
|
-
importance: Math.round((result.confidence || 0.5) * 10),
|
|
188
|
-
category: 'recall',
|
|
189
|
-
created_at: null,
|
|
190
|
-
trust_score: result.trust_score,
|
|
191
|
-
channel_scores: result.channel_scores
|
|
192
|
-
}, 'recall'); // source='recall': show View Original, hide Expand Neighbors
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
})(r);
|
|
196
|
-
|
|
197
|
-
listGroup.appendChild(item);
|
|
198
|
-
});
|
|
199
|
-
resultsDiv.appendChild(listGroup);
|
|
200
|
-
|
|
201
|
-
// Pagination
|
|
202
|
-
if (totalPages > 1) {
|
|
203
|
-
var nav = document.createElement('nav');
|
|
204
|
-
nav.className = 'mt-3';
|
|
205
|
-
var ul = document.createElement('ul');
|
|
206
|
-
ul.className = 'pagination justify-content-center';
|
|
207
|
-
|
|
208
|
-
var prevLi = document.createElement('li');
|
|
209
|
-
prevLi.className = 'page-item' + (recallLabState.page === 0 ? ' disabled' : '');
|
|
210
|
-
var prevA = document.createElement('a');
|
|
211
|
-
prevA.className = 'page-link';
|
|
212
|
-
prevA.href = '#';
|
|
213
|
-
prevA.textContent = 'Previous';
|
|
214
|
-
prevA.addEventListener('click', function(e) {
|
|
215
|
-
e.preventDefault();
|
|
216
|
-
if (recallLabState.page > 0) { recallLabState.page--; renderRecallPage(); }
|
|
217
|
-
});
|
|
218
|
-
prevLi.appendChild(prevA);
|
|
219
|
-
ul.appendChild(prevLi);
|
|
220
|
-
|
|
221
|
-
for (var p = 0; p < totalPages; p++) {
|
|
222
|
-
var li = document.createElement('li');
|
|
223
|
-
li.className = 'page-item' + (p === recallLabState.page ? ' active' : '');
|
|
224
|
-
var a = document.createElement('a');
|
|
225
|
-
a.className = 'page-link';
|
|
226
|
-
a.href = '#';
|
|
227
|
-
a.textContent = String(p + 1);
|
|
228
|
-
(function(pageNum) {
|
|
229
|
-
a.addEventListener('click', function(e) {
|
|
230
|
-
e.preventDefault();
|
|
231
|
-
recallLabState.page = pageNum;
|
|
232
|
-
renderRecallPage();
|
|
233
|
-
});
|
|
234
|
-
})(p);
|
|
235
|
-
li.appendChild(a);
|
|
236
|
-
ul.appendChild(li);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
var nextLi = document.createElement('li');
|
|
240
|
-
nextLi.className = 'page-item' + (recallLabState.page >= totalPages - 1 ? ' disabled' : '');
|
|
241
|
-
var nextA = document.createElement('a');
|
|
242
|
-
nextA.className = 'page-link';
|
|
243
|
-
nextA.href = '#';
|
|
244
|
-
nextA.textContent = 'Next';
|
|
245
|
-
nextA.addEventListener('click', function(e) {
|
|
246
|
-
e.preventDefault();
|
|
247
|
-
if (recallLabState.page < totalPages - 1) { recallLabState.page++; renderRecallPage(); }
|
|
248
|
-
});
|
|
249
|
-
nextLi.appendChild(nextA);
|
|
250
|
-
ul.appendChild(nextLi);
|
|
251
|
-
nav.appendChild(ul);
|
|
252
|
-
resultsDiv.appendChild(nav);
|
|
253
|
-
|
|
254
|
-
var info = document.createElement('div');
|
|
255
|
-
info.className = 'text-center text-muted small';
|
|
256
|
-
info.textContent = 'Showing ' + (start + 1) + '-' + end + ' of ' + results.length + ' results';
|
|
257
|
-
resultsDiv.appendChild(info);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function appendMetaField(parent, label, value) {
|
|
262
|
-
parent.appendChild(document.createTextNode(label));
|
|
263
|
-
var strong = document.createElement('strong');
|
|
264
|
-
strong.textContent = value;
|
|
265
|
-
parent.appendChild(strong);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function buildChannelBar(name, score, max, color) {
|
|
269
|
-
var pct = max > 0 ? Math.round((score / max) * 100) : 0;
|
|
270
|
-
var row = document.createElement('div');
|
|
271
|
-
row.className = 'd-flex align-items-center mb-1';
|
|
272
|
-
var label = document.createElement('span');
|
|
273
|
-
label.className = 'me-2';
|
|
274
|
-
label.style.width = '70px';
|
|
275
|
-
label.style.fontSize = '0.75rem';
|
|
276
|
-
label.textContent = name;
|
|
277
|
-
row.appendChild(label);
|
|
278
|
-
var progressWrap = document.createElement('div');
|
|
279
|
-
progressWrap.className = 'progress flex-grow-1';
|
|
280
|
-
progressWrap.style.height = '14px';
|
|
281
|
-
var bar = document.createElement('div');
|
|
282
|
-
bar.className = 'progress-bar bg-' + color;
|
|
283
|
-
bar.style.width = pct + '%';
|
|
284
|
-
bar.textContent = score.toFixed(3);
|
|
285
|
-
progressWrap.appendChild(bar);
|
|
286
|
-
row.appendChild(progressWrap);
|
|
287
|
-
return row;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
document.getElementById('recall-lab-query')?.addEventListener('keydown', function(e) {
|
|
291
|
-
if (e.key === 'Enter') document.getElementById('recall-lab-search')?.click();
|
|
292
|
-
});
|
package/ui/js/search.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// SuperLocalMemory V2 - Search
|
|
2
|
-
// Depends on: core.js, memories.js (renderMemoriesTable, loadMemories)
|
|
3
|
-
|
|
4
|
-
var lastSearchResults = null;
|
|
5
|
-
|
|
6
|
-
async function searchMemories() {
|
|
7
|
-
var query = document.getElementById('search-query').value;
|
|
8
|
-
if (!query.trim()) { loadMemories(); return; }
|
|
9
|
-
|
|
10
|
-
showLoading('memories-list', 'Searching...');
|
|
11
|
-
try {
|
|
12
|
-
var response = await fetch('/api/search', {
|
|
13
|
-
method: 'POST',
|
|
14
|
-
headers: { 'Content-Type': 'application/json' },
|
|
15
|
-
body: JSON.stringify({ query: query, limit: 20, min_score: 0.3 })
|
|
16
|
-
});
|
|
17
|
-
var data = await response.json();
|
|
18
|
-
|
|
19
|
-
var results = data.results || [];
|
|
20
|
-
results.sort(function(a, b) { return (b.score || 0) - (a.score || 0); });
|
|
21
|
-
|
|
22
|
-
lastSearchResults = results;
|
|
23
|
-
|
|
24
|
-
var exportBtn = document.getElementById('export-search-btn');
|
|
25
|
-
if (exportBtn) exportBtn.style.display = results.length > 0 ? '' : 'none';
|
|
26
|
-
|
|
27
|
-
renderMemoriesTable(results, true);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
console.error('Error searching:', error);
|
|
30
|
-
showEmpty('memories-list', 'exclamation-triangle', 'Search failed. Please try again.');
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ============================================================================
|
|
35
|
-
// Export All / Search Results
|
|
36
|
-
// ============================================================================
|
|
37
|
-
|
|
38
|
-
function exportAll(format) {
|
|
39
|
-
var url = '/api/export?format=' + encodeURIComponent(format);
|
|
40
|
-
var category = document.getElementById('filter-category').value;
|
|
41
|
-
var project = document.getElementById('filter-project').value;
|
|
42
|
-
if (category) url += '&category=' + encodeURIComponent(category);
|
|
43
|
-
if (project) url += '&project_name=' + encodeURIComponent(project);
|
|
44
|
-
window.location.href = url;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function exportSearchResults() {
|
|
48
|
-
if (!lastSearchResults || lastSearchResults.length === 0) {
|
|
49
|
-
showToast('No search results to export');
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
var content = JSON.stringify({
|
|
53
|
-
exported_at: new Date().toISOString(),
|
|
54
|
-
query: document.getElementById('search-query').value,
|
|
55
|
-
total: lastSearchResults.length,
|
|
56
|
-
results: lastSearchResults
|
|
57
|
-
}, null, 2);
|
|
58
|
-
downloadFile('search-results-' + Date.now() + '.json', content, 'application/json');
|
|
59
|
-
}
|
package/ui/js/settings.js
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
// SuperLocalMemory V2 - Settings & Backup
|
|
2
|
-
// Depends on: core.js, profiles.js (loadProfilesTable)
|
|
3
|
-
|
|
4
|
-
async function loadSettings() {
|
|
5
|
-
loadProfilesTable();
|
|
6
|
-
loadBackupStatus();
|
|
7
|
-
loadBackupList();
|
|
8
|
-
loadLearningDataStats();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function loadLearningDataStats() {
|
|
12
|
-
try {
|
|
13
|
-
var response = await fetch('/api/feedback/stats');
|
|
14
|
-
var data = await response.json();
|
|
15
|
-
var container = document.getElementById('learning-data-stats');
|
|
16
|
-
if (!container) return;
|
|
17
|
-
|
|
18
|
-
container.textContent = '';
|
|
19
|
-
var row = document.createElement('div');
|
|
20
|
-
row.className = 'row g-2';
|
|
21
|
-
|
|
22
|
-
var stats = [
|
|
23
|
-
{ value: String(data.total_signals || 0), label: 'Feedback Signals' },
|
|
24
|
-
{ value: data.ranking_phase || 'baseline', label: 'Ranking Phase' },
|
|
25
|
-
{ value: Math.round(data.progress || 0) + '%', label: 'ML Progress' },
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
stats.forEach(function(s) {
|
|
29
|
-
var col = document.createElement('div');
|
|
30
|
-
col.className = 'col-4';
|
|
31
|
-
var stat = document.createElement('div');
|
|
32
|
-
stat.className = 'backup-stat';
|
|
33
|
-
var val = document.createElement('div');
|
|
34
|
-
val.className = 'value';
|
|
35
|
-
val.textContent = s.value;
|
|
36
|
-
var lbl = document.createElement('div');
|
|
37
|
-
lbl.className = 'label';
|
|
38
|
-
lbl.textContent = s.label;
|
|
39
|
-
stat.appendChild(val);
|
|
40
|
-
stat.appendChild(lbl);
|
|
41
|
-
col.appendChild(stat);
|
|
42
|
-
row.appendChild(col);
|
|
43
|
-
});
|
|
44
|
-
container.appendChild(row);
|
|
45
|
-
} catch (error) {
|
|
46
|
-
// Silent — learning stats are optional
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function backupLearningDb() {
|
|
51
|
-
try {
|
|
52
|
-
var response = await fetch('/api/learning/backup', { method: 'POST' });
|
|
53
|
-
var data = await response.json();
|
|
54
|
-
if (data.success) {
|
|
55
|
-
showToast('Learning DB backed up: ' + (data.filename || 'learning.db.bak'));
|
|
56
|
-
} else {
|
|
57
|
-
showToast('Backup created at ~/.superlocalmemory/learning.db.bak');
|
|
58
|
-
}
|
|
59
|
-
} catch (error) {
|
|
60
|
-
// Fallback: just tell user the manual path
|
|
61
|
-
showToast('Manual backup: cp ~/.superlocalmemory/learning.db ~/.superlocalmemory/learning.db.bak');
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function loadBackupStatus() {
|
|
66
|
-
try {
|
|
67
|
-
var response = await fetch('/api/backup/status');
|
|
68
|
-
var data = await response.json();
|
|
69
|
-
renderBackupStatus(data);
|
|
70
|
-
document.getElementById('backup-interval').value = data.interval_hours <= 24 ? '24' : '168';
|
|
71
|
-
document.getElementById('backup-max').value = data.max_backups || 10;
|
|
72
|
-
document.getElementById('backup-enabled').checked = data.enabled !== false;
|
|
73
|
-
} catch (error) {
|
|
74
|
-
var container = document.getElementById('backup-status');
|
|
75
|
-
var alert = document.createElement('div');
|
|
76
|
-
alert.className = 'alert alert-warning mb-0';
|
|
77
|
-
alert.textContent = 'Auto-backup not available. Update to v2.4.0+.';
|
|
78
|
-
container.textContent = '';
|
|
79
|
-
container.appendChild(alert);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function renderBackupStatus(data) {
|
|
84
|
-
var container = document.getElementById('backup-status');
|
|
85
|
-
container.textContent = '';
|
|
86
|
-
|
|
87
|
-
var lastBackup = data.last_backup ? formatDateFull(data.last_backup) : 'Never';
|
|
88
|
-
var nextBackup = data.next_backup || 'N/A';
|
|
89
|
-
if (nextBackup === 'overdue') nextBackup = 'Overdue';
|
|
90
|
-
else if (nextBackup !== 'N/A' && nextBackup !== 'unknown') nextBackup = formatDateFull(nextBackup);
|
|
91
|
-
|
|
92
|
-
var statusColor = data.enabled ? 'text-success' : 'text-secondary';
|
|
93
|
-
var statusText = data.enabled ? 'Active' : 'Disabled';
|
|
94
|
-
|
|
95
|
-
var row = document.createElement('div');
|
|
96
|
-
row.className = 'row g-2 mb-2';
|
|
97
|
-
|
|
98
|
-
var stats = [
|
|
99
|
-
{ value: statusText, label: 'Status', cls: statusColor },
|
|
100
|
-
{ value: String(data.backup_count || 0), label: 'Backups', cls: '' },
|
|
101
|
-
{ value: (data.total_size_mb || 0) + ' MB', label: 'Storage', cls: '' }
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
stats.forEach(function(s) {
|
|
105
|
-
var col = document.createElement('div');
|
|
106
|
-
col.className = 'col-4';
|
|
107
|
-
var stat = document.createElement('div');
|
|
108
|
-
stat.className = 'backup-stat';
|
|
109
|
-
var val = document.createElement('div');
|
|
110
|
-
val.className = 'value ' + s.cls;
|
|
111
|
-
val.textContent = s.value;
|
|
112
|
-
var lbl = document.createElement('div');
|
|
113
|
-
lbl.className = 'label';
|
|
114
|
-
lbl.textContent = s.label;
|
|
115
|
-
stat.appendChild(val);
|
|
116
|
-
stat.appendChild(lbl);
|
|
117
|
-
col.appendChild(stat);
|
|
118
|
-
row.appendChild(col);
|
|
119
|
-
});
|
|
120
|
-
container.appendChild(row);
|
|
121
|
-
|
|
122
|
-
var details = [
|
|
123
|
-
{ label: 'Last backup:', value: lastBackup },
|
|
124
|
-
{ label: 'Next backup:', value: nextBackup },
|
|
125
|
-
{ label: 'Interval:', value: data.interval_display || '-' }
|
|
126
|
-
];
|
|
127
|
-
details.forEach(function(d) {
|
|
128
|
-
var div = document.createElement('div');
|
|
129
|
-
div.className = 'small text-muted';
|
|
130
|
-
var strong = document.createElement('strong');
|
|
131
|
-
strong.textContent = d.label + ' ';
|
|
132
|
-
div.appendChild(strong);
|
|
133
|
-
div.appendChild(document.createTextNode(d.value));
|
|
134
|
-
container.appendChild(div);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async function saveBackupConfig() {
|
|
139
|
-
try {
|
|
140
|
-
var response = await fetch('/api/backup/configure', {
|
|
141
|
-
method: 'POST',
|
|
142
|
-
headers: { 'Content-Type': 'application/json' },
|
|
143
|
-
body: JSON.stringify({
|
|
144
|
-
interval_hours: parseInt(document.getElementById('backup-interval').value),
|
|
145
|
-
max_backups: parseInt(document.getElementById('backup-max').value),
|
|
146
|
-
enabled: document.getElementById('backup-enabled').checked
|
|
147
|
-
})
|
|
148
|
-
});
|
|
149
|
-
var data = await response.json();
|
|
150
|
-
// API wraps status inside data.status on configure response
|
|
151
|
-
var status = data.status || data;
|
|
152
|
-
renderBackupStatus(status);
|
|
153
|
-
showToast('Backup settings saved');
|
|
154
|
-
} catch (error) {
|
|
155
|
-
console.error('Error saving backup config:', error);
|
|
156
|
-
showToast('Failed to save backup settings');
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async function createBackupNow() {
|
|
161
|
-
showToast('Creating backup...');
|
|
162
|
-
try {
|
|
163
|
-
var response = await fetch('/api/backup/create', { method: 'POST' });
|
|
164
|
-
var data = await response.json();
|
|
165
|
-
if (data.success) {
|
|
166
|
-
showToast('Backup created: ' + data.filename);
|
|
167
|
-
loadBackupStatus();
|
|
168
|
-
loadBackupList();
|
|
169
|
-
} else {
|
|
170
|
-
showToast('Backup failed');
|
|
171
|
-
}
|
|
172
|
-
} catch (error) {
|
|
173
|
-
console.error('Error creating backup:', error);
|
|
174
|
-
showToast('Backup failed');
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
async function loadBackupList() {
|
|
179
|
-
try {
|
|
180
|
-
var response = await fetch('/api/backup/list');
|
|
181
|
-
var data = await response.json();
|
|
182
|
-
renderBackupList(data.backups || []);
|
|
183
|
-
} catch (error) {
|
|
184
|
-
var container = document.getElementById('backup-list');
|
|
185
|
-
container.textContent = 'Backup list unavailable';
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function renderBackupList(backups) {
|
|
190
|
-
var container = document.getElementById('backup-list');
|
|
191
|
-
if (!backups || backups.length === 0) {
|
|
192
|
-
showEmpty('backup-list', 'archive', 'No backups yet. Create your first backup above.');
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
var table = document.createElement('table');
|
|
197
|
-
table.className = 'table table-sm';
|
|
198
|
-
var thead = document.createElement('thead');
|
|
199
|
-
var headRow = document.createElement('tr');
|
|
200
|
-
['Filename', 'Size', 'Age', 'Created'].forEach(function(h) {
|
|
201
|
-
var th = document.createElement('th');
|
|
202
|
-
th.textContent = h;
|
|
203
|
-
headRow.appendChild(th);
|
|
204
|
-
});
|
|
205
|
-
thead.appendChild(headRow);
|
|
206
|
-
table.appendChild(thead);
|
|
207
|
-
|
|
208
|
-
var tbody = document.createElement('tbody');
|
|
209
|
-
backups.forEach(function(b) {
|
|
210
|
-
var row = document.createElement('tr');
|
|
211
|
-
var age = b.age_hours < 48 ? Math.round(b.age_hours) + 'h ago' : Math.round(b.age_hours / 24) + 'd ago';
|
|
212
|
-
var cells = [b.filename, b.size_mb + ' MB', age, formatDateFull(b.created)];
|
|
213
|
-
cells.forEach(function(text) {
|
|
214
|
-
var td = document.createElement('td');
|
|
215
|
-
td.textContent = text;
|
|
216
|
-
row.appendChild(td);
|
|
217
|
-
});
|
|
218
|
-
tbody.appendChild(row);
|
|
219
|
-
});
|
|
220
|
-
table.appendChild(tbody);
|
|
221
|
-
|
|
222
|
-
container.textContent = '';
|
|
223
|
-
container.appendChild(table);
|
|
224
|
-
}
|
package/ui/js/timeline.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// SuperLocalMemory V2 - Timeline View (D3.js bar chart)
|
|
2
|
-
// Depends on: core.js
|
|
3
|
-
|
|
4
|
-
async function loadTimeline() {
|
|
5
|
-
showLoading('timeline-chart', 'Loading timeline...');
|
|
6
|
-
try {
|
|
7
|
-
var response = await fetch('/api/timeline?days=30');
|
|
8
|
-
var data = await response.json();
|
|
9
|
-
renderTimeline(data.timeline);
|
|
10
|
-
} catch (error) {
|
|
11
|
-
console.error('Error loading timeline:', error);
|
|
12
|
-
showEmpty('timeline-chart', 'clock-history', 'Failed to load timeline');
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function renderTimeline(timeline) {
|
|
17
|
-
var container = document.getElementById('timeline-chart');
|
|
18
|
-
if (!timeline || timeline.length === 0) {
|
|
19
|
-
showEmpty('timeline-chart', 'clock-history', 'No timeline data for the last 30 days.');
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
var margin = { top: 20, right: 20, bottom: 50, left: 50 };
|
|
23
|
-
var width = container.clientWidth - margin.left - margin.right;
|
|
24
|
-
var height = 300 - margin.top - margin.bottom;
|
|
25
|
-
container.textContent = '';
|
|
26
|
-
var svg = d3.select('#timeline-chart').append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom).append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
|
27
|
-
var x = d3.scaleBand().range([0, width]).domain(timeline.map(function(d) { return d.date || d.period; })).padding(0.1);
|
|
28
|
-
var y = d3.scaleLinear().range([height, 0]).domain([0, d3.max(timeline, function(d) { return d.count; })]);
|
|
29
|
-
svg.append('g').attr('transform', 'translate(0,' + height + ')').call(d3.axisBottom(x)).selectAll('text').attr('transform', 'rotate(-45)').style('text-anchor', 'end');
|
|
30
|
-
svg.append('g').call(d3.axisLeft(y));
|
|
31
|
-
svg.selectAll('.bar').data(timeline).enter().append('rect').attr('class', 'bar').attr('x', function(d) { return x(d.date || d.period); }).attr('y', function(d) { return y(d.count); }).attr('width', x.bandwidth()).attr('height', function(d) { return height - y(d.count); }).attr('fill', '#667eea').attr('rx', 3);
|
|
32
|
-
}
|
package/ui/js/trust-dashboard.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// SuperLocalMemory V3 — Trust Dashboard
|
|
2
|
-
// Loads and displays Bayesian trust scores per agent and per fact.
|
|
3
|
-
|
|
4
|
-
async function loadTrustDashboard() {
|
|
5
|
-
try {
|
|
6
|
-
var response = await fetch('/api/v3/trust/dashboard');
|
|
7
|
-
if (!response.ok) return;
|
|
8
|
-
var data = await response.json();
|
|
9
|
-
|
|
10
|
-
var agents = data.agents || [];
|
|
11
|
-
document.getElementById('trust-agent-count').textContent = agents.length;
|
|
12
|
-
|
|
13
|
-
var avg = agents.length > 0
|
|
14
|
-
? (agents.reduce(function(s, a) { return s + (a.trust_score || 0); }, 0) / agents.length).toFixed(3)
|
|
15
|
-
: '\u2014';
|
|
16
|
-
document.getElementById('trust-avg-score').textContent = avg;
|
|
17
|
-
document.getElementById('trust-burst-count').textContent = (data.alerts || []).length;
|
|
18
|
-
|
|
19
|
-
var tbody = document.getElementById('trust-agents-body');
|
|
20
|
-
tbody.textContent = '';
|
|
21
|
-
agents.forEach(function(a) {
|
|
22
|
-
var tr = document.createElement('tr');
|
|
23
|
-
var score = (a.trust_score || 0);
|
|
24
|
-
var badge = score >= 0.7 ? 'success' : score >= 0.3 ? 'warning' : 'danger';
|
|
25
|
-
var label = score >= 0.7 ? 'Trusted' : score >= 0.3 ? 'Neutral' : 'Low Trust';
|
|
26
|
-
|
|
27
|
-
// Target ID cell
|
|
28
|
-
var tdTarget = document.createElement('td');
|
|
29
|
-
tdTarget.textContent = a.target_id || '';
|
|
30
|
-
tr.appendChild(tdTarget);
|
|
31
|
-
|
|
32
|
-
// Type cell
|
|
33
|
-
var tdType = document.createElement('td');
|
|
34
|
-
var spanType = document.createElement('span');
|
|
35
|
-
spanType.className = 'badge bg-secondary';
|
|
36
|
-
spanType.textContent = a.target_type || '';
|
|
37
|
-
tdType.appendChild(spanType);
|
|
38
|
-
tr.appendChild(tdType);
|
|
39
|
-
|
|
40
|
-
// Trust score progress bar cell
|
|
41
|
-
var tdScore = document.createElement('td');
|
|
42
|
-
var progress = document.createElement('div');
|
|
43
|
-
progress.className = 'progress';
|
|
44
|
-
progress.style.height = '20px';
|
|
45
|
-
var bar = document.createElement('div');
|
|
46
|
-
bar.className = 'progress-bar bg-' + badge;
|
|
47
|
-
bar.style.width = Math.round(score * 100) + '%';
|
|
48
|
-
bar.textContent = score.toFixed(3);
|
|
49
|
-
progress.appendChild(bar);
|
|
50
|
-
tdScore.appendChild(progress);
|
|
51
|
-
tr.appendChild(tdScore);
|
|
52
|
-
|
|
53
|
-
// Evidence count cell
|
|
54
|
-
var tdEvidence = document.createElement('td');
|
|
55
|
-
tdEvidence.textContent = a.evidence_count || 0;
|
|
56
|
-
tr.appendChild(tdEvidence);
|
|
57
|
-
|
|
58
|
-
// Status badge cell
|
|
59
|
-
var tdStatus = document.createElement('td');
|
|
60
|
-
var spanStatus = document.createElement('span');
|
|
61
|
-
spanStatus.className = 'badge bg-' + badge;
|
|
62
|
-
spanStatus.textContent = label;
|
|
63
|
-
tdStatus.appendChild(spanStatus);
|
|
64
|
-
tr.appendChild(tdStatus);
|
|
65
|
-
|
|
66
|
-
tbody.appendChild(tr);
|
|
67
|
-
});
|
|
68
|
-
} catch (e) {
|
|
69
|
-
console.log('Trust dashboard error:', e);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
document.getElementById('trust-tab')?.addEventListener('shown.bs.tab', loadTrustDashboard);
|