pi-mega-compact 0.13.4 → 0.13.6
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/README.md +11 -8
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +50 -0
- package/dist/extensions/dashboard-server/api-contracts/rag-metrics.js +1 -0
- package/dist/extensions/dashboard-server/api-contracts/rag-settings.js +3 -3
- package/dist/extensions/dashboard-server/api-contracts/wiki.js +1 -0
- package/dist/extensions/dashboard-server/routes-rag-metrics.js +60 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +167 -0
- package/dist/extensions/dashboard-server/routes-rag-settings.js +136 -77
- package/dist/extensions/dashboard-server/routes-wiki-helpers.js +97 -0
- package/dist/extensions/dashboard-server/routes-wiki.js +330 -0
- package/dist/extensions/dashboard-server/routes.js +2 -0
- package/dist/extensions/dashboard-server/server.js +17 -3
- package/dist/extensions/mega-events/context-handler/afterCompact.js +35 -2
- package/dist/extensions/mega-pipeline/recall.js +31 -0
- package/dist/extensions/mega-turn-store.js +2 -1
- package/dist/src/config/turns.js +10 -0
- package/dist/src/config.js +2 -0
- package/dist/src/recall/async.js +10 -1
- package/dist/src/recall/format.js +10 -1
- package/dist/src/recall/hydeTelemetry.js +22 -0
- package/dist/src/recall/sync.js +28 -2
- package/dist/src/store/turns/hydeStore.js +32 -0
- package/dist/src/store/turns/index.js +1 -0
- package/dist/src/store/turns/schema.js +102 -1
- package/dist/src/store/turns/sqlite-store/rows.js +23 -0
- package/dist/src/store/turns/sqlite-store/write.js +7 -3
- package/dist/src/topics/durability.js +187 -0
- package/dist/src/topics/index.js +2 -1
- package/dist/src/topics/store.js +28 -9
- package/dist/src/wiki/curation-helpers.js +71 -0
- package/dist/src/wiki/curation.js +147 -0
- package/dist/src/wiki/incremental.js +126 -0
- package/dist/src/wiki/index.js +5 -0
- package/extensions/dashboard-client/dist/assets/AreaChart-KAmp_6bL.js +70 -0
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C30AwyoF.js.map → AreaChart-KAmp_6bL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-Bk-gm-R0.js +2 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-Bk-gm-R0.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-Cyylo0of.js +2 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-Cyylo0of.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-D-IzmV29.js +2 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-D-IzmV29.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-CrlkCFVj.js +2 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-CrlkCFVj.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DHUdZ7RR.js +2 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DHUdZ7RR.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-B7I4HWVg.js +2 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-B7I4HWVg.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-K6j4ZI7u.js +2 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-K6j4ZI7u.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-BSRWhn56.js +2 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-BSRWhn56.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/SessionsTab-BXdizHN1.js +2 -0
- package/extensions/dashboard-client/dist/assets/SessionsTab-BXdizHN1.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CAgyfqY3.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CAgyfqY3.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-DwgCzPD9.js +2 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-DwgCzPD9.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TurnsTab-CVKcStBp.js +5 -0
- package/extensions/dashboard-client/dist/assets/TurnsTab-CVKcStBp.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-BNohxTbs.js +2 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-BNohxTbs.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/button-B4A-_dCA.js +2 -0
- package/extensions/dashboard-client/dist/assets/button-B4A-_dCA.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/card-Cjn7Ifoe.js +2 -0
- package/extensions/dashboard-client/dist/assets/card-Cjn7Ifoe.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-CQjCLvv7.js +137 -0
- package/extensions/dashboard-client/dist/assets/index-CQjCLvv7.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +1 -0
- package/extensions/dashboard-client/dist/assets/switch-CcdXX0Zm.js +2 -0
- package/extensions/dashboard-client/dist/assets/switch-CcdXX0Zm.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/toggle-KdBnFLu3.js +2 -0
- package/extensions/dashboard-client/dist/assets/toggle-KdBnFLu3.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js → useSSE-B6t44vzc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js.map → useSSE-B6t44vzc.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/package-lock.json +1995 -191
- package/extensions/dashboard-client/package.json +12 -1
- package/extensions/dashboard-client/postcss.config.js +6 -0
- package/extensions/dashboard-client/src/App.tsx +127 -88
- package/extensions/dashboard-client/src/api/client.ts +109 -10
- package/extensions/dashboard-client/src/components/ActiveReposTable.tsx +15 -7
- package/extensions/dashboard-client/src/components/ActiveSessionsTable.tsx +67 -55
- package/extensions/dashboard-client/src/components/CacheHitRateTrendCard.tsx +17 -13
- package/extensions/dashboard-client/src/components/CacheHitsCard.tsx +35 -30
- package/extensions/dashboard-client/src/components/CacheStatusPerModel.tsx +33 -28
- package/extensions/dashboard-client/src/components/EventCategoryFilter.tsx +5 -6
- package/extensions/dashboard-client/src/components/EventStream.tsx +17 -13
- package/extensions/dashboard-client/src/components/HydeDetailPanel.tsx +173 -0
- package/extensions/dashboard-client/src/components/LegendCard.tsx +16 -9
- package/extensions/dashboard-client/src/components/PerfCards.tsx +28 -20
- package/extensions/dashboard-client/src/components/PerfChart.tsx +9 -6
- package/extensions/dashboard-client/src/components/ProviderCacheCard.tsx +15 -7
- package/extensions/dashboard-client/src/components/RagDashboard.tsx +253 -0
- package/extensions/dashboard-client/src/components/RepoAllSessionsCard.tsx +15 -10
- package/extensions/dashboard-client/src/components/RepoContextStack.tsx +24 -16
- package/extensions/dashboard-client/src/components/RepoDetailModal.tsx +52 -49
- package/extensions/dashboard-client/src/components/RepoTable.tsx +26 -17
- package/extensions/dashboard-client/src/components/SessionContextGauges.tsx +11 -14
- package/extensions/dashboard-client/src/components/SessionInfo.tsx +20 -15
- package/extensions/dashboard-client/src/components/SessionsMemoryChart.tsx +8 -5
- package/extensions/dashboard-client/src/components/SummaryTiles.tsx +26 -17
- package/extensions/dashboard-client/src/components/TabBar.tsx +1 -3
- package/extensions/dashboard-client/src/components/layout/AppShell.tsx +42 -0
- package/extensions/dashboard-client/src/components/layout/BottomBar.tsx +88 -0
- package/extensions/dashboard-client/src/components/layout/Sidebar.tsx +83 -0
- package/extensions/dashboard-client/src/components/ui/badge.tsx +30 -0
- package/extensions/dashboard-client/src/components/ui/button.tsx +44 -0
- package/extensions/dashboard-client/src/components/ui/card.tsx +32 -0
- package/extensions/dashboard-client/src/components/ui/select.tsx +64 -0
- package/extensions/dashboard-client/src/components/ui/switch.tsx +26 -0
- package/extensions/dashboard-client/src/components/ui/tabs.tsx +36 -0
- package/extensions/dashboard-client/src/components/ui/toggle.tsx +28 -0
- package/extensions/dashboard-client/src/components/ui/tooltip.tsx +27 -0
- package/extensions/dashboard-client/src/config.ts +10 -0
- package/extensions/dashboard-client/src/main.tsx +2 -2
- package/extensions/dashboard-client/src/memory-map-layout.ts +1 -2
- package/extensions/dashboard-client/src/styles/index.css +79 -0
- package/extensions/dashboard-client/src/tabs/CacheTab.tsx +33 -26
- package/extensions/dashboard-client/src/tabs/EventsTab.tsx +22 -7
- package/extensions/dashboard-client/src/tabs/HealthTab.tsx +77 -46
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/ActionsCard.tsx +60 -50
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/DbStatsCard.tsx +61 -35
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/DebugBundleCard.tsx +34 -23
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/HealthMitigationCard.tsx +62 -43
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/SchemaHealthCard.tsx +53 -32
- package/extensions/dashboard-client/src/tabs/MaintenanceTab.tsx +2 -2
- package/extensions/dashboard-client/src/tabs/MemoryMapTab/MemoryMapView.tsx +29 -46
- package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +10 -34
- package/extensions/dashboard-client/src/tabs/MemoryMapTab.tsx +14 -34
- package/extensions/dashboard-client/src/tabs/MetricsTab.tsx +5 -2
- package/extensions/dashboard-client/src/tabs/OverviewTab.tsx +11 -5
- package/extensions/dashboard-client/src/tabs/ReposTab.tsx +5 -5
- package/extensions/dashboard-client/src/tabs/SessionsTab.tsx +47 -33
- package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetup.tsx +6 -2
- package/extensions/dashboard-client/src/tabs/SetupTab/RagHealthCard.tsx +78 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/SettingsPanel.tsx +198 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/SettingsSection.tsx +50 -0
- package/extensions/dashboard-client/src/tabs/SetupTab.tsx +21 -59
- package/extensions/dashboard-client/src/tabs/TopicsTab.tsx +75 -40
- package/extensions/dashboard-client/src/tabs/TurnsTab.tsx +150 -112
- package/extensions/dashboard-client/src/tabs/WikiTab/TopicEvolutionGraph.tsx +274 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/TopicEvolutionView.tsx +71 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/TopicTimeline.tsx +103 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/WikiPage.tsx +213 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/WikiPageControls.tsx +188 -0
- package/extensions/dashboard-client/src/tabs/WikiTab.tsx +222 -0
- package/extensions/dashboard-client/src/tabs/registry.ts +57 -0
- package/extensions/dashboard-client/src/utils/cn.ts +7 -0
- package/extensions/dashboard-client/tailwind.config.js +46 -0
- package/extensions/dashboard-server/api-contracts/core.ts +59 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +79 -0
- package/extensions/dashboard-server/api-contracts/index.ts +48 -2
- package/extensions/dashboard-server/api-contracts/rag-metrics.ts +22 -0
- package/extensions/dashboard-server/api-contracts/rag-settings.ts +30 -20
- package/extensions/dashboard-server/api-contracts/wiki.ts +138 -0
- package/extensions/dashboard-server/routes-rag-metrics.ts +82 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +314 -0
- package/extensions/dashboard-server/routes-rag-settings.ts +147 -97
- package/extensions/dashboard-server/routes-wiki-helpers.ts +126 -0
- package/extensions/dashboard-server/routes-wiki.ts +376 -0
- package/extensions/dashboard-server/routes.ts +2 -0
- package/extensions/dashboard-server/server.ts +18 -2
- package/extensions/mega-events/context-handler/afterCompact.ts +44 -1
- package/extensions/mega-pipeline/recall.ts +31 -0
- package/extensions/mega-turn-store.ts +13 -0
- package/package.json +1 -1
- package/src/config/turns.ts +17 -0
- package/src/config.ts +3 -0
- package/src/recall/async.ts +10 -1
- package/src/recall/format.ts +15 -2
- package/src/recall/hydeTelemetry.ts +44 -0
- package/src/recall/sync.ts +34 -2
- package/src/recall/types.ts +36 -0
- package/src/store/turns/hydeStore.ts +82 -0
- package/src/store/turns/index.ts +4 -0
- package/src/store/turns/schema.ts +126 -1
- package/src/store/turns/sqlite-store/rows.ts +25 -0
- package/src/store/turns/sqlite-store/write.ts +20 -2
- package/src/store/turns/types.ts +33 -0
- package/src/topics/durability.ts +231 -0
- package/src/topics/index.ts +7 -1
- package/src/topics/store.ts +35 -9
- package/src/wiki/curation-helpers.ts +140 -0
- package/src/wiki/curation.ts +217 -0
- package/src/wiki/incremental.ts +164 -0
- package/src/wiki/index.ts +13 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-Cqnc7lMg.js +0 -2
- package/extensions/dashboard-client/dist/assets/CacheTab-Cqnc7lMg.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/EventsTab-tYk3VFAp.js +0 -2
- package/extensions/dashboard-client/dist/assets/EventsTab-tYk3VFAp.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/HealthTab-D2_kjgxw.js +0 -2
- package/extensions/dashboard-client/dist/assets/HealthTab-D2_kjgxw.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js +0 -2
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js +0 -2
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-DT_XfL96.js +0 -2
- package/extensions/dashboard-client/dist/assets/MetricsTab-DT_XfL96.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/OverviewTab-BY6KZCme.js +0 -2
- package/extensions/dashboard-client/dist/assets/OverviewTab-BY6KZCme.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/ReposTab-CeS-tpDM.js +0 -2
- package/extensions/dashboard-client/dist/assets/ReposTab-CeS-tpDM.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/SessionsTab-C30AwyoF.js +0 -70
- package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-p55K1tFP.js +0 -2
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-p55K1tFP.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TopicsTab-D8FqyAbK.js +0 -2
- package/extensions/dashboard-client/dist/assets/TopicsTab-D8FqyAbK.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TurnsTab-ju-nXDys.js +0 -2
- package/extensions/dashboard-client/dist/assets/TurnsTab-ju-nXDys.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js +0 -42
- package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-CUNn22iV.css +0 -1
- package/extensions/dashboard-client/src/styles/metrics-extra.css +0 -69
- package/extensions/dashboard-client/src/styles/turns.css +0 -142
- package/extensions/dashboard-client/src/tabs/SetupTab/RagSettingsCard.tsx +0 -160
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* curation.ts — W2 user curation of the auto-categorized wiki (factory shell).
|
|
3
|
+
*
|
|
4
|
+
* Persist rename / merge / split over the `topic_overrides` +
|
|
5
|
+
* `topic_evolution` tables (reserved in the W1.1 schema). Every mutation is
|
|
6
|
+
* atomic (SAVEPOINT via withTx) so a partial write never leaks. The DB
|
|
7
|
+
* primitives live in curation-helpers.ts; this file owns the three
|
|
8
|
+
* transactions (renameTopic / mergeTopics / splitTopic) + label resolution.
|
|
9
|
+
*
|
|
10
|
+
* Host-agnostic (no pi imports); pure local node:sqlite (PREVENT-PI-004), all
|
|
11
|
+
* SQL parameterized (PREVENT-002). Overrides are immutable per (topic_id, kind).
|
|
12
|
+
* `topics`/`memory_topics` are writable; the append-only invariant applies only
|
|
13
|
+
* to the `turns` table.
|
|
14
|
+
*/
|
|
15
|
+
import { openTurnStore, withTx } from "../store/turns/connection.js";
|
|
16
|
+
import { getStateDir } from "../store.js";
|
|
17
|
+
import { getTopicLabel, recountTopic, customLabelOverride, writeLabelOverride, moveMemory, recordEvolution, createSplitTopic, } from "./curation-helpers.js";
|
|
18
|
+
/** Open the wiki curation store over the shared turns.db connection. */
|
|
19
|
+
export function createWikiCuration(stateDir) {
|
|
20
|
+
const db = openTurnStore(stateDir ?? getStateDir());
|
|
21
|
+
const now = () => Date.now();
|
|
22
|
+
function tryCatchResult(res, fn) {
|
|
23
|
+
try {
|
|
24
|
+
return fn();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { ...res, ok: false };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function renameTopic(topicId, label) {
|
|
31
|
+
const base = {
|
|
32
|
+
ok: false,
|
|
33
|
+
topicId,
|
|
34
|
+
label,
|
|
35
|
+
edited: false,
|
|
36
|
+
merged: false,
|
|
37
|
+
split: false,
|
|
38
|
+
};
|
|
39
|
+
if (!getTopicLabel(db, topicId))
|
|
40
|
+
return base;
|
|
41
|
+
return tryCatchResult(base, () => {
|
|
42
|
+
withTx(db, () => writeLabelOverride(db, topicId, label, now()));
|
|
43
|
+
return { ...base, ok: true, edited: label.trim() !== "" };
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function mergeTopics(sourceTopicId, targetTopicId) {
|
|
47
|
+
const base = {
|
|
48
|
+
ok: false,
|
|
49
|
+
topicId: targetTopicId,
|
|
50
|
+
label: "",
|
|
51
|
+
edited: false,
|
|
52
|
+
merged: true,
|
|
53
|
+
split: false,
|
|
54
|
+
};
|
|
55
|
+
if (sourceTopicId === targetTopicId)
|
|
56
|
+
return base;
|
|
57
|
+
const sourceLabel = getTopicLabel(db, sourceTopicId);
|
|
58
|
+
const targetLabel = getTopicLabel(db, targetTopicId);
|
|
59
|
+
if (!sourceLabel || !targetLabel)
|
|
60
|
+
return base;
|
|
61
|
+
return tryCatchResult(base, () => {
|
|
62
|
+
withTx(db, () => {
|
|
63
|
+
const t = now();
|
|
64
|
+
const members = db
|
|
65
|
+
.prepare(`SELECT memory_id, session_id FROM memory_topics
|
|
66
|
+
WHERE topic_id = ? ORDER BY memory_id ASC`)
|
|
67
|
+
.all(sourceTopicId);
|
|
68
|
+
for (const m of members) {
|
|
69
|
+
moveMemory(db, m.memory_id, targetTopicId);
|
|
70
|
+
recordEvolution(db, targetTopicId, m.memory_id, m.session_id, t, "merge");
|
|
71
|
+
}
|
|
72
|
+
db.prepare(`INSERT OR REPLACE INTO topic_overrides
|
|
73
|
+
(topic_id, kind, merged_into, merged_memory_ids, overridden_at)
|
|
74
|
+
VALUES (?, 'merge', ?, ?, ?)`).run(sourceTopicId, targetTopicId, JSON.stringify(members.map((m) => m.memory_id)), t);
|
|
75
|
+
db.prepare("DELETE FROM memory_topics WHERE topic_id = ?").run(sourceTopicId);
|
|
76
|
+
db.prepare("DELETE FROM topics WHERE id = ?").run(sourceTopicId);
|
|
77
|
+
recountTopic(db, targetTopicId);
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
...base,
|
|
81
|
+
ok: true,
|
|
82
|
+
label: getTopicLabel(db, targetTopicId) ?? "",
|
|
83
|
+
edited: customLabelOverride(db, targetTopicId) !== null,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function splitTopic(topicId, memoryIds) {
|
|
88
|
+
const base = {
|
|
89
|
+
ok: false,
|
|
90
|
+
topicId,
|
|
91
|
+
label: "",
|
|
92
|
+
edited: false,
|
|
93
|
+
merged: false,
|
|
94
|
+
split: true,
|
|
95
|
+
};
|
|
96
|
+
const sourceLabel = getTopicLabel(db, topicId);
|
|
97
|
+
if (!sourceLabel || memoryIds.length === 0)
|
|
98
|
+
return base;
|
|
99
|
+
return tryCatchResult(base, () => {
|
|
100
|
+
let newTopicId = "";
|
|
101
|
+
withTx(db, () => {
|
|
102
|
+
const t = now();
|
|
103
|
+
newTopicId = createSplitTopic(db, topicId, sourceLabel, t);
|
|
104
|
+
for (const memoryId of memoryIds) {
|
|
105
|
+
const row = db
|
|
106
|
+
.prepare("SELECT session_id FROM memory_topics WHERE memory_id = ? AND topic_id = ?")
|
|
107
|
+
.get(memoryId, topicId);
|
|
108
|
+
if (!row)
|
|
109
|
+
continue;
|
|
110
|
+
moveMemory(db, memoryId, newTopicId);
|
|
111
|
+
recordEvolution(db, newTopicId, memoryId, row.session_id, t, "split");
|
|
112
|
+
recordEvolution(db, topicId, memoryId, row.session_id, t, "split");
|
|
113
|
+
}
|
|
114
|
+
db.prepare(`INSERT OR REPLACE INTO topic_overrides
|
|
115
|
+
(topic_id, kind, split_from, split_memory_ids, overridden_at)
|
|
116
|
+
VALUES (?, 'split', ?, ?, ?)`).run(newTopicId, topicId, JSON.stringify(memoryIds), t);
|
|
117
|
+
recountTopic(db, topicId);
|
|
118
|
+
recountTopic(db, newTopicId);
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
...base,
|
|
122
|
+
ok: true,
|
|
123
|
+
topicId: newTopicId,
|
|
124
|
+
label: getTopicLabel(db, newTopicId) ?? "",
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function resolveLabel(topicId, autoLabel) {
|
|
129
|
+
const custom = customLabelOverride(db, topicId);
|
|
130
|
+
if (custom)
|
|
131
|
+
return { label: custom, edited: true };
|
|
132
|
+
return { label: autoLabel, edited: false };
|
|
133
|
+
}
|
|
134
|
+
function overrideKinds(topicId) {
|
|
135
|
+
const rows = db
|
|
136
|
+
.prepare("SELECT kind FROM topic_overrides WHERE topic_id = ? ORDER BY kind")
|
|
137
|
+
.all(topicId);
|
|
138
|
+
return rows.map((r) => r.kind);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
renameTopic,
|
|
142
|
+
mergeTopics,
|
|
143
|
+
splitTopic,
|
|
144
|
+
resolveLabel,
|
|
145
|
+
overrideKinds,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { cosineSimilarity } from "../embedder.js";
|
|
2
|
+
import { loadEmbeddings } from "../topics/cluster.js";
|
|
3
|
+
import { silhouette } from "../topics/kselection.js";
|
|
4
|
+
import { openTurnStore, withTx } from "../store/turns/connection.js";
|
|
5
|
+
/** Min cosine to a centroid before a chunk is admitted to a topic. */
|
|
6
|
+
const ASSIGN_SIM_FLOOR = 0.3;
|
|
7
|
+
/** Average of vectors → the centroid for a topic's current members. */
|
|
8
|
+
function meanOf(vectors) {
|
|
9
|
+
const dim = vectors[0]?.length ?? 0;
|
|
10
|
+
const centroid = new Array(dim).fill(0);
|
|
11
|
+
for (const v of vectors) {
|
|
12
|
+
for (let i = 0; i < dim; i++)
|
|
13
|
+
centroid[i] += v[i];
|
|
14
|
+
}
|
|
15
|
+
return centroid.map((x) => x / Math.max(1, vectors.length));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Assign new memories (not already in memory_topics) to their nearest existing
|
|
19
|
+
* topic centroid without a full rebuild. `db` is the main memory store whose
|
|
20
|
+
* `context_chunks` holds the embeddings; `stateDir` locates the turns.db where
|
|
21
|
+
* `topics` / `memory_topics` live. Writes are best-effort + non-fatal.
|
|
22
|
+
*/
|
|
23
|
+
export function assignNewMemoriesIncremental(db, stateDir) {
|
|
24
|
+
const result = {
|
|
25
|
+
assigned: 0,
|
|
26
|
+
pending: 0,
|
|
27
|
+
silhouette: null,
|
|
28
|
+
};
|
|
29
|
+
try {
|
|
30
|
+
const turnDb = openTurnStore(stateDir);
|
|
31
|
+
const assignedRows = turnDb
|
|
32
|
+
.prepare("SELECT memory_id, topic_id FROM memory_topics")
|
|
33
|
+
.all();
|
|
34
|
+
const chunks = loadEmbeddings(db);
|
|
35
|
+
if (chunks.length === 0)
|
|
36
|
+
return result;
|
|
37
|
+
// Map memory_id → chunk for both centroid build + unassigned scan.
|
|
38
|
+
const chunkById = new Map();
|
|
39
|
+
for (const c of chunks)
|
|
40
|
+
chunkById.set(c.chunkId, c);
|
|
41
|
+
const assignedIds = new Set(assignedRows.map((r) => r.memory_id));
|
|
42
|
+
const centroids = new Map();
|
|
43
|
+
// Accumulate real member vectors per topic from assigned, embedded chunks.
|
|
44
|
+
const byTopic = new Map();
|
|
45
|
+
for (const r of assignedRows) {
|
|
46
|
+
const c = chunkById.get(r.memory_id);
|
|
47
|
+
if (!c)
|
|
48
|
+
continue;
|
|
49
|
+
const list = byTopic.get(r.topic_id) ?? [];
|
|
50
|
+
list.push(c.vec);
|
|
51
|
+
byTopic.set(r.topic_id, list);
|
|
52
|
+
}
|
|
53
|
+
for (const [topicId, vecs] of byTopic) {
|
|
54
|
+
if (vecs.length > 0)
|
|
55
|
+
centroids.set(topicId, meanOf(vecs));
|
|
56
|
+
}
|
|
57
|
+
// Assign unassigned chunks to the nearest non-empty centroid.
|
|
58
|
+
const assignmentsToWrite = new Map();
|
|
59
|
+
for (const c of chunks) {
|
|
60
|
+
if (assignedIds.has(c.chunkId))
|
|
61
|
+
continue;
|
|
62
|
+
let bestTopic = "";
|
|
63
|
+
let bestSim = ASSIGN_SIM_FLOOR;
|
|
64
|
+
for (const [topicId, centroid] of centroids) {
|
|
65
|
+
const sim = cosineSimilarity(c.vec, centroid);
|
|
66
|
+
if (sim > bestSim) {
|
|
67
|
+
bestSim = sim;
|
|
68
|
+
bestTopic = topicId;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (bestTopic) {
|
|
72
|
+
assignmentsToWrite.set(c.chunkId, bestTopic);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
result.pending++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Persist new assignments atomically + best-effort.
|
|
79
|
+
if (assignmentsToWrite.size > 0) {
|
|
80
|
+
try {
|
|
81
|
+
withTx(turnDb, () => {
|
|
82
|
+
const ins = turnDb.prepare(`INSERT OR REPLACE INTO memory_topics
|
|
83
|
+
(memory_id, topic_id, confidence, assigned_at, method, session_id)
|
|
84
|
+
VALUES (?, ?, ?, ?, 'kmeans+tfidf', ?)`);
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
for (const [memoryId, topicId] of assignmentsToWrite) {
|
|
87
|
+
const cent = centroids.get(topicId);
|
|
88
|
+
const c = chunkById.get(memoryId);
|
|
89
|
+
const sim = cent && c ? cosineSimilarity(c.vec, cent) : 0;
|
|
90
|
+
ins.run(memoryId, topicId, sim, now, c?.sessionId ?? null);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
result.assigned = assignmentsToWrite.size;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* non-fatal: assignment write failure never breaks the loop */
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Compute mean silhouette over current + newly assigned memberships.
|
|
100
|
+
const allPoints = [];
|
|
101
|
+
const assignments = [];
|
|
102
|
+
const topicIndex = new Map();
|
|
103
|
+
const lookup = new Map();
|
|
104
|
+
for (const r of assignedRows)
|
|
105
|
+
lookup.set(r.memory_id, { topic: r.topic_id });
|
|
106
|
+
for (const c of chunks) {
|
|
107
|
+
const topic = lookup.has(c.chunkId)
|
|
108
|
+
? lookup.get(c.chunkId).topic
|
|
109
|
+
: assignmentsToWrite.get(c.chunkId);
|
|
110
|
+
if (!topic)
|
|
111
|
+
continue;
|
|
112
|
+
if (!topicIndex.has(topic))
|
|
113
|
+
topicIndex.set(topic, topicIndex.size);
|
|
114
|
+
allPoints.push(c.vec);
|
|
115
|
+
assignments.push(topicIndex.get(topic));
|
|
116
|
+
}
|
|
117
|
+
if (allPoints.length > 0) {
|
|
118
|
+
result.silhouette = silhouette(allPoints, assignments, topicIndex.size);
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
/* non-fatal: incremental assignment never breaks compaction */
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
}
|