superlocalmemory 3.0.17 → 3.0.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/bin/slm-npm +8 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/superlocalmemory/cli/main.py +10 -0
- package/src/superlocalmemory/core/embedding_worker.py +120 -0
- package/src/superlocalmemory/core/embeddings.py +156 -240
- package/src/superlocalmemory/core/recall_worker.py +193 -0
- package/src/superlocalmemory/core/summarizer.py +182 -0
- package/src/superlocalmemory/core/worker_pool.py +209 -0
- package/src/superlocalmemory/mcp/server.py +9 -0
- package/src/superlocalmemory/mcp/tools_core.py +21 -8
- package/src/superlocalmemory/server/routes/helpers.py +21 -0
- package/src/superlocalmemory/server/routes/memories.py +49 -33
- package/src/superlocalmemory/server/routes/v3_api.py +195 -43
- package/src/superlocalmemory/server/ui.py +15 -14
- package/src/superlocalmemory/storage/database.py +23 -0
- package/src/superlocalmemory.egg-info/PKG-INFO +1 -1
- package/src/superlocalmemory.egg-info/SOURCES.txt +4 -0
- package/ui/index.html +77 -21
- package/ui/js/auto-settings.js +330 -1
- package/ui/js/clusters.js +11 -0
- package/ui/js/graph-interactions.js +2 -5
- package/ui/js/memories.js +65 -2
- package/ui/js/modal.js +79 -42
- package/ui/js/recall-lab.js +98 -46
package/ui/js/recall-lab.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// SuperLocalMemory V3 — Recall Lab with Pagination
|
|
1
|
+
// SuperLocalMemory V3 — Recall Lab with Dual-Display + Pagination
|
|
2
2
|
// Part of Qualixar | https://superlocalmemory.com
|
|
3
3
|
|
|
4
4
|
var recallLabState = {
|
|
@@ -6,6 +6,7 @@ var recallLabState = {
|
|
|
6
6
|
page: 0,
|
|
7
7
|
perPage: 10,
|
|
8
8
|
query: '',
|
|
9
|
+
synthesis: '',
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
document.getElementById('recall-lab-search')?.addEventListener('click', function() {
|
|
@@ -16,13 +17,13 @@ document.getElementById('recall-lab-search')?.addEventListener('click', function
|
|
|
16
17
|
recallLabState.page = 0;
|
|
17
18
|
var perPageEl = document.getElementById('recall-lab-per-page');
|
|
18
19
|
recallLabState.perPage = perPageEl ? parseInt(perPageEl.value) : 10;
|
|
19
|
-
var fetchLimit = Math.max(recallLabState.perPage * 5, 50);
|
|
20
|
+
var fetchLimit = Math.max(recallLabState.perPage * 5, 50);
|
|
20
21
|
|
|
21
22
|
var resultsDiv = document.getElementById('recall-lab-results');
|
|
22
23
|
var metaDiv = document.getElementById('recall-lab-meta');
|
|
23
24
|
resultsDiv.textContent = '';
|
|
24
25
|
var spinner = document.createElement('div');
|
|
25
|
-
spinner.className = 'text-center';
|
|
26
|
+
spinner.className = 'text-center py-4';
|
|
26
27
|
var spinnerInner = document.createElement('div');
|
|
27
28
|
spinnerInner.className = 'spinner-border text-primary';
|
|
28
29
|
spinner.appendChild(spinnerInner);
|
|
@@ -31,7 +32,7 @@ document.getElementById('recall-lab-search')?.addEventListener('click', function
|
|
|
31
32
|
fetch('/api/v3/recall/trace', {
|
|
32
33
|
method: 'POST',
|
|
33
34
|
headers: {'Content-Type': 'application/json'},
|
|
34
|
-
body: JSON.stringify({query: query, limit: fetchLimit})
|
|
35
|
+
body: JSON.stringify({query: query, limit: fetchLimit, synthesize: true})
|
|
35
36
|
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
36
37
|
if (data.error) {
|
|
37
38
|
resultsDiv.textContent = '';
|
|
@@ -50,6 +51,7 @@ document.getElementById('recall-lab-search')?.addEventListener('click', function
|
|
|
50
51
|
appendMetaField(metaDiv, 'Time: ', (data.retrieval_time_ms || 0).toFixed(0) + 'ms');
|
|
51
52
|
|
|
52
53
|
recallLabState.allResults = data.results || [];
|
|
54
|
+
recallLabState.synthesis = data.synthesis || '';
|
|
53
55
|
|
|
54
56
|
if (recallLabState.allResults.length === 0) {
|
|
55
57
|
resultsDiv.textContent = '';
|
|
@@ -80,6 +82,20 @@ function renderRecallPage() {
|
|
|
80
82
|
var pageResults = results.slice(start, end);
|
|
81
83
|
var totalPages = Math.ceil(results.length / recallLabState.perPage);
|
|
82
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
|
+
|
|
83
99
|
var listGroup = document.createElement('div');
|
|
84
100
|
listGroup.className = 'list-group';
|
|
85
101
|
|
|
@@ -87,60 +103,108 @@ function renderRecallPage() {
|
|
|
87
103
|
var globalIndex = start + i;
|
|
88
104
|
var channels = r.channel_scores || {};
|
|
89
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;
|
|
90
108
|
|
|
91
109
|
var item = document.createElement('div');
|
|
92
|
-
item.className = 'list-group-item
|
|
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
|
|
93
178
|
item.style.cursor = 'pointer';
|
|
94
|
-
item.title = 'Click to view full memory';
|
|
95
179
|
(function(result) {
|
|
96
|
-
|
|
180
|
+
contentDiv.addEventListener('click', function() {
|
|
97
181
|
if (typeof openMemoryDetail === 'function') {
|
|
98
182
|
openMemoryDetail({
|
|
99
183
|
id: result.fact_id,
|
|
100
|
-
|
|
184
|
+
memory_id: result.memory_id,
|
|
185
|
+
content: result.source_content || result.content,
|
|
101
186
|
score: result.score,
|
|
102
187
|
importance: Math.round((result.confidence || 0.5) * 10),
|
|
103
188
|
category: 'recall',
|
|
104
|
-
tags: Object.keys(result.channel_scores || {}).join(', '),
|
|
105
189
|
created_at: null,
|
|
106
190
|
trust_score: result.trust_score,
|
|
107
191
|
channel_scores: result.channel_scores
|
|
108
|
-
});
|
|
192
|
+
}, 'recall'); // source='recall': show View Original, hide Expand Neighbors
|
|
109
193
|
}
|
|
110
194
|
});
|
|
111
195
|
})(r);
|
|
112
196
|
|
|
113
|
-
var header = document.createElement('h6');
|
|
114
|
-
header.className = 'mb-1';
|
|
115
|
-
header.textContent = (globalIndex + 1) + '. ' + (r.content || '').substring(0, 200);
|
|
116
|
-
item.appendChild(header);
|
|
117
|
-
|
|
118
|
-
var meta = document.createElement('small');
|
|
119
|
-
meta.className = 'text-muted';
|
|
120
|
-
meta.textContent = 'Score: ' + r.score + ' | Trust: ' + r.trust_score + ' | Confidence: ' + r.confidence;
|
|
121
|
-
item.appendChild(meta);
|
|
122
|
-
|
|
123
|
-
var barsDiv = document.createElement('div');
|
|
124
|
-
barsDiv.className = 'mt-2';
|
|
125
|
-
barsDiv.appendChild(buildChannelBar('Semantic', channels.semantic || 0, maxChannel, 'primary'));
|
|
126
|
-
barsDiv.appendChild(buildChannelBar('BM25', channels.bm25 || 0, maxChannel, 'success'));
|
|
127
|
-
barsDiv.appendChild(buildChannelBar('Entity', channels.entity_graph || 0, maxChannel, 'info'));
|
|
128
|
-
barsDiv.appendChild(buildChannelBar('Temporal', channels.temporal || 0, maxChannel, 'warning'));
|
|
129
|
-
item.appendChild(barsDiv);
|
|
130
|
-
|
|
131
197
|
listGroup.appendChild(item);
|
|
132
198
|
});
|
|
133
199
|
resultsDiv.appendChild(listGroup);
|
|
134
200
|
|
|
135
|
-
// Pagination
|
|
201
|
+
// Pagination
|
|
136
202
|
if (totalPages > 1) {
|
|
137
203
|
var nav = document.createElement('nav');
|
|
138
204
|
nav.className = 'mt-3';
|
|
139
|
-
nav.setAttribute('aria-label', 'Recall results pagination');
|
|
140
205
|
var ul = document.createElement('ul');
|
|
141
206
|
ul.className = 'pagination justify-content-center';
|
|
142
207
|
|
|
143
|
-
// Prev
|
|
144
208
|
var prevLi = document.createElement('li');
|
|
145
209
|
prevLi.className = 'page-item' + (recallLabState.page === 0 ? ' disabled' : '');
|
|
146
210
|
var prevA = document.createElement('a');
|
|
@@ -149,15 +213,11 @@ function renderRecallPage() {
|
|
|
149
213
|
prevA.textContent = 'Previous';
|
|
150
214
|
prevA.addEventListener('click', function(e) {
|
|
151
215
|
e.preventDefault();
|
|
152
|
-
if (recallLabState.page > 0) {
|
|
153
|
-
recallLabState.page--;
|
|
154
|
-
renderRecallPage();
|
|
155
|
-
}
|
|
216
|
+
if (recallLabState.page > 0) { recallLabState.page--; renderRecallPage(); }
|
|
156
217
|
});
|
|
157
218
|
prevLi.appendChild(prevA);
|
|
158
219
|
ul.appendChild(prevLi);
|
|
159
220
|
|
|
160
|
-
// Page numbers
|
|
161
221
|
for (var p = 0; p < totalPages; p++) {
|
|
162
222
|
var li = document.createElement('li');
|
|
163
223
|
li.className = 'page-item' + (p === recallLabState.page ? ' active' : '');
|
|
@@ -176,7 +236,6 @@ function renderRecallPage() {
|
|
|
176
236
|
ul.appendChild(li);
|
|
177
237
|
}
|
|
178
238
|
|
|
179
|
-
// Next
|
|
180
239
|
var nextLi = document.createElement('li');
|
|
181
240
|
nextLi.className = 'page-item' + (recallLabState.page >= totalPages - 1 ? ' disabled' : '');
|
|
182
241
|
var nextA = document.createElement('a');
|
|
@@ -185,18 +244,13 @@ function renderRecallPage() {
|
|
|
185
244
|
nextA.textContent = 'Next';
|
|
186
245
|
nextA.addEventListener('click', function(e) {
|
|
187
246
|
e.preventDefault();
|
|
188
|
-
if (recallLabState.page < totalPages - 1) {
|
|
189
|
-
recallLabState.page++;
|
|
190
|
-
renderRecallPage();
|
|
191
|
-
}
|
|
247
|
+
if (recallLabState.page < totalPages - 1) { recallLabState.page++; renderRecallPage(); }
|
|
192
248
|
});
|
|
193
249
|
nextLi.appendChild(nextA);
|
|
194
250
|
ul.appendChild(nextLi);
|
|
195
|
-
|
|
196
251
|
nav.appendChild(ul);
|
|
197
252
|
resultsDiv.appendChild(nav);
|
|
198
253
|
|
|
199
|
-
// Page info
|
|
200
254
|
var info = document.createElement('div');
|
|
201
255
|
info.className = 'text-center text-muted small';
|
|
202
256
|
info.textContent = 'Showing ' + (start + 1) + '-' + end + ' of ' + results.length + ' results';
|
|
@@ -205,8 +259,7 @@ function renderRecallPage() {
|
|
|
205
259
|
}
|
|
206
260
|
|
|
207
261
|
function appendMetaField(parent, label, value) {
|
|
208
|
-
|
|
209
|
-
parent.appendChild(text);
|
|
262
|
+
parent.appendChild(document.createTextNode(label));
|
|
210
263
|
var strong = document.createElement('strong');
|
|
211
264
|
strong.textContent = value;
|
|
212
265
|
parent.appendChild(strong);
|
|
@@ -234,7 +287,6 @@ function buildChannelBar(name, score, max, color) {
|
|
|
234
287
|
return row;
|
|
235
288
|
}
|
|
236
289
|
|
|
237
|
-
// Enter key support
|
|
238
290
|
document.getElementById('recall-lab-query')?.addEventListener('keydown', function(e) {
|
|
239
291
|
if (e.key === 'Enter') document.getElementById('recall-lab-search')?.click();
|
|
240
292
|
});
|