pi-mega-compact 0.13.5 → 0.13.7
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/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/index-reader.js +3 -1
- package/dist/extensions/dashboard-server/resolve-snapshot.js +81 -0
- package/dist/extensions/dashboard-server/routes-core.js +8 -3
- 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-repo.js +5 -1
- package/dist/extensions/dashboard-server/routes-sessions.js +6 -3
- 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-runtime/capture-model.js +5 -2
- 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/pricing.js +8 -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-j2VOSRp6.js +70 -0
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C30AwyoF.js.map → AreaChart-j2VOSRp6.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-Dr1HeMfc.js +2 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-Dr1HeMfc.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-DRG2k7FS.js +2 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-DRG2k7FS.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-DGE9PpW3.js +2 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-DGE9PpW3.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-DeYRhF4q.js +2 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-DeYRhF4q.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DSnSO3nG.js +2 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DSnSO3nG.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-RIzNc1Uj.js +2 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-RIzNc1Uj.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-_1BJ4Bmh.js +2 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-_1BJ4Bmh.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-DkU7ywZB.js +2 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-DkU7ywZB.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/SessionsTab-Bq_F_aOk.js +2 -0
- package/extensions/dashboard-client/dist/assets/SessionsTab-Bq_F_aOk.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-BkBD2Y97.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-BkBD2Y97.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-BXzFKU7C.js +2 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-BXzFKU7C.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TurnsTab-Bjpp3vBH.js +5 -0
- package/extensions/dashboard-client/dist/assets/TurnsTab-Bjpp3vBH.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-dBN2EA5G.js +2 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-dBN2EA5G.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/button-Bt0b5QVp.js +2 -0
- package/extensions/dashboard-client/dist/assets/button-Bt0b5QVp.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/card-D5CafXtg.js +2 -0
- package/extensions/dashboard-client/dist/assets/card-D5CafXtg.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +1 -0
- package/extensions/dashboard-client/dist/assets/index-GPHRnEN7.js +137 -0
- package/extensions/dashboard-client/dist/assets/index-GPHRnEN7.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/pricing-DkYp8-vi.js +2 -0
- package/extensions/dashboard-client/dist/assets/pricing-DkYp8-vi.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/switch-CY5Gwj1o.js +2 -0
- package/extensions/dashboard-client/dist/assets/switch-CY5Gwj1o.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/toggle-C9HpkIfH.js +2 -0
- package/extensions/dashboard-client/dist/assets/toggle-C9HpkIfH.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js → useSSE-2JFrLDlE.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js.map → useSSE-2JFrLDlE.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/index-reader.ts +3 -1
- package/extensions/dashboard-server/resolve-snapshot.ts +98 -0
- package/extensions/dashboard-server/routes-core.ts +8 -3
- 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-repo.ts +5 -1
- package/extensions/dashboard-server/routes-sessions.ts +6 -3
- 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-runtime/capture-model.ts +5 -2
- 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/pricing.ts +8 -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/dist/assets/pricing-CvE4NllQ.js +0 -2
- package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js.map +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,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-rag-settings-helpers.ts — SETTINGS inventory.
|
|
3
|
+
*
|
|
4
|
+
* The full catalog of user-adjustable MEGACOMPACT_* settings surfaced by the
|
|
5
|
+
* dashboard Setup panel, grouped by category. Kept separate from the route
|
|
6
|
+
* handler so the inventory can grow without bloating the handler file.
|
|
7
|
+
*
|
|
8
|
+
* PREVENT-011: no `any` type.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Base metadata for a single setting entry before its live `value` is resolved.
|
|
14
|
+
* `category` and `value` are filled in at read time by the handler.
|
|
15
|
+
*/
|
|
16
|
+
export interface SettingSpec {
|
|
17
|
+
key: string;
|
|
18
|
+
label: string;
|
|
19
|
+
description: string;
|
|
20
|
+
type: "boolean" | "number" | "string";
|
|
21
|
+
default: string | number | boolean;
|
|
22
|
+
/** True when this is a `_DISABLED`-convention opt-out flag. */
|
|
23
|
+
disabledConvention: boolean;
|
|
24
|
+
requiresLlm: boolean;
|
|
25
|
+
unit?: string;
|
|
26
|
+
min?: number;
|
|
27
|
+
max?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Shorthand builders to keep the inventory terse and unambiguous.
|
|
31
|
+
const boolFlag = (
|
|
32
|
+
key: string,
|
|
33
|
+
label: string,
|
|
34
|
+
description: string,
|
|
35
|
+
def: boolean,
|
|
36
|
+
requiresLlm = false,
|
|
37
|
+
): SettingSpec => ({
|
|
38
|
+
key,
|
|
39
|
+
label,
|
|
40
|
+
description,
|
|
41
|
+
type: "boolean",
|
|
42
|
+
default: def,
|
|
43
|
+
disabledConvention: true,
|
|
44
|
+
requiresLlm,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const boolDirect = (
|
|
48
|
+
key: string,
|
|
49
|
+
label: string,
|
|
50
|
+
description: string,
|
|
51
|
+
def: boolean,
|
|
52
|
+
): SettingSpec => ({
|
|
53
|
+
key,
|
|
54
|
+
label,
|
|
55
|
+
description,
|
|
56
|
+
type: "boolean",
|
|
57
|
+
default: def,
|
|
58
|
+
disabledConvention: false,
|
|
59
|
+
requiresLlm: false,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const num = (
|
|
63
|
+
key: string,
|
|
64
|
+
label: string,
|
|
65
|
+
description: string,
|
|
66
|
+
def: number,
|
|
67
|
+
min: number,
|
|
68
|
+
max: number,
|
|
69
|
+
unit?: string,
|
|
70
|
+
): SettingSpec => ({
|
|
71
|
+
key,
|
|
72
|
+
label,
|
|
73
|
+
description,
|
|
74
|
+
type: "number",
|
|
75
|
+
default: def,
|
|
76
|
+
disabledConvention: false,
|
|
77
|
+
requiresLlm: false,
|
|
78
|
+
min,
|
|
79
|
+
max,
|
|
80
|
+
...(unit ? { unit } : {}),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const str = (
|
|
84
|
+
key: string,
|
|
85
|
+
label: string,
|
|
86
|
+
description: string,
|
|
87
|
+
def: string,
|
|
88
|
+
): SettingSpec => ({
|
|
89
|
+
key,
|
|
90
|
+
label,
|
|
91
|
+
description,
|
|
92
|
+
type: "string",
|
|
93
|
+
default: def,
|
|
94
|
+
disabledConvention: false,
|
|
95
|
+
requiresLlm: false,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/** Every adjustable setting, grouped by category. Read-only after module load. */
|
|
99
|
+
export const SETTINGS: ReadonlyArray<{
|
|
100
|
+
name: string;
|
|
101
|
+
settings: SettingSpec[];
|
|
102
|
+
}> = [
|
|
103
|
+
{
|
|
104
|
+
name: "RAG Pipeline",
|
|
105
|
+
settings: [
|
|
106
|
+
boolFlag(
|
|
107
|
+
"MEGACOMPACT_QUERY_REFORMULATION",
|
|
108
|
+
"Query Reformulation",
|
|
109
|
+
"TF-IDF keyword expansion for vague recall queries",
|
|
110
|
+
true,
|
|
111
|
+
),
|
|
112
|
+
boolFlag(
|
|
113
|
+
"MEGACOMPACT_TIERED_ROUTER",
|
|
114
|
+
"Tiered Recall Router",
|
|
115
|
+
"L0 cache → L1 FTS5 → L2 HNSW routing",
|
|
116
|
+
true,
|
|
117
|
+
),
|
|
118
|
+
boolFlag(
|
|
119
|
+
"MEGACOMPACT_RECALL_METRICS",
|
|
120
|
+
"Recall Quality Metrics",
|
|
121
|
+
"Precision/recall scoring and logging",
|
|
122
|
+
true,
|
|
123
|
+
),
|
|
124
|
+
boolFlag(
|
|
125
|
+
"MEGACOMPACT_MEMORY_GRAPH",
|
|
126
|
+
"Memory Graph",
|
|
127
|
+
"Dashboard-oriented memory graph traversal",
|
|
128
|
+
true,
|
|
129
|
+
),
|
|
130
|
+
boolFlag(
|
|
131
|
+
"MEGACOMPACT_HYDE",
|
|
132
|
+
"HyDE",
|
|
133
|
+
"Generate hypothetical answer via LLM, embed it, RRF-fuse",
|
|
134
|
+
true,
|
|
135
|
+
true,
|
|
136
|
+
),
|
|
137
|
+
boolFlag(
|
|
138
|
+
"MEGACOMPACT_NEW_UI",
|
|
139
|
+
"New Dashboard UI",
|
|
140
|
+
"Tailwind + shadcn visual design (sidebar, glass panels)",
|
|
141
|
+
true,
|
|
142
|
+
),
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "Wiki / Turns",
|
|
147
|
+
settings: [
|
|
148
|
+
boolFlag(
|
|
149
|
+
"MEGACOMPACT_WIKI_ENHANCED",
|
|
150
|
+
"Wiki Enhanced",
|
|
151
|
+
"User curation (rename/merge/split) + topic evolution",
|
|
152
|
+
true,
|
|
153
|
+
),
|
|
154
|
+
boolFlag(
|
|
155
|
+
"MEGACOMPACT_WIKI_INCREMENTAL",
|
|
156
|
+
"Wiki Incremental",
|
|
157
|
+
"Assign new memories to nearest centroid",
|
|
158
|
+
true,
|
|
159
|
+
),
|
|
160
|
+
boolDirect(
|
|
161
|
+
"MEGACOMPACT_AUTO_WIKI",
|
|
162
|
+
"Auto Wiki",
|
|
163
|
+
"Auto-categorizing wiki (k-means + TF-IDF)",
|
|
164
|
+
true,
|
|
165
|
+
),
|
|
166
|
+
boolDirect(
|
|
167
|
+
"MEGACOMPACT_WIKI_SEED_FROM_TURNS",
|
|
168
|
+
"Wiki Seed from Turns",
|
|
169
|
+
"Seed topic model from raw_transcript when chunks thin",
|
|
170
|
+
true,
|
|
171
|
+
),
|
|
172
|
+
boolDirect(
|
|
173
|
+
"MEGACOMPACT_TURNS_DB",
|
|
174
|
+
"Turns DB",
|
|
175
|
+
"Isolated turns.db store",
|
|
176
|
+
true,
|
|
177
|
+
),
|
|
178
|
+
num(
|
|
179
|
+
"MEGACOMPACT_WIKI_SILHOUETTE_MIN",
|
|
180
|
+
"Silhouette Minimum",
|
|
181
|
+
"Full rebuild trigger threshold",
|
|
182
|
+
0.2,
|
|
183
|
+
0,
|
|
184
|
+
1,
|
|
185
|
+
),
|
|
186
|
+
num(
|
|
187
|
+
"MEGACOMPACT_TURNS_RETENTION_DAYS",
|
|
188
|
+
"Turn Retention",
|
|
189
|
+
"Per-turn provenance retention window",
|
|
190
|
+
30,
|
|
191
|
+
1,
|
|
192
|
+
365,
|
|
193
|
+
"days",
|
|
194
|
+
),
|
|
195
|
+
num(
|
|
196
|
+
"MEGACOMPACT_TURNS_KEEP_MIN",
|
|
197
|
+
"Turns Keep Minimum",
|
|
198
|
+
"Min turns kept per conversation during prune",
|
|
199
|
+
5,
|
|
200
|
+
1,
|
|
201
|
+
100,
|
|
202
|
+
),
|
|
203
|
+
num(
|
|
204
|
+
"MEGACOMPACT_WIKI_LABEL_TOP_TERMS",
|
|
205
|
+
"Wiki Label Terms",
|
|
206
|
+
"How many TF-IDF terms form a topic label",
|
|
207
|
+
5,
|
|
208
|
+
1,
|
|
209
|
+
20,
|
|
210
|
+
),
|
|
211
|
+
num(
|
|
212
|
+
"MEGACOMPACT_WIKI_REBUILD_EVERY",
|
|
213
|
+
"Wiki Rebuild Every",
|
|
214
|
+
"Rebuild topic model every Nth compaction",
|
|
215
|
+
3,
|
|
216
|
+
1,
|
|
217
|
+
50,
|
|
218
|
+
),
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: "Dedup Tiers",
|
|
223
|
+
settings: [
|
|
224
|
+
boolDirect("MEGACOMPACT_L0_ENABLED", "L0 Exact Match", "Exact-hash dedup tier", true),
|
|
225
|
+
boolDirect("MEGACOMPACT_L1_ENABLED", "L1 MinHash/LSH", "Near-dup tier", true),
|
|
226
|
+
boolDirect("MEGACOMPACT_L2_ENABLED", "L2 Semantic", "Cosine similarity dedup tier", true),
|
|
227
|
+
boolDirect("MEGACOMPACT_RAPTOR_ENABLED", "RAPTOR", "Hierarchical clustering tier", true),
|
|
228
|
+
boolDirect("MEGACOMPACT_RAPTOR_MULTILEVEL", "RAPTOR Multi-level", "Multi-level retrieval (score all tree levels)", true),
|
|
229
|
+
boolDirect("MEGACOMPACT_RAPTOR_LEAF_EXPANSION", "RAPTOR Leaf Expansion", "Leaf node expansion in retrieval", true),
|
|
230
|
+
boolDirect("MEGACOMPACT_RAPTOR_INCREMENTAL", "RAPTOR Incremental", "Incremental rebuild mode", true),
|
|
231
|
+
boolDirect("MEGACOMPACT_RAPTOR_INJECT_SUMMARIES", "RAPTOR Inject Summaries", "Inject top-level summary nodes into recall", true),
|
|
232
|
+
boolDirect("MEGACOMPACT_MARK_ONLY_L0", "Mark Only L0", "L0 runs but does not collapse", false),
|
|
233
|
+
boolDirect("MEGACOMPACT_MARK_ONLY_L1", "Mark Only L1", "L1 runs but does not collapse", false),
|
|
234
|
+
boolDirect("MEGACOMPACT_MARK_ONLY_L2", "Mark Only L2", "L2 runs but does not collapse", false),
|
|
235
|
+
boolDirect("MEGACOMPACT_MINILM", "MiniLM Embedder", "Use MiniLM instead of trigram", false),
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: "Dedup Thresholds",
|
|
240
|
+
settings: [
|
|
241
|
+
num("MEGACOMPACT_L2_THRESHOLD", "L2 Cosine Threshold", "L2 semantic dedup firing point", 0.85, 0, 1),
|
|
242
|
+
num("MEGACOMPACT_L1_JACCARD", "L1 Jaccard Threshold", "L1 MinHash near-dup threshold", 0.8, 0, 1),
|
|
243
|
+
num("MEGACOMPACT_DEDUP_SIM", "Dedup Similarity", "Legacy content-similarity fallback", 0.9, 0, 1),
|
|
244
|
+
num("MEGACOMPACT_MMR_LAMBDA", "MMR Lambda", "Maximal Marginal Relevance diversity", 0.5, 0, 1),
|
|
245
|
+
num("MEGACOMPACT_SEMDEDUP_COSINE", "SemDeDup Cosine", "Offline SemDeDup pair threshold", 0.95, 0, 1),
|
|
246
|
+
num("MEGACOMPACT_CONSOLIDATE_COSINE", "Consolidate Cosine", "Memory consolidation merge threshold", 0.7, 0, 1),
|
|
247
|
+
num("MEGACOMPACT_SIMILARITY_BUDGET_MS", "Similarity Budget", "Time budget for similarity computation", 50, 1, 10000, "ms"),
|
|
248
|
+
num("MEGACOMPACT_L1_VERIFY_BUDGET_MS", "L1 Verify Budget", "L1 verification time budget", 20, 1, 10000, "ms"),
|
|
249
|
+
num("MEGACOMPACT_L1_CANDIDATE_CAP", "L1 Candidate Cap", "L1 candidate cap", 100, 1, 10000),
|
|
250
|
+
],
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "RAPTOR Tuning",
|
|
254
|
+
settings: [
|
|
255
|
+
num("MEGACOMPACT_RAPTOR_BUDGET_MS", "RAPTOR Budget", "RAPTOR time budget", 5000, 100, 60000, "ms"),
|
|
256
|
+
num("MEGACOMPACT_RAPTOR_CLUSTERS", "RAPTOR Clusters", "Clusters per level", 5, 1, 50),
|
|
257
|
+
num("MEGACOMPACT_RAPTOR_CONSISTENCY", "RAPTOR Consistency", "Consistency threshold", 0.6, 0, 1),
|
|
258
|
+
num("MEGACOMPACT_RAPTOR_MAX_LEAF_EXP", "RAPTOR Max Leaf Expansion", "Max leaf expansion nodes", 10, 1, 100),
|
|
259
|
+
num("MEGACOMPACT_RAPTOR_FRESHNESS_HOURS", "RAPTOR Freshness", "Skip rebuild when tree is fresh", 4, 1, 168, "hours"),
|
|
260
|
+
num("MEGACOMPACT_FP_RATE_L0", "FP Rate L0", "FP alert threshold for exact tier", 0.01, 0, 1),
|
|
261
|
+
num("MEGACOMPACT_FP_RATE_L1L2", "FP Rate L1/L2", "FP alert threshold for fuzzy tiers", 0.05, 0, 1),
|
|
262
|
+
num("MEGACOMPACT_ALERT_WINDOW_MS", "Alert Window", "Alert evaluation window", 600000, 1000, 3600000, "ms"),
|
|
263
|
+
num("MEGACOMPACT_P95_BUDGET_MS", "P95 Budget", "Canary p95 budget per tier", 100, 1, 10000, "ms"),
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: "Models",
|
|
268
|
+
settings: [
|
|
269
|
+
str("MEGACOMPACT_HYDE_MODEL", "HyDE Model", "LLM model name for HyDE generation", "llama3.2"),
|
|
270
|
+
str("MEGACOMPACT_RAPTOR_MODEL", "RAPTOR Summary Model", "Ollama model for cluster summarization (empty = extractive)", ""),
|
|
271
|
+
str("MEGACOMPACT_RAPTOR_URL", "RAPTOR Ollama URL", "Ollama endpoint for RAPTOR summarization", "http://127.0.0.1:11434"),
|
|
272
|
+
num("MEGACOMPACT_EMBED_CACHE", "Embed Cache Size", "Embedding cache entries (0 = disabled)", 256, 0, 10000),
|
|
273
|
+
],
|
|
274
|
+
},
|
|
275
|
+
];
|
|
276
|
+
|
|
277
|
+
/** Flat index of every setting by key for O(1) lookup + validation. */
|
|
278
|
+
export const SETTING_BY_KEY: ReadonlyMap<string, SettingSpec> = new Map(
|
|
279
|
+
SETTINGS.flatMap((c) => c.settings).map((s) => [s.key, s]),
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Adjustable MEGACOMPACT_* env vars intentionally NOT surfaced in the settings
|
|
284
|
+
* UI. Handled by other panels, install-time paths, dev-only, internal tuning,
|
|
285
|
+
* or special string formats the generic form cannot represent.
|
|
286
|
+
* Kept as string literals so regression_check.py's coverage scan sees them.
|
|
287
|
+
*/
|
|
288
|
+
export const EXCLUDED_SETTINGS: readonly string[] = [
|
|
289
|
+
// Embedder telemetry — handled by EmbedderSetup.
|
|
290
|
+
"MEGACOMPACT_EMBEDDING_URL",
|
|
291
|
+
"MEGACOMPACT_EMBEDDING_KEY",
|
|
292
|
+
"MEGACOMPACT_EMBEDDING_HEADERS",
|
|
293
|
+
"MEGACOMPACT_EMBEDDING_DIM",
|
|
294
|
+
"MEGACOMPACT_OLLAMA_MODEL",
|
|
295
|
+
"MEGACOMPACT_ALLOW_REMOTE_EMBEDDER",
|
|
296
|
+
// Install-time paths.
|
|
297
|
+
"MEGACOMPACT_STATE_DIR",
|
|
298
|
+
"MEGACOMPACT_INDEX_DIR",
|
|
299
|
+
"MEGACOMPACT_VECTOR_INDEX_DIR",
|
|
300
|
+
"MEGACOMPACT_TURNS_DB_PATH",
|
|
301
|
+
// Dev-only.
|
|
302
|
+
"MEGACOMPACT_EXT_SCAN_DIR",
|
|
303
|
+
"MEGACOMPACT_EXT_USER_DIR",
|
|
304
|
+
// PGlite internal tuning.
|
|
305
|
+
"MEGACOMPACT_PGLITE_DISABLED",
|
|
306
|
+
"MEGACOMPACT_PGLITE_OPEN_TIMEOUT_MS",
|
|
307
|
+
"MEGACOMPACT_PGLITE_CLOSE_TIMEOUT_MS",
|
|
308
|
+
"MEGACOMPACT_PGLITE_QUERY_TIMEOUT_MS",
|
|
309
|
+
// Special string formats the generic form cannot represent.
|
|
310
|
+
"MEGACOMPACT_WIKI_K_RANGE",
|
|
311
|
+
"MEGACOMPACT_RAPTOR_LEVEL_WEIGHTS",
|
|
312
|
+
// Internal calibration, not user-facing.
|
|
313
|
+
"MEGACOMPACT_FTS5_MAX_BM25",
|
|
314
|
+
];
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dashboard-server/routes-rag-settings.ts —
|
|
2
|
+
* dashboard-server/routes-rag-settings.ts — comprehensive settings route handler.
|
|
3
3
|
*
|
|
4
|
-
* GET /api/rag-settings — Returns
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* GET /api/rag-settings — Returns every adjustable MEGACOMPACT_* setting,
|
|
5
|
+
* grouped by category, with live values from env.
|
|
6
|
+
* POST /api/rag-settings — Updates a single setting by writing its line to the
|
|
7
|
+
* per-repo .mega-compact.env file.
|
|
8
|
+
*
|
|
9
|
+
* The SETTINGS inventory lives in routes-rag-settings-helpers.ts so this file
|
|
10
|
+
* stays within the line budget.
|
|
7
11
|
*
|
|
8
12
|
* Guardrails: PREVENT-PI-004 (loopback-only), PREVENT-001 (null-safe JSON),
|
|
9
13
|
* PREVENT-011 (no `any`). Each JSON write carries a guardrails-allow annotation.
|
|
@@ -14,68 +18,101 @@ import { join } from "node:path";
|
|
|
14
18
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
15
19
|
import type { RouteContext } from "./routes-core.js";
|
|
16
20
|
import { detectCurrentEmbedder } from "./routes-setup.js";
|
|
21
|
+
import { SETTINGS, SETTING_BY_KEY } from "./routes-rag-settings-helpers.js";
|
|
22
|
+
import type { SettingSpec } from "./routes-rag-settings-helpers.js";
|
|
17
23
|
import type {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
SettingState,
|
|
25
|
+
SettingsResponse,
|
|
26
|
+
SettingsUpdateRequest,
|
|
27
|
+
SettingsResponsePost,
|
|
22
28
|
} from "./api-contracts/rag-settings.js";
|
|
23
29
|
|
|
24
30
|
// ---------------------------------------------------------------------------
|
|
25
|
-
//
|
|
31
|
+
// Env-reading helpers — one per setting type.
|
|
26
32
|
// ---------------------------------------------------------------------------
|
|
27
33
|
|
|
28
|
-
const RAG_FLAGS: {
|
|
29
|
-
key: string;
|
|
30
|
-
label: string;
|
|
31
|
-
description: string;
|
|
32
|
-
requiresLlm: boolean;
|
|
33
|
-
}[] = [
|
|
34
|
-
{
|
|
35
|
-
key: "MEGACOMPACT_QUERY_REFORMULATION",
|
|
36
|
-
label: "Query Reformulation",
|
|
37
|
-
description:
|
|
38
|
-
"TF-IDF keyword expansion for vague recall queries (TrigramEmbedder path)",
|
|
39
|
-
requiresLlm: false,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
key: "MEGACOMPACT_TIERED_ROUTER",
|
|
43
|
-
label: "Tiered Recall Router",
|
|
44
|
-
description:
|
|
45
|
-
"L0 cache → L1 FTS5 → L2 HNSW routing for faster recall",
|
|
46
|
-
requiresLlm: false,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
key: "MEGACOMPACT_RECALL_METRICS",
|
|
50
|
-
label: "Recall Quality Metrics",
|
|
51
|
-
description:
|
|
52
|
-
"Precision/recall scoring and logging for recall evaluation",
|
|
53
|
-
requiresLlm: false,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
key: "MEGACOMPACT_MEMORY_GRAPH",
|
|
57
|
-
label: "Memory Graph",
|
|
58
|
-
description:
|
|
59
|
-
"Dashboard-oriented memory graph traversal across sessions",
|
|
60
|
-
requiresLlm: false,
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
key: "MEGACOMPACT_HYDE",
|
|
64
|
-
label: "HyDE (Hypothetical Document Embeddings)",
|
|
65
|
-
description:
|
|
66
|
-
"Generate hypothetical answer via LLM, embed it, RRF-fuse with raw-query results",
|
|
67
|
-
requiresLlm: true,
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
/** Strip any MEGACOMPACT_*_DISABLED assignment lines from env file content. */
|
|
72
|
-
const DISABLED_LINE = /^export\s+MEGACOMPACT_\w+_DISABLED=/;
|
|
73
|
-
|
|
74
34
|
function isDisabled(key: string): boolean {
|
|
75
35
|
const v = process.env[key + "_DISABLED"];
|
|
76
36
|
return v === "true" || v === "1";
|
|
77
37
|
}
|
|
78
38
|
|
|
39
|
+
function isEnabled(key: string, def: boolean): boolean {
|
|
40
|
+
const v = process.env[key];
|
|
41
|
+
if (v === undefined) return def;
|
|
42
|
+
return v === "true" || v === "1";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function readNumber(key: string, def: number): number {
|
|
46
|
+
const v = process.env[key];
|
|
47
|
+
if (v === undefined) return def;
|
|
48
|
+
const n = Number(v);
|
|
49
|
+
return Number.isNaN(n) ? def : n;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function resolveValue(spec: SettingSpec): string | number | boolean {
|
|
53
|
+
if (spec.type === "boolean") {
|
|
54
|
+
return spec.disabledConvention
|
|
55
|
+
? !isDisabled(spec.key)
|
|
56
|
+
: isEnabled(spec.key, spec.default as boolean);
|
|
57
|
+
}
|
|
58
|
+
if (spec.type === "number") {
|
|
59
|
+
return readNumber(spec.key, spec.default as number);
|
|
60
|
+
}
|
|
61
|
+
return process.env[spec.key] ?? spec.default;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function toSettingState(spec: SettingSpec, category: string): SettingState {
|
|
65
|
+
return {
|
|
66
|
+
key: spec.key,
|
|
67
|
+
label: spec.label,
|
|
68
|
+
description: spec.description,
|
|
69
|
+
category,
|
|
70
|
+
type: spec.type,
|
|
71
|
+
value: resolveValue(spec),
|
|
72
|
+
default: spec.default,
|
|
73
|
+
disabledConvention: spec.disabledConvention,
|
|
74
|
+
requiresLlm: spec.requiresLlm,
|
|
75
|
+
...(spec.unit !== undefined ? { unit: spec.unit } : {}),
|
|
76
|
+
...(spec.min !== undefined ? { min: spec.min } : {}),
|
|
77
|
+
...(spec.max !== undefined ? { max: spec.max } : {}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Env file I/O.
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
/** Strip lines assigning KEY or KEY_DISABLED from env file content. */
|
|
86
|
+
const keyLinePattern = (key: string): RegExp =>
|
|
87
|
+
new RegExp(`^export\\s+${key}(_DISABLED)?=`);
|
|
88
|
+
|
|
89
|
+
function envPathOf(ctx: RouteContext): string {
|
|
90
|
+
return join(ctx.stateDir, ".mega-compact.env");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function readEnvLines(envPath: string, key: string): string[] {
|
|
94
|
+
if (!existsSync(envPath)) return [];
|
|
95
|
+
return readFileSync(envPath, "utf-8")
|
|
96
|
+
.split("\n")
|
|
97
|
+
.filter((l) => !keyLinePattern(key).test(l));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function writeSetting(envPath: string, key: string, line: string): void {
|
|
101
|
+
const lines = readEnvLines(envPath, key);
|
|
102
|
+
lines.push(line);
|
|
103
|
+
if (lines[lines.length - 1] !== "") lines.push("");
|
|
104
|
+
writeFileSync(envPath, lines.join("\n"), "utf-8");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Strip KEY/KEY_DISABLED lines, leaving the file otherwise intact. */
|
|
108
|
+
function removeSetting(envPath: string, key: string): void {
|
|
109
|
+
writeFileSync(envPath, readEnvLines(envPath, key).join("\n"), "utf-8");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Request body parsing.
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
|
|
79
116
|
function readJsonBody(
|
|
80
117
|
req: IncomingMessage,
|
|
81
118
|
cb: (
|
|
@@ -96,7 +133,7 @@ function readJsonBody(
|
|
|
96
133
|
req.on("end", () => {
|
|
97
134
|
if (tooBig) return cb({ ok: false, error: "body_too_large" });
|
|
98
135
|
try {
|
|
99
|
-
const v = body ? JSON.parse(body) : {}; // PREVENT-001: parsed value type-checked below
|
|
136
|
+
const v: unknown = body ? JSON.parse(body) : {}; // PREVENT-001: parsed value type-checked below
|
|
100
137
|
if (typeof v !== "object" || v === null || Array.isArray(v)) {
|
|
101
138
|
return cb({ ok: false, error: "invalid_object" });
|
|
102
139
|
}
|
|
@@ -120,15 +157,12 @@ export function handleRagSettings(
|
|
|
120
157
|
if (req.url !== "/api/rag-settings") return false;
|
|
121
158
|
|
|
122
159
|
if (req.method === "GET") {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
description: f.description,
|
|
127
|
-
enabled: !isDisabled(f.key),
|
|
128
|
-
requiresLlm: f.requiresLlm,
|
|
160
|
+
const categories = SETTINGS.map((cat) => ({
|
|
161
|
+
name: cat.name,
|
|
162
|
+
settings: cat.settings.map((s) => toSettingState(s, cat.name)),
|
|
129
163
|
}));
|
|
130
|
-
const body:
|
|
131
|
-
|
|
164
|
+
const body: SettingsResponse = {
|
|
165
|
+
categories,
|
|
132
166
|
llmActive: detectCurrentEmbedder() === "http",
|
|
133
167
|
};
|
|
134
168
|
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
@@ -145,51 +179,60 @@ export function handleRagSettings(
|
|
|
145
179
|
res.end(JSON.stringify({ error: parsed.error }));
|
|
146
180
|
return;
|
|
147
181
|
}
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
|
|
182
|
+
const reqBody = parsed.value as unknown as SettingsUpdateRequest;
|
|
183
|
+
const key = reqBody.key;
|
|
184
|
+
const value = reqBody.value;
|
|
185
|
+
if (typeof key !== "string" || typeof value !== "string") {
|
|
151
186
|
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
152
187
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
153
|
-
res.end(JSON.stringify({ error: "
|
|
188
|
+
res.end(JSON.stringify({ error: "invalid_body" }));
|
|
154
189
|
return;
|
|
155
190
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
res.end(JSON.stringify({ error: `unknown_flag: ${key}` }));
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
191
|
+
const spec = SETTING_BY_KEY.get(key);
|
|
192
|
+
if (!spec) {
|
|
193
|
+
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
194
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
195
|
+
res.end(JSON.stringify({ error: `unknown_setting: ${key}` }));
|
|
196
|
+
return;
|
|
165
197
|
}
|
|
166
198
|
|
|
167
|
-
const envPath =
|
|
168
|
-
let lines: string[] = [];
|
|
169
|
-
if (existsSync(envPath)) {
|
|
170
|
-
const content = readFileSync(envPath, "utf-8");
|
|
171
|
-
lines = content.split("\n").filter((line) => !DISABLED_LINE.test(line));
|
|
172
|
-
}
|
|
173
|
-
for (const key of Object.keys(desired)) {
|
|
174
|
-
if (desired[key] === false) {
|
|
175
|
-
lines.push(`export ${key}_DISABLED="true"`);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (lines.length > 0 && lines[lines.length - 1] !== "") lines.push("");
|
|
199
|
+
const envPath = envPathOf(ctx);
|
|
179
200
|
try {
|
|
180
201
|
mkdirSync(ctx.stateDir, { recursive: true });
|
|
181
|
-
|
|
202
|
+
if (spec.type === "boolean") {
|
|
203
|
+
if (value !== "true" && value !== "false") {
|
|
204
|
+
throw new SettingError("boolean_value_required");
|
|
205
|
+
}
|
|
206
|
+
if (spec.disabledConvention) {
|
|
207
|
+
// false → opt out via KEY_DISABLED="true"; true → strip the line.
|
|
208
|
+
if (value === "false") {
|
|
209
|
+
writeSetting(envPath, spec.key, `export ${spec.key}_DISABLED="true"`);
|
|
210
|
+
} else {
|
|
211
|
+
removeSetting(envPath, spec.key);
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
writeSetting(envPath, spec.key, `export ${spec.key}="${value}"`);
|
|
215
|
+
}
|
|
216
|
+
} else if (spec.type === "number") {
|
|
217
|
+
const n = Number(value);
|
|
218
|
+
if (Number.isNaN(n)) throw new SettingError("invalid_number");
|
|
219
|
+
if (spec.min !== undefined && n < spec.min) throw new SettingError("below_min");
|
|
220
|
+
if (spec.max !== undefined && n > spec.max) throw new SettingError("above_max");
|
|
221
|
+
writeSetting(envPath, spec.key, `export ${spec.key}="${n}"`);
|
|
222
|
+
} else {
|
|
223
|
+
writeSetting(envPath, spec.key, `export ${spec.key}="${value}"`);
|
|
224
|
+
}
|
|
182
225
|
} catch (e) {
|
|
226
|
+
const msg =
|
|
227
|
+
e instanceof SettingError
|
|
228
|
+
? e.message
|
|
229
|
+
: `write_failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
183
230
|
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
184
|
-
res.writeHead(
|
|
185
|
-
res.end(
|
|
186
|
-
JSON.stringify({
|
|
187
|
-
error: `write_failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
188
|
-
}),
|
|
189
|
-
);
|
|
231
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
232
|
+
res.end(JSON.stringify({ error: msg }));
|
|
190
233
|
return;
|
|
191
234
|
}
|
|
192
|
-
const resp:
|
|
235
|
+
const resp: SettingsResponsePost = {
|
|
193
236
|
envPath,
|
|
194
237
|
restartRequired: true,
|
|
195
238
|
};
|
|
@@ -205,3 +248,10 @@ export function handleRagSettings(
|
|
|
205
248
|
res.end(JSON.stringify({ error: "method_not_allowed" }));
|
|
206
249
|
return true;
|
|
207
250
|
}
|
|
251
|
+
|
|
252
|
+
class SettingError extends Error {
|
|
253
|
+
constructor(message: string) {
|
|
254
|
+
super(message);
|
|
255
|
+
this.name = "SettingError";
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -7,6 +7,7 @@ import { join } from "node:path";
|
|
|
7
7
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
8
8
|
|
|
9
9
|
import { readSnapshot } from "./snapshot.js";
|
|
10
|
+
import { resolveSnapshot } from "./resolve-snapshot.js";
|
|
10
11
|
import { dashboardHtml } from "./html.js";
|
|
11
12
|
import { readIndex, getIndexDir } from "./index-reader.js";
|
|
12
13
|
import { ACTIVE_WINDOW_SEC } from "./types.js";
|
|
@@ -41,7 +42,10 @@ export function handleIndex(
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
if (req.url === "/api/snapshot") {
|
|
44
|
-
|
|
45
|
+
// Dynamically resolve the most recently active session's dashboard.json
|
|
46
|
+
// so the Overview shows live data from the repo pi is running in — not
|
|
47
|
+
// the stale launcher dir the server was started with.
|
|
48
|
+
const { snapshot: snap } = resolveSnapshot(snapshotPath, ctx.stateDir);
|
|
45
49
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
46
50
|
res.end(JSON.stringify(snap));
|
|
47
51
|
return true;
|
|
@@ -28,10 +28,13 @@ export function handleEvents(
|
|
|
28
28
|
Connection: "keep-alive",
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
// Drain existing events so the client starts with history
|
|
31
|
+
// Drain existing events so the client starts with history.
|
|
32
|
+
// Only stream events with a "type" field — events.log also contains
|
|
33
|
+
// internal monitoring rows (e.g. captureModel:recorded) that use "event"
|
|
34
|
+
// instead of "type" and aren't part of the SseEvent contract.
|
|
32
35
|
const { data: existing, offset: initialOffset } = readFrom(eventsPath, 0);
|
|
33
36
|
eventOffsetRef.value = initialOffset;
|
|
34
|
-
const lines = existing.split("\n").filter((l: string) => l.trim());
|
|
37
|
+
const lines = existing.split("\n").filter((l: string) => l.trim() && l.includes('"type"'));
|
|
35
38
|
for (const line of lines) {
|
|
36
39
|
res.write(`data: ${line}\n\n`);
|
|
37
40
|
}
|
|
@@ -44,7 +47,7 @@ export function handleEvents(
|
|
|
44
47
|
watchTimer = null;
|
|
45
48
|
const { data, offset } = readFrom(eventsPath, eventOffsetRef.value);
|
|
46
49
|
eventOffsetRef.value = offset;
|
|
47
|
-
const newLines = data.split("\n").filter((l: string) => l.trim());
|
|
50
|
+
const newLines = data.split("\n").filter((l: string) => l.trim() && l.includes('"type"'));
|
|
48
51
|
for (const line of newLines) {
|
|
49
52
|
res.write(`data: ${line}\n\n`);
|
|
50
53
|
}
|