superlocalmemory 3.8.0 → 3.8.2
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 +112 -0
- package/README.md +32 -120
- package/package.json +9 -2
- package/plugin/.claude-plugin/plugin.json +1 -2
- package/plugin/CLAUDE.md +3 -3
- package/plugin/agents/slm-governance-advisor.md +1 -1
- package/plugin/agents/slm-loop-runner.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +2 -2
- package/plugin/agents/slm-optimize-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-cache/SKILL.md +1 -1
- package/plugin/skills/slm-compress/SKILL.md +1 -1
- package/plugin/skills/slm-governance/SKILL.md +1 -1
- package/plugin/skills/slm-graph/SKILL.md +1 -1
- package/plugin/skills/slm-loop/SKILL.md +1 -1
- package/plugin/skills/slm-mesh/SKILL.md +1 -1
- package/plugin/skills/slm-profile/SKILL.md +1 -1
- package/plugin/skills/slm-recall/SKILL.md +3 -5
- package/plugin/skills/slm-remember/SKILL.md +1 -1
- package/plugin/skills/slm-scope/SKILL.md +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin/skills/slm-status/SKILL.md +1 -1
- package/plugin-src/rules/AGENTS.md +2 -1
- package/plugin-src/skills/slm-cache/SKILL.md +1 -1
- package/plugin-src/skills/slm-compress/SKILL.md +1 -1
- package/plugin-src/skills/slm-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-recall/SKILL.md +3 -5
- package/plugin-src/skills/slm-remember/SKILL.md +1 -1
- package/plugin-src/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/skills/slm-status/SKILL.md +1 -1
- package/pyproject.toml +2 -1
- package/scripts/postinstall.js +7 -1
- package/src/superlocalmemory/__init__.py +1 -1
- package/src/superlocalmemory/cli/commands.py +494 -9
- package/src/superlocalmemory/cli/daemon.py +7 -0
- package/src/superlocalmemory/cli/loop_cmd.py +2 -7
- package/src/superlocalmemory/cli/main.py +72 -7
- package/src/superlocalmemory/cli/setup_wizard.py +142 -16
- package/src/superlocalmemory/cli/version_banner.py +17 -3
- package/src/superlocalmemory/core/backend_orchestrator.py +18 -16
- package/src/superlocalmemory/core/component_healer.py +144 -0
- package/src/superlocalmemory/core/component_registry.py +487 -0
- package/src/superlocalmemory/core/config.py +21 -0
- package/src/superlocalmemory/core/embedding_worker.py +4 -5
- package/src/superlocalmemory/core/embeddings.py +132 -45
- package/src/superlocalmemory/core/engine.py +29 -22
- package/src/superlocalmemory/core/engine_ingestion.py +332 -45
- package/src/superlocalmemory/core/ingestion_command.py +154 -25
- package/src/superlocalmemory/core/injection.py +12 -7
- package/src/superlocalmemory/core/maintenance.py +43 -0
- package/src/superlocalmemory/core/maintenance_scheduler.py +44 -6
- package/src/superlocalmemory/core/recall_pipeline.py +42 -4
- package/src/superlocalmemory/core/store_pipeline.py +195 -20
- package/src/superlocalmemory/hooks/hook_handlers.py +6 -1
- package/src/superlocalmemory/hooks/portable_kit.py +34 -2
- package/src/superlocalmemory/learning/model_rollback.py +3 -0
- package/src/superlocalmemory/learning/ranker_retrain_online.py +2 -0
- package/src/superlocalmemory/learning/reward.py +50 -0
- package/src/superlocalmemory/learning/source_quality.py +523 -1
- package/src/superlocalmemory/loops/ledger.py +25 -5
- package/src/superlocalmemory/mcp/_daemon_proxy.py +6 -2
- package/src/superlocalmemory/mcp/_pool_adapter.py +4 -1
- package/src/superlocalmemory/mcp/server.py +11 -30
- package/src/superlocalmemory/mcp/tools_active.py +1 -1
- package/src/superlocalmemory/mcp/tools_core.py +21 -5
- package/src/superlocalmemory/mcp/tools_learning.py +2 -2
- package/src/superlocalmemory/retrieval/bridge_discovery.py +14 -0
- package/src/superlocalmemory/retrieval/engine.py +53 -21
- package/src/superlocalmemory/retrieval/reranker.py +3 -4
- package/src/superlocalmemory/retrieval/spreading_activation.py +68 -38
- package/src/superlocalmemory/server/config_file.py +90 -0
- package/src/superlocalmemory/server/origin.py +50 -0
- package/src/superlocalmemory/server/routes/backup.py +293 -70
- package/src/superlocalmemory/server/routes/behavioral.py +342 -61
- package/src/superlocalmemory/server/routes/brain.py +57 -16
- package/src/superlocalmemory/server/routes/config_api.py +84 -82
- package/src/superlocalmemory/server/routes/entity.py +100 -23
- package/src/superlocalmemory/server/routes/evolution.py +103 -100
- package/src/superlocalmemory/server/routes/learning.py +286 -105
- package/src/superlocalmemory/server/routes/learning_telemetry.py +153 -0
- package/src/superlocalmemory/server/routes/memories.py +8 -3
- package/src/superlocalmemory/server/routes/mesh.py +121 -32
- package/src/superlocalmemory/server/routes/ratelimit.py +33 -25
- package/src/superlocalmemory/server/routes/stats.py +93 -155
- package/src/superlocalmemory/server/routes/token.py +3 -13
- package/src/superlocalmemory/server/routes/v3_api.py +184 -20
- package/src/superlocalmemory/server/unified_daemon.py +732 -41
- package/src/superlocalmemory/storage/embedding_migrator.py +235 -0
- package/src/superlocalmemory/storage/migration_runner.py +79 -1
- package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +5 -0
- package/src/superlocalmemory/storage/migrations/M028_fact_entity_associations.py +270 -0
- package/src/superlocalmemory/storage/migrations/M029_behavioral_history_indexes.py +137 -0
- package/src/superlocalmemory/storage/migrations/M030_entity_explorer_indexes.py +93 -0
- package/src/superlocalmemory/storage/migrations/__init__.py +4 -0
- package/src/superlocalmemory/storage/schema.py +49 -1
- package/src/superlocalmemory/storage/schema_v32.py +2 -0
- package/src/superlocalmemory/storage/schema_v347.py +4 -0
- package/src/superlocalmemory/ui/index.html +6 -8
- package/src/superlocalmemory/ui/js/core.js +52 -9
- package/src/superlocalmemory/ui/js/dashboard.js +169 -82
- package/src/superlocalmemory/ui/js/od-backup.js +156 -65
- package/src/superlocalmemory/ui/js/od-brain.js +88 -51
- package/src/superlocalmemory/ui/js/od-components.js +147 -0
- package/src/superlocalmemory/ui/js/od-entities.js +65 -22
- package/src/superlocalmemory/ui/js/od-graph.js +46 -4
- package/src/superlocalmemory/ui/js/od-health.js +18 -0
- package/src/superlocalmemory/ui/js/od-memories.js +84 -5
- package/src/superlocalmemory/ui/js/od-mesh.js +23 -9
- package/src/superlocalmemory/ui/js/od-operations.js +36 -0
- package/src/superlocalmemory/ui/js/od-settings.js +186 -63
- package/src/superlocalmemory/ui/js/od-shell.js +249 -33
- package/src/superlocalmemory/ui/js/od-skills.js +44 -17
- package/src/superlocalmemory/ui/js/settings.js +15 -1
- package/plugin-src/.mcp.json +0 -12
- package/plugin-src/agents/slm-governance-advisor.md +0 -80
- package/plugin-src/agents/slm-loop-runner.md +0 -71
- package/plugin-src/agents/slm-memory-advisor.md +0 -49
- package/plugin-src/agents/slm-optimize-advisor.md +0 -44
- package/plugin-src/commands/slm-loop.md +0 -31
- package/plugin-src/hooks/.gitkeep +0 -0
- package/plugin-src/hooks/hooks.json +0 -102
- package/plugin-src/manifest.json +0 -30
- package/plugin-src/requirements.txt +0 -1
- package/plugin-src/rules/CLAUDE.md.fragment +0 -44
- package/plugin-src/scripts/ensure-venv.bat +0 -122
- package/plugin-src/scripts/ensure-venv.sh +0 -105
- package/plugin-src/scripts/slm-launch +0 -62
- package/plugin-src/scripts/slm-launch.bat +0 -23
- package/plugin-src/settings.json +0 -25
- package/plugin-src/skills/slm-governance/SKILL.md +0 -248
- package/plugin-src/skills/slm-loop/SKILL.md +0 -99
- package/plugin-src/skills/slm-mesh/SKILL.md +0 -282
- package/plugin-src/skills/slm-profile/SKILL.md +0 -148
- package/plugin-src/skills/slm-scope/SKILL.md +0 -176
|
@@ -30,23 +30,67 @@
|
|
|
30
30
|
var _tokenCache = null;
|
|
31
31
|
|
|
32
32
|
/* ── Auth helper ──────────────────────────────────────────── */
|
|
33
|
-
function
|
|
33
|
+
function tokenError(message) {
|
|
34
|
+
var error = new Error(message);
|
|
35
|
+
error.code = 'install_token_missing';
|
|
36
|
+
return error;
|
|
37
|
+
}
|
|
38
|
+
function getToken(refresh) {
|
|
39
|
+
if (refresh) _tokenCache = null;
|
|
34
40
|
if (_tokenCache) return Promise.resolve(_tokenCache);
|
|
35
41
|
return fetch('/internal/token')
|
|
36
|
-
.then(function (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
.then(function (response) {
|
|
43
|
+
if (!response.ok) throw new Error('Could not refresh dashboard credential');
|
|
44
|
+
return response.json();
|
|
45
|
+
})
|
|
46
|
+
.then(function (data) {
|
|
47
|
+
var token = data.token || '';
|
|
48
|
+
if (!token) throw tokenError('Dashboard credential is empty');
|
|
49
|
+
_tokenCache = token;
|
|
50
|
+
return token;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function sendAuthenticated(url, method, body, token) {
|
|
54
|
+
return fetch(url, {
|
|
55
|
+
method: method,
|
|
56
|
+
headers: { 'Content-Type': 'application/json', 'X-Install-Token': token },
|
|
57
|
+
body: JSON.stringify(body)
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function requireSuccess(response) {
|
|
61
|
+
if (response.ok) return Promise.resolve(response);
|
|
62
|
+
var details = typeof response.json === 'function'
|
|
63
|
+
? response.json().catch(function () { return {}; })
|
|
64
|
+
: Promise.resolve({});
|
|
65
|
+
return details.then(function (data) {
|
|
66
|
+
var message = data.error || data.detail || data.message ||
|
|
67
|
+
('Request failed with status ' + response.status);
|
|
68
|
+
var error = new Error(message);
|
|
69
|
+
error.status = response.status;
|
|
70
|
+
throw error;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Authenticated dashboard mutation; callers must re-read daemon truth on success. */
|
|
74
|
+
function authRequest(url, method, body) {
|
|
75
|
+
function attempt(refresh) {
|
|
76
|
+
return getToken(refresh).then(function (token) {
|
|
77
|
+
return sendAuthenticated(url, method, body, token);
|
|
47
78
|
});
|
|
79
|
+
}
|
|
80
|
+
return attempt(false).then(function (response) {
|
|
81
|
+
if (response.status === 401 || response.status === 403) {
|
|
82
|
+
return attempt(true).then(requireSuccess);
|
|
83
|
+
}
|
|
84
|
+
return requireSuccess(response);
|
|
85
|
+
}, function (error) {
|
|
86
|
+
if (error && error.code === 'install_token_missing') {
|
|
87
|
+
return attempt(true).then(requireSuccess);
|
|
88
|
+
}
|
|
89
|
+
throw error;
|
|
48
90
|
});
|
|
49
91
|
}
|
|
92
|
+
function authPut(url, body) { return authRequest(url, 'PUT', body); }
|
|
93
|
+
function authPost(url, body) { return authRequest(url, 'POST', body); }
|
|
50
94
|
|
|
51
95
|
/* ── Helpers ──────────────────────────────────────────────── */
|
|
52
96
|
function esc(s) {
|
|
@@ -270,9 +314,7 @@
|
|
|
270
314
|
var ep = q('endpoint') ? q('endpoint').value : '';
|
|
271
315
|
if (k) { body.api_key = k; }
|
|
272
316
|
if (ep) { body.base_url = ep; body.endpoint = ep; }
|
|
273
|
-
|
|
274
|
-
method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body)
|
|
275
|
-
}).then(function (r) { return r.json(); })
|
|
317
|
+
authPost('/api/v3/mode/set', body).then(function (r) { return r.json(); })
|
|
276
318
|
.then(function () { setSt('mode', 'Saved', true); toast('Mode saved'); loadMode(); })
|
|
277
319
|
.catch(function () { setSt('mode', 'Error', false); toast('Mode save failed', true); });
|
|
278
320
|
}
|
|
@@ -348,10 +390,8 @@
|
|
|
348
390
|
embedding_dimension: parseInt(q('emb-dim') ? q('emb-dim').value : '768') || 768,
|
|
349
391
|
embedding_key: q('emb-key') ? q('emb-key').value : '' }
|
|
350
392
|
: { embedding_provider:'default' };
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}).then(function (r) { return r.json(); })
|
|
354
|
-
.then(function () { setSt('emb', 'Saved', true); toast('Embedding config saved'); })
|
|
393
|
+
authPost('/api/v3/mode/set', body).then(function (r) { return r.json(); })
|
|
394
|
+
.then(function () { setSt('emb', 'Saved', true); toast('Embedding config saved'); loadEmb(); })
|
|
355
395
|
.catch(function () { setSt('emb', 'Error', false); toast('Embedding save failed', true); });
|
|
356
396
|
}
|
|
357
397
|
function testEmb() {
|
|
@@ -418,6 +458,7 @@
|
|
|
418
458
|
setSt('stor', 'Saved', true);
|
|
419
459
|
toast('Storage backends saved');
|
|
420
460
|
showRestartNote('stor', !!d.restart_required);
|
|
461
|
+
loadStorage();
|
|
421
462
|
}).catch(function () { setSt('stor', 'Error', false); toast('Storage save failed', true); });
|
|
422
463
|
}
|
|
423
464
|
|
|
@@ -442,6 +483,7 @@
|
|
|
442
483
|
}).then(function (r) { return r.json(); })
|
|
443
484
|
.then(function (d) {
|
|
444
485
|
setSt('scope', d.success !== false ? 'Applied' : esc(d.error || 'Error'), d.success !== false);
|
|
486
|
+
if (d.success !== false) loadScope();
|
|
445
487
|
})
|
|
446
488
|
.catch(function () { setSt('scope', 'Error', false); toast('Scope save failed', true); });
|
|
447
489
|
}
|
|
@@ -467,6 +509,75 @@
|
|
|
467
509
|
}).catch(function () {});
|
|
468
510
|
}
|
|
469
511
|
|
|
512
|
+
/* ═══════════════════════════════════════════════════════════
|
|
513
|
+
GROUP — Recall & Memory Behaviour (v3.8.2, live-apply, no restart)
|
|
514
|
+
PUT /api/v3/runtime/config {retrieval:{top_k,use_cross_encoder},
|
|
515
|
+
injection:{enabled,core_block_enabled,
|
|
516
|
+
core_block_max_facts}}
|
|
517
|
+
═══════════════════════════════════════════════════════════ */
|
|
518
|
+
function buildRuntime() {
|
|
519
|
+
var topkWrap = makeRange('rt-topk', 1, 200, 1, 20);
|
|
520
|
+
var topkInp = topkWrap.querySelector('input');
|
|
521
|
+
var xencSw = makeSwitch('rt-xenc', true);
|
|
522
|
+
var injSw = makeSwitch('rt-inj', true);
|
|
523
|
+
var cbSw = makeSwitch('rt-cb', true);
|
|
524
|
+
var cbWrap = makeRange('rt-cbmax', 0, 50, 1, 5);
|
|
525
|
+
var cbInp = cbWrap.querySelector('input');
|
|
526
|
+
var st = makeSt('rt');
|
|
527
|
+
function save() {
|
|
528
|
+
authPut('/api/v3/runtime/config', {
|
|
529
|
+
retrieval: {
|
|
530
|
+
top_k: Number(topkInp.value),
|
|
531
|
+
use_cross_encoder: xencSw.classList.contains('on')
|
|
532
|
+
},
|
|
533
|
+
injection: {
|
|
534
|
+
enabled: injSw.classList.contains('on'),
|
|
535
|
+
core_block_enabled: cbSw.classList.contains('on'),
|
|
536
|
+
core_block_max_facts: Number(cbInp.value)
|
|
537
|
+
}
|
|
538
|
+
}).then(function (r) { return r.json(); })
|
|
539
|
+
.then(function (d) {
|
|
540
|
+
setSt('rt', d.success !== false ? 'Applied' : esc(d.error || 'Error'), d.success !== false);
|
|
541
|
+
if (d.success !== false) loadRuntime();
|
|
542
|
+
})
|
|
543
|
+
.catch(function () { setSt('rt', 'Error', false); toast('Save failed', true); });
|
|
544
|
+
}
|
|
545
|
+
// Ranges save on release ('change'), not each drag tick ('input').
|
|
546
|
+
topkInp.addEventListener('change', save);
|
|
547
|
+
cbInp.addEventListener('change', save);
|
|
548
|
+
xencSw.addEventListener('od-toggle', save);
|
|
549
|
+
injSw.addEventListener('od-toggle', save);
|
|
550
|
+
cbSw.addEventListener('od-toggle', save);
|
|
551
|
+
return makeGrp('Recall & Memory Behaviour (auto-saves, no restart)', 'operations', [
|
|
552
|
+
makeRow('Recall depth', 'Memories each recall considers — higher is more thorough, a little slower', 'retrieval.top_k', topkWrap),
|
|
553
|
+
makeRow('Reranker', 'Re-scores results for quality (uses ~200MB RAM, adds ~200ms)', 'retrieval.use_cross_encoder', xencSw),
|
|
554
|
+
makeRow('Inject memories into prompts', 'Master switch for automatic memory injection', 'injection.enabled', injSw),
|
|
555
|
+
makeRow('Core-memory block', 'Prepend your most important facts to every prompt', 'injection.core_block_enabled', cbSw),
|
|
556
|
+
makeRow('Core-block size', 'Max facts in the core-memory block', 'injection.core_block_max_facts', cbWrap),
|
|
557
|
+
makeRow('Status', '', '', st)
|
|
558
|
+
]);
|
|
559
|
+
}
|
|
560
|
+
function loadRuntime() {
|
|
561
|
+
fetch('/api/v3/runtime/config').then(function (r) { return r.ok ? r.json() : null; })
|
|
562
|
+
.then(function (d) {
|
|
563
|
+
if (!d || !d.config) return;
|
|
564
|
+
var rt = d.config.retrieval || {}, inj = d.config.injection || {};
|
|
565
|
+
function setRange(id, val) {
|
|
566
|
+
var i = q(id); if (i == null) return;
|
|
567
|
+
i.value = val; var disp = q(id + '-disp'); if (disp) disp.textContent = val;
|
|
568
|
+
}
|
|
569
|
+
function setSw(id, on) {
|
|
570
|
+
var s = q(id); if (!s) return;
|
|
571
|
+
s.classList.toggle('on', !!on); s.setAttribute('aria-checked', String(!!on));
|
|
572
|
+
}
|
|
573
|
+
if (rt.top_k != null) setRange('rt-topk', rt.top_k);
|
|
574
|
+
setSw('rt-xenc', rt.use_cross_encoder);
|
|
575
|
+
setSw('rt-inj', inj.enabled);
|
|
576
|
+
setSw('rt-cb', inj.core_block_enabled);
|
|
577
|
+
if (inj.core_block_max_facts != null) setRange('rt-cbmax', inj.core_block_max_facts);
|
|
578
|
+
}).catch(function () {});
|
|
579
|
+
}
|
|
580
|
+
|
|
470
581
|
/* ═══════════════════════════════════════════════════════════
|
|
471
582
|
GROUP 5 — Auto-Capture
|
|
472
583
|
═══════════════════════════════════════════════════════════ */
|
|
@@ -481,9 +592,9 @@
|
|
|
481
592
|
capture_decisions: swDec.classList.contains('on'),
|
|
482
593
|
capture_bugs: swBug.classList.contains('on')
|
|
483
594
|
});
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
595
|
+
authPut('/api/v3/auto-capture/config', body)
|
|
596
|
+
.then(function (r) { if (!r.ok) throw new Error('Save failed'); loadCapture(); })
|
|
597
|
+
.catch(function () { toast('Auto-capture save failed', true); });
|
|
487
598
|
}
|
|
488
599
|
sw.addEventListener('od-toggle', save);
|
|
489
600
|
swDec.addEventListener('od-toggle', save);
|
|
@@ -516,13 +627,11 @@
|
|
|
516
627
|
var sw = makeSwitch('rec-en', true);
|
|
517
628
|
var swSess = makeSwitch('rec-sess', true);
|
|
518
629
|
function save() {
|
|
519
|
-
|
|
520
|
-
method:'PUT', headers:{'Content-Type':'application/json'},
|
|
521
|
-
body:JSON.stringify({
|
|
630
|
+
authPut('/api/v3/auto-recall/config', {
|
|
522
631
|
enabled: sw.classList.contains('on'),
|
|
523
632
|
on_session_start: swSess.classList.contains('on')
|
|
524
|
-
})
|
|
525
|
-
|
|
633
|
+
}).then(function (r) { if (!r.ok) throw new Error('Save failed'); loadRecall(); })
|
|
634
|
+
.catch(function () { toast('Auto-recall save failed', true); });
|
|
526
635
|
}
|
|
527
636
|
sw.addEventListener('od-toggle', save);
|
|
528
637
|
swSess.addEventListener('od-toggle', save);
|
|
@@ -552,15 +661,12 @@
|
|
|
552
661
|
var arSw = makeSwitch('ai-actr', false);
|
|
553
662
|
var st = makeSt('ai');
|
|
554
663
|
function save() {
|
|
555
|
-
|
|
556
|
-
method:'PUT', headers:{'Content-Type':'application/json'},
|
|
557
|
-
body:JSON.stringify({
|
|
664
|
+
authPut('/api/v3/auto-invoke/config', {
|
|
558
665
|
enabled: sw.classList.contains('on'),
|
|
559
666
|
min_score: parseFloat(q('ai-fok') ? q('ai-fok').value : '0.12'),
|
|
560
667
|
act_r_mode: arSw.classList.contains('on')
|
|
561
|
-
})
|
|
562
|
-
|
|
563
|
-
.then(function () { setSt('ai', 'Saved', true); })
|
|
668
|
+
}).then(function (r) { return r.json(); })
|
|
669
|
+
.then(function () { setSt('ai', 'Saved', true); loadInvoke(); })
|
|
564
670
|
.catch(function () { toast('Auto-invoke save failed', true); });
|
|
565
671
|
}
|
|
566
672
|
sw.addEventListener('od-toggle', save);
|
|
@@ -602,6 +708,7 @@
|
|
|
602
708
|
{ fontSize:'12px', color:'var(--fg-2)', fontFamily:'var(--font-mono)' });
|
|
603
709
|
var saveBtn = makeBtn('forg-save', 'Save Forgetting', true);
|
|
604
710
|
var st = makeSt('forg');
|
|
711
|
+
var restNote = makeRestartNote('forg');
|
|
605
712
|
saveBtn.addEventListener('click', saveForgetting);
|
|
606
713
|
onSw.addEventListener('od-toggle', saveForgetting);
|
|
607
714
|
immSw.addEventListener('od-toggle', saveForgetting);
|
|
@@ -615,7 +722,7 @@
|
|
|
615
722
|
makeRow('Forget threshold', 'Memories below this strength are permanently deleted', 'forgetting.forget_threshold', fgtR),
|
|
616
723
|
makeRow('Run every (minutes)', 'How often the forgetting engine runs in the background', 'forgetting.scheduler_interval_minutes', intInp),
|
|
617
724
|
makeRow('Memory zone stats', '', 'forgetting.stats', statsEl),
|
|
618
|
-
makeRow('Actions', '', '', bRow(saveBtn, st))
|
|
725
|
+
makeRow('Actions', '', '', bRow(saveBtn, st, restNote))
|
|
619
726
|
]);
|
|
620
727
|
}
|
|
621
728
|
function loadForgetting() {
|
|
@@ -647,6 +754,7 @@
|
|
|
647
754
|
}
|
|
648
755
|
function saveForgetting() {
|
|
649
756
|
setSt('forg', 'Saving…', null);
|
|
757
|
+
showRestartNote('forg', false);
|
|
650
758
|
authPut('/api/v3/forgetting/config', {
|
|
651
759
|
enabled: q('forg-en') ? q('forg-en').classList.contains('on') : false,
|
|
652
760
|
core_memory_immune: q('forg-imm') ? q('forg-imm').classList.contains('on') : true,
|
|
@@ -654,7 +762,12 @@
|
|
|
654
762
|
forget_threshold: parseFloat(q('forg-fgt') ? q('forg-fgt').value : '0.05'),
|
|
655
763
|
scheduler_interval_minutes: parseInt(q('forg-int') ? q('forg-int').value : '30') || 30
|
|
656
764
|
}).then(function (r) { return r.json(); })
|
|
657
|
-
.then(function () {
|
|
765
|
+
.then(function (d) {
|
|
766
|
+
setSt('forg', 'Saved', true);
|
|
767
|
+
toast('Forgetting settings saved');
|
|
768
|
+
showRestartNote('forg', !!d.restart_required);
|
|
769
|
+
loadForgetting();
|
|
770
|
+
})
|
|
658
771
|
.catch(function () { setSt('forg', 'Error', false); toast('Forgetting save failed', true); });
|
|
659
772
|
}
|
|
660
773
|
|
|
@@ -673,7 +786,7 @@
|
|
|
673
786
|
var st = makeSt('evo');
|
|
674
787
|
sw.addEventListener('od-toggle', function () {
|
|
675
788
|
var on = sw.classList.contains('on');
|
|
676
|
-
|
|
789
|
+
authPost(on ? '/api/evolution/enable' : '/api/evolution/disable', {})
|
|
677
790
|
.then(function (r) { return r.json(); })
|
|
678
791
|
.then(function (d) {
|
|
679
792
|
if (d.ok === false) {
|
|
@@ -692,11 +805,9 @@
|
|
|
692
805
|
});
|
|
693
806
|
saveBtn.addEventListener('click', function () {
|
|
694
807
|
setSt('evo', 'Saving…', null);
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}).then(function (r) { return r.json(); })
|
|
699
|
-
.then(function () { setSt('evo', 'Saved', true); })
|
|
808
|
+
authPost('/api/evolution/config', { backend: q('evo-bk') ? q('evo-bk').value : 'auto' })
|
|
809
|
+
.then(function (r) { return r.json(); })
|
|
810
|
+
.then(function (d) { if (d.ok === false) throw new Error(d.error || 'Save failed'); setSt('evo', 'Saved', true); loadEvolution(); })
|
|
700
811
|
.catch(function () { setSt('evo', 'Error', false); toast('Evolution save failed', true); });
|
|
701
812
|
});
|
|
702
813
|
return makeGrp('Skill Evolution', 'skill', [
|
|
@@ -731,7 +842,7 @@
|
|
|
731
842
|
saveBtn.addEventListener('click', saveBackupConfig);
|
|
732
843
|
nowBtn.addEventListener('click', function () {
|
|
733
844
|
setSt('bk', 'Creating…', null);
|
|
734
|
-
|
|
845
|
+
authPost('/api/backup/create', {}).then(function (r) { return r.json(); })
|
|
735
846
|
.then(function (d) {
|
|
736
847
|
setSt('bk', d.success ? 'Done: ' + esc(d.filename || '') : 'Failed', d.success);
|
|
737
848
|
toast(d.success ? 'Backup created' : 'Backup failed', !d.success);
|
|
@@ -768,15 +879,12 @@
|
|
|
768
879
|
}
|
|
769
880
|
function saveBackupConfig() {
|
|
770
881
|
setSt('bk', 'Saving…', null);
|
|
771
|
-
|
|
772
|
-
method:'POST', headers:{'Content-Type':'application/json'},
|
|
773
|
-
body:JSON.stringify({
|
|
882
|
+
authPost('/api/backup/configure', {
|
|
774
883
|
interval_hours: parseInt(q('bk-int') ? q('bk-int').value : '168'),
|
|
775
884
|
max_backups: parseInt(q('bk-max') ? q('bk-max').value : '10'),
|
|
776
885
|
enabled: q('bk-en') ? q('bk-en').classList.contains('on') : true
|
|
777
|
-
})
|
|
778
|
-
|
|
779
|
-
.then(function () { setSt('bk', 'Saved', true); toast('Backup settings saved'); })
|
|
886
|
+
}).then(function (r) { return r.json(); })
|
|
887
|
+
.then(function (d) { if (d.success === false) throw new Error(d.message || 'Save failed'); setSt('bk', 'Saved', true); toast('Backup settings saved'); loadBackup(); })
|
|
780
888
|
.catch(function () { setSt('bk', 'Error', false); toast('Backup save failed', true); });
|
|
781
889
|
}
|
|
782
890
|
|
|
@@ -787,15 +895,24 @@
|
|
|
787
895
|
function buildMesh() {
|
|
788
896
|
var sw = makeSwitch('mesh-en', false);
|
|
789
897
|
var st = makeSt('mesh');
|
|
898
|
+
var restNote = makeRestartNote('mesh');
|
|
790
899
|
sw.addEventListener('od-toggle', function () {
|
|
900
|
+
showRestartNote('mesh', false);
|
|
791
901
|
authPut('/api/v3/mesh/config', { enabled: sw.classList.contains('on') })
|
|
792
902
|
.then(function (r) { return r.json(); })
|
|
793
|
-
.then(function () {
|
|
794
|
-
|
|
903
|
+
.then(function (d) {
|
|
904
|
+
setSt('mesh', 'Saved', true);
|
|
905
|
+
showRestartNote('mesh', !!d.restart_required);
|
|
906
|
+
})
|
|
907
|
+
.catch(function () {
|
|
908
|
+
setSt('mesh', 'Error', false);
|
|
909
|
+
toast('Mesh save failed', true);
|
|
910
|
+
loadMesh();
|
|
911
|
+
});
|
|
795
912
|
});
|
|
796
913
|
return makeGrp('Mesh Network', 'mesh', [
|
|
797
914
|
makeRow('Enable mesh sync', 'Synchronise memories across devices on the same local network', 'mesh.enabled', sw),
|
|
798
|
-
makeRow('Status', '', '', st)
|
|
915
|
+
makeRow('Status', '', '', bRow(st, restNote))
|
|
799
916
|
]);
|
|
800
917
|
}
|
|
801
918
|
function loadMesh() {
|
|
@@ -817,6 +934,7 @@
|
|
|
817
934
|
var pmR = makeRange('trust-pm', '0', '1', '0.01', '0.5');
|
|
818
935
|
var saveBtn = makeBtn('trust-save', 'Save Trust', true);
|
|
819
936
|
var st = makeSt('trust');
|
|
937
|
+
var restNote = makeRestartNote('trust');
|
|
820
938
|
saveBtn.addEventListener('click', saveTrust);
|
|
821
939
|
twSw.addEventListener('od-toggle', saveTrust);
|
|
822
940
|
fpSw.addEventListener('od-toggle', saveTrust);
|
|
@@ -825,7 +943,7 @@
|
|
|
825
943
|
makeRow('Weight recall by trust', 'Higher-trust sources appear first in recall results', 'trust.use_trust_weighting', twSw),
|
|
826
944
|
makeRow('Prefer first-party agents', 'Your own Claude/Gemini sessions rank higher than third-party', 'trust.trust_first_party', fpSw),
|
|
827
945
|
makeRow('Promotion min trust', 'Min trust score required to promote a memory to long-term storage', 'trust.promotion_min_trust', pmR),
|
|
828
|
-
makeRow('Actions', '', '', bRow(saveBtn, st))
|
|
946
|
+
makeRow('Actions', '', '', bRow(saveBtn, st, restNote))
|
|
829
947
|
]);
|
|
830
948
|
}
|
|
831
949
|
function loadTrust() {
|
|
@@ -842,12 +960,17 @@
|
|
|
842
960
|
}
|
|
843
961
|
function saveTrust() {
|
|
844
962
|
setSt('trust', 'Saving…', null);
|
|
963
|
+
showRestartNote('trust', false);
|
|
845
964
|
authPut('/api/v3/trust/config', {
|
|
846
965
|
use_trust_weighting: q('trust-tw') ? q('trust-tw').classList.contains('on') : true,
|
|
847
966
|
trust_first_party: q('trust-fp') ? q('trust-fp').classList.contains('on') : false,
|
|
848
967
|
promotion_min_trust: parseFloat(q('trust-pm') ? q('trust-pm').value : '0.5')
|
|
849
968
|
}).then(function (r) { return r.json(); })
|
|
850
|
-
.then(function () {
|
|
969
|
+
.then(function (d) {
|
|
970
|
+
setSt('trust', 'Saved', true);
|
|
971
|
+
showRestartNote('trust', !!d.restart_required);
|
|
972
|
+
loadTrust();
|
|
973
|
+
})
|
|
851
974
|
.catch(function () { setSt('trust', 'Error', false); toast('Trust save failed', true); });
|
|
852
975
|
}
|
|
853
976
|
|
|
@@ -899,7 +1022,7 @@
|
|
|
899
1022
|
read: parseInt(q('rl-read') ? q('rl-read').value : '300') || 300,
|
|
900
1023
|
window: parseInt(q('rl-window') ? q('rl-window').value : '60') || 60
|
|
901
1024
|
}).then(function (r) { return r.json(); })
|
|
902
|
-
.then(function (d) { setSt('rl', 'Saved', true); _rlSetLb(d); })
|
|
1025
|
+
.then(function (d) { setSt('rl', 'Saved', true); _rlSetLb(d); loadRateLimit(); })
|
|
903
1026
|
.catch(function () { setSt('rl', 'Error', false); toast('Rate limit save failed', true); });
|
|
904
1027
|
}
|
|
905
1028
|
|
|
@@ -952,6 +1075,7 @@
|
|
|
952
1075
|
setSt('dmn', 'Saved', true);
|
|
953
1076
|
toast('Daemon settings saved');
|
|
954
1077
|
showRestartNote('dmn', !!d.restart_required);
|
|
1078
|
+
loadDaemon();
|
|
955
1079
|
}).catch(function () { setSt('dmn', 'Error', false); toast('Daemon save failed', true); });
|
|
956
1080
|
}
|
|
957
1081
|
|
|
@@ -971,8 +1095,8 @@
|
|
|
971
1095
|
});
|
|
972
1096
|
}
|
|
973
1097
|
function loadAll() {
|
|
974
|
-
loadMode(); loadEmb(); loadStorage(); loadScope();
|
|
975
|
-
loadRecall(); loadInvoke(); loadForgetting(); loadEvolution();
|
|
1098
|
+
loadMode(); loadEmb(); loadStorage(); loadScope(); loadRuntime();
|
|
1099
|
+
loadCapture(); loadRecall(); loadInvoke(); loadForgetting(); loadEvolution();
|
|
976
1100
|
loadBackup(); loadMesh(); loadTrust(); loadRateLimit(); loadDaemon();
|
|
977
1101
|
}
|
|
978
1102
|
|
|
@@ -992,7 +1116,7 @@
|
|
|
992
1116
|
var headDiv = el('div', null, { marginBottom:'22px' });
|
|
993
1117
|
headDiv.appendChild(el('h2', { text:'Settings' },
|
|
994
1118
|
{ fontSize:'22px', fontWeight:'650', letterSpacing:'-0.02em' }));
|
|
995
|
-
headDiv.appendChild(el('p', { text:'Every SuperLocalMemory configuration, grouped and searchable — no config files to edit by hand.
|
|
1119
|
+
headDiv.appendChild(el('p', { text:'Every SuperLocalMemory configuration, grouped and searchable — no config files to edit by hand. Settings show when a daemon restart is required.' },
|
|
996
1120
|
{ color:'var(--fg-2)', marginTop:'5px', maxWidth:'62ch' }));
|
|
997
1121
|
hub.appendChild(headDiv);
|
|
998
1122
|
|
|
@@ -1007,7 +1131,7 @@
|
|
|
1007
1131
|
hub.appendChild(sWrap);
|
|
1008
1132
|
|
|
1009
1133
|
var frag = document.createDocumentFragment();
|
|
1010
|
-
[buildMode(), buildEmb(), buildStorage(), buildScope(),
|
|
1134
|
+
[buildMode(), buildEmb(), buildStorage(), buildScope(), buildRuntime(),
|
|
1011
1135
|
buildCapture(), buildRecall(), buildInvoke(), buildForgetting(),
|
|
1012
1136
|
buildEvolution(), buildBackup(), buildMesh(), buildTrust(),
|
|
1013
1137
|
buildRateLimit(), buildDaemon()
|
|
@@ -1022,15 +1146,14 @@
|
|
|
1022
1146
|
var discardBtn = el('button', { type:'button' }); discardBtn.className = 'btn ghost';
|
|
1023
1147
|
discardBtn.textContent = 'Discard';
|
|
1024
1148
|
var syncBadge = el('span', null, { alignSelf:'center', marginLeft:'auto' });
|
|
1025
|
-
syncBadge.className = 'badge
|
|
1026
|
-
syncBadge.innerHTML = '<span class="dot"></span>
|
|
1149
|
+
syncBadge.className = 'badge';
|
|
1150
|
+
syncBadge.innerHTML = '<span class="dot"></span> Ready';
|
|
1027
1151
|
saveAllBtn.addEventListener('click', function () {
|
|
1028
1152
|
['mode-save','emb-save','stor-save','forg-save','trust-save','rl-save','evo-save','bk-save','dmn-save']
|
|
1029
1153
|
.forEach(function (i) { var b = q(i); if (b) b.click(); });
|
|
1030
1154
|
saveBackupConfig();
|
|
1031
|
-
syncBadge.className = 'badge
|
|
1032
|
-
syncBadge.innerHTML = '<span class="dot"></span>
|
|
1033
|
-
setTimeout(function () { syncBadge.innerHTML = '<span class="dot"></span> All synced'; }, 3000);
|
|
1155
|
+
syncBadge.className = 'badge';
|
|
1156
|
+
syncBadge.innerHTML = '<span class="dot"></span> Check each section';
|
|
1034
1157
|
});
|
|
1035
1158
|
discardBtn.addEventListener('click', function () { loadAll(); });
|
|
1036
1159
|
foot.appendChild(saveAllBtn); foot.appendChild(discardBtn); foot.appendChild(syncBadge);
|