pi-mega-compact 0.13.1 → 0.13.3

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.
Files changed (212) hide show
  1. package/dist/extensions/dashboard-server/api-contracts/embedder-health.js +11 -0
  2. package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +238 -0
  3. package/dist/extensions/dashboard-server/api-contracts/endpoints/types.js +1 -0
  4. package/dist/extensions/dashboard-server/api-contracts/endpoints.js +5 -224
  5. package/dist/extensions/dashboard-server/api-contracts/rag-settings.js +10 -0
  6. package/dist/extensions/dashboard-server/api-contracts/raptor.js +8 -0
  7. package/dist/extensions/dashboard-server/api-contracts.test/_helpers.js +32 -0
  8. package/dist/extensions/dashboard-server/routes-cache.test/_helpers.js +48 -0
  9. package/dist/extensions/dashboard-server/routes-embedder-health.js +67 -0
  10. package/dist/extensions/dashboard-server/routes-rag-settings.js +169 -0
  11. package/dist/extensions/dashboard-server/routes-raptor.js +88 -0
  12. package/dist/extensions/dashboard-server/routes-setup.js +1 -1
  13. package/dist/extensions/dashboard-server/routes.js +3 -0
  14. package/dist/extensions/dashboard-server/server.js +7 -1
  15. package/dist/extensions/mega-cache-replay.test/_helpers.js +175 -0
  16. package/dist/extensions/mega-commands/dataCommands.js +151 -0
  17. package/dist/extensions/mega-commands/helpers.js +61 -0
  18. package/dist/extensions/mega-commands/historyCommands.js +97 -0
  19. package/dist/extensions/mega-commands/setupCommand.js +200 -0
  20. package/dist/extensions/mega-commands.js +14 -499
  21. package/dist/extensions/mega-compact-s38.test/_helpers.js +194 -0
  22. package/dist/extensions/mega-compact.test/_helpers.js +225 -0
  23. package/dist/extensions/mega-events/agent-handlers/agentEndHandler.js +211 -0
  24. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/cacheStripe.js +49 -0
  25. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/contextHealth.js +33 -0
  26. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/errorRetry.js +387 -0
  27. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/event.js +7 -0
  28. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/gameScoring.js +55 -0
  29. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/lengthStop.js +12 -0
  30. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/memoryReview.js +22 -0
  31. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.js +38 -0
  32. package/dist/extensions/mega-events/agent-handlers/turnEndHandler.js +36 -0
  33. package/dist/extensions/mega-events/agent-handlers.js +4 -799
  34. package/dist/extensions/mega-events/context-handler/afterCompact.js +163 -0
  35. package/dist/extensions/mega-events/context-handler/messageText.js +12 -0
  36. package/dist/extensions/mega-events/context-handler/tailResult.js +46 -0
  37. package/dist/extensions/mega-events/context-handler.js +11 -198
  38. package/dist/extensions/mega-events/separated-prompt.test/_helpers.js +25 -0
  39. package/dist/src/config.js +14 -5
  40. package/dist/src/dedup-engine.test/_helpers.js +55 -0
  41. package/dist/src/e2e.test/_helpers.js +52 -0
  42. package/dist/src/embedder.js +1 -0
  43. package/dist/src/httpEmbedder.js +6 -0
  44. package/dist/src/hyde.js +146 -0
  45. package/dist/src/importance.test/_helpers.js +5 -0
  46. package/dist/src/memoryGraph/sources/checkpoints.js +78 -0
  47. package/dist/src/memoryGraph/sources/edges.js +17 -0
  48. package/dist/src/memoryGraph/sources/flags.js +22 -0
  49. package/dist/src/memoryGraph/sources/helpers.js +14 -0
  50. package/dist/src/memoryGraph/sources/memories.js +88 -0
  51. package/dist/src/memoryGraph/sources/raptor.js +26 -0
  52. package/dist/src/memoryGraph/sources/turns.js +176 -0
  53. package/dist/src/memoryGraph/sources.js +15 -441
  54. package/dist/src/memoryGraph-gates.test/_helpers.js +120 -0
  55. package/dist/src/ratio.bench.test/_helpers.js +198 -0
  56. package/dist/src/recall/async.js +112 -0
  57. package/dist/src/recall/format.js +149 -0
  58. package/dist/src/recall/memory.js +62 -0
  59. package/dist/src/recall/reformulate.js +82 -0
  60. package/dist/src/recall/sync.js +170 -0
  61. package/dist/src/recall/types.js +1 -0
  62. package/dist/src/recall.js +13 -530
  63. package/dist/src/store/sqlite/schema/core.js +232 -0
  64. package/dist/src/store/sqlite/schema/game.js +65 -0
  65. package/dist/src/store/sqlite/schema/plan-v2.js +107 -0
  66. package/dist/src/store/sqlite/schema/turns.js +59 -0
  67. package/dist/src/store/sqlite/schema.js +8 -441
  68. package/dist/src/store/turns/contract-compliance.test/_helpers.js +21 -0
  69. package/dist/src/store/turns/sqlite-store/admin.js +171 -0
  70. package/dist/src/store/turns/sqlite-store/ctx.js +1 -0
  71. package/dist/src/store/turns/sqlite-store/read.js +111 -0
  72. package/dist/src/store/turns/sqlite-store/rows.js +42 -0
  73. package/dist/src/store/turns/sqlite-store/write.js +102 -0
  74. package/dist/src/store/turns/sqlite-store.js +31 -367
  75. package/dist/src/vectorStore/class.js +356 -0
  76. package/dist/src/vectorStore/hash.js +10 -0
  77. package/dist/src/vectorStore/types.js +2 -0
  78. package/dist/src/vectorStore.js +8 -359
  79. package/dist/src/vectorStore.test/_helpers.js +17 -0
  80. package/extensions/dashboard-client/dist/assets/{CacheTab-8HRroK9K.js → CacheTab-Cqnc7lMg.js} +2 -2
  81. package/extensions/dashboard-client/dist/assets/{CacheTab-8HRroK9K.js.map → CacheTab-Cqnc7lMg.js.map} +1 -1
  82. package/extensions/dashboard-client/dist/assets/{EventsTab-ncobZw-I.js → EventsTab-tYk3VFAp.js} +2 -2
  83. package/extensions/dashboard-client/dist/assets/{EventsTab-ncobZw-I.js.map → EventsTab-tYk3VFAp.js.map} +1 -1
  84. package/extensions/dashboard-client/dist/assets/{HealthTab-C6BI1EZG.js → HealthTab-D2_kjgxw.js} +2 -2
  85. package/extensions/dashboard-client/dist/assets/{HealthTab-C6BI1EZG.js.map → HealthTab-D2_kjgxw.js.map} +1 -1
  86. package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js +2 -0
  87. package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js.map +1 -0
  88. package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js +2 -0
  89. package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js.map +1 -0
  90. package/extensions/dashboard-client/dist/assets/{MetricsTab-B88XTCMk.js → MetricsTab-DT_XfL96.js} +2 -2
  91. package/extensions/dashboard-client/dist/assets/{MetricsTab-B88XTCMk.js.map → MetricsTab-DT_XfL96.js.map} +1 -1
  92. package/extensions/dashboard-client/dist/assets/{OverviewTab-CGZrSia-.js → OverviewTab-BY6KZCme.js} +2 -2
  93. package/extensions/dashboard-client/dist/assets/{OverviewTab-CGZrSia-.js.map → OverviewTab-BY6KZCme.js.map} +1 -1
  94. package/extensions/dashboard-client/dist/assets/{ReposTab-BZo5cNS1.js → ReposTab-CeS-tpDM.js} +2 -2
  95. package/extensions/dashboard-client/dist/assets/{ReposTab-BZo5cNS1.js.map → ReposTab-CeS-tpDM.js.map} +1 -1
  96. package/extensions/dashboard-client/dist/assets/{SessionsTab-C2RokJcw.js → SessionsTab-C30AwyoF.js} +2 -2
  97. package/extensions/dashboard-client/dist/assets/{SessionsTab-C2RokJcw.js.map → SessionsTab-C30AwyoF.js.map} +1 -1
  98. package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js +2 -0
  99. package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js.map +1 -0
  100. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CewYB2aA.js → TimeSavedCard-p55K1tFP.js} +2 -2
  101. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CewYB2aA.js.map → TimeSavedCard-p55K1tFP.js.map} +1 -1
  102. package/extensions/dashboard-client/dist/assets/{TopicsTab-DpVNIuaL.js → TopicsTab-D8FqyAbK.js} +2 -2
  103. package/extensions/dashboard-client/dist/assets/{TopicsTab-DpVNIuaL.js.map → TopicsTab-D8FqyAbK.js.map} +1 -1
  104. package/extensions/dashboard-client/dist/assets/{TurnsTab-KeuKKVC9.js → TurnsTab-ju-nXDys.js} +2 -2
  105. package/extensions/dashboard-client/dist/assets/{TurnsTab-KeuKKVC9.js.map → TurnsTab-ju-nXDys.js.map} +1 -1
  106. package/extensions/dashboard-client/dist/assets/{index-Cucgohga.js → index-BEj1Zahy.js} +9 -9
  107. package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js.map +1 -0
  108. package/extensions/dashboard-client/dist/assets/{useSSE-DJsqdPXC.js → useSSE-p1pOI_-P.js} +2 -2
  109. package/extensions/dashboard-client/dist/assets/{useSSE-DJsqdPXC.js.map → useSSE-p1pOI_-P.js.map} +1 -1
  110. package/extensions/dashboard-client/dist/index.html +1 -1
  111. package/extensions/dashboard-client/src/api/client.ts +33 -0
  112. package/extensions/dashboard-client/src/tabs/MaintenanceTab/ActionsCard.tsx +178 -0
  113. package/extensions/dashboard-client/src/tabs/MaintenanceTab/DbStatsCard.tsx +140 -0
  114. package/extensions/dashboard-client/src/tabs/MaintenanceTab/DebugBundleCard.tsx +109 -0
  115. package/extensions/dashboard-client/src/tabs/MaintenanceTab/HealthMitigationCard.tsx +98 -0
  116. package/extensions/dashboard-client/src/tabs/MaintenanceTab/SchemaHealthCard.tsx +108 -0
  117. package/extensions/dashboard-client/src/tabs/MaintenanceTab.tsx +12 -598
  118. package/extensions/dashboard-client/src/tabs/MemoryMapTab/MemoryMapView.tsx +476 -0
  119. package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +163 -0
  120. package/extensions/dashboard-client/src/tabs/MemoryMapTab.tsx +56 -466
  121. package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderHealthCard.tsx +109 -0
  122. package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetup.tsx +470 -0
  123. package/extensions/dashboard-client/src/tabs/SetupTab/RagSettingsCard.tsx +160 -0
  124. package/extensions/dashboard-client/src/tabs/SetupTab.tsx +13 -483
  125. package/extensions/dashboard-server/api-contracts/embedder-health.ts +32 -0
  126. package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +383 -0
  127. package/extensions/dashboard-server/api-contracts/endpoints/types.ts +350 -0
  128. package/extensions/dashboard-server/api-contracts/endpoints.ts +27 -648
  129. package/extensions/dashboard-server/api-contracts/index.ts +14 -0
  130. package/extensions/dashboard-server/api-contracts/rag-settings.ts +42 -0
  131. package/extensions/dashboard-server/api-contracts/raptor.ts +49 -0
  132. package/extensions/dashboard-server/api-contracts.test/_helpers.ts +47 -0
  133. package/extensions/dashboard-server/routes-cache.test/_helpers.ts +94 -0
  134. package/extensions/dashboard-server/routes-embedder-health.ts +77 -0
  135. package/extensions/dashboard-server/routes-rag-settings.ts +207 -0
  136. package/extensions/dashboard-server/routes-raptor.ts +128 -0
  137. package/extensions/dashboard-server/routes-setup.ts +1 -1
  138. package/extensions/dashboard-server/routes.ts +3 -0
  139. package/extensions/dashboard-server/server.ts +6 -0
  140. package/extensions/mega-cache-replay.test/_helpers.ts +188 -0
  141. package/extensions/mega-commands/dataCommands.ts +169 -0
  142. package/extensions/mega-commands/helpers.ts +62 -0
  143. package/extensions/mega-commands/historyCommands.ts +117 -0
  144. package/extensions/mega-commands/setupCommand.ts +235 -0
  145. package/extensions/mega-commands.ts +25 -538
  146. package/extensions/mega-compact-s38.test/_helpers.ts +201 -0
  147. package/extensions/mega-compact.test/_helpers.ts +237 -0
  148. package/extensions/mega-events/agent-handlers/agentEndHandler.ts +238 -0
  149. package/extensions/mega-events/agent-handlers/turnEndHandler/cacheStripe.ts +74 -0
  150. package/extensions/mega-events/agent-handlers/turnEndHandler/contextHealth.ts +50 -0
  151. package/extensions/mega-events/agent-handlers/turnEndHandler/errorRetry.ts +421 -0
  152. package/extensions/mega-events/agent-handlers/turnEndHandler/event.ts +16 -0
  153. package/extensions/mega-events/agent-handlers/turnEndHandler/gameScoring.ts +73 -0
  154. package/extensions/mega-events/agent-handlers/turnEndHandler/lengthStop.ts +29 -0
  155. package/extensions/mega-events/agent-handlers/turnEndHandler/memoryReview.ts +42 -0
  156. package/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.ts +61 -0
  157. package/extensions/mega-events/agent-handlers/turnEndHandler.ts +64 -0
  158. package/extensions/mega-events/agent-handlers.ts +15 -861
  159. package/extensions/mega-events/context-handler/afterCompact.ts +213 -0
  160. package/extensions/mega-events/context-handler/messageText.ts +20 -0
  161. package/extensions/mega-events/context-handler/tailResult.ts +63 -0
  162. package/extensions/mega-events/context-handler.ts +17 -235
  163. package/extensions/mega-events/separated-prompt.test/_helpers.ts +35 -0
  164. package/package.json +1 -1
  165. package/src/config.ts +17 -5
  166. package/src/dedup-engine.test/_helpers.ts +79 -0
  167. package/src/e2e.test/_helpers.ts +59 -0
  168. package/src/embedder.ts +4 -0
  169. package/src/httpEmbedder.ts +7 -0
  170. package/src/hyde.ts +162 -0
  171. package/src/importance.test/_helpers.ts +5 -0
  172. package/src/memoryGraph/sources/checkpoints.ts +99 -0
  173. package/src/memoryGraph/sources/edges.ts +23 -0
  174. package/src/memoryGraph/sources/flags.ts +26 -0
  175. package/src/memoryGraph/sources/helpers.ts +13 -0
  176. package/src/memoryGraph/sources/memories.ts +108 -0
  177. package/src/memoryGraph/sources/raptor.ts +37 -0
  178. package/src/memoryGraph/sources/turns.ts +226 -0
  179. package/src/memoryGraph/sources.ts +19 -544
  180. package/src/memoryGraph-gates.test/_helpers.ts +164 -0
  181. package/src/ratio.bench.test/_helpers.ts +268 -0
  182. package/src/recall/async.ts +142 -0
  183. package/src/recall/format.ts +173 -0
  184. package/src/recall/memory.ts +90 -0
  185. package/src/recall/reformulate.ts +111 -0
  186. package/src/recall/sync.ts +197 -0
  187. package/src/recall/types.ts +63 -0
  188. package/src/recall.ts +25 -712
  189. package/src/store/sqlite/schema/core.ts +233 -0
  190. package/src/store/sqlite/schema/game.ts +66 -0
  191. package/src/store/sqlite/schema/plan-v2.ts +108 -0
  192. package/src/store/sqlite/schema/turns.ts +60 -0
  193. package/src/store/sqlite/schema.ts +13 -441
  194. package/src/store/turns/contract-compliance.test/_helpers.ts +38 -0
  195. package/src/store/turns/sqlite-store/admin.ts +249 -0
  196. package/src/store/turns/sqlite-store/ctx.ts +14 -0
  197. package/src/store/turns/sqlite-store/read.ts +174 -0
  198. package/src/store/turns/sqlite-store/rows.ts +55 -0
  199. package/src/store/turns/sqlite-store/write.ts +193 -0
  200. package/src/store/turns/sqlite-store.ts +33 -514
  201. package/src/vectorStore/class.ts +433 -0
  202. package/src/vectorStore/hash.ts +11 -0
  203. package/src/vectorStore/types.ts +58 -0
  204. package/src/vectorStore.test/_helpers.ts +20 -0
  205. package/src/vectorStore.ts +13 -489
  206. package/extensions/dashboard-client/dist/assets/MaintenanceTab-DZi1MnZI.js +0 -2
  207. package/extensions/dashboard-client/dist/assets/MaintenanceTab-DZi1MnZI.js.map +0 -1
  208. package/extensions/dashboard-client/dist/assets/MemoryMapTab-CjUa9zzw.js +0 -2
  209. package/extensions/dashboard-client/dist/assets/MemoryMapTab-CjUa9zzw.js.map +0 -1
  210. package/extensions/dashboard-client/dist/assets/SetupTab-C_BwmebC.js +0 -2
  211. package/extensions/dashboard-client/dist/assets/SetupTab-C_BwmebC.js.map +0 -1
  212. package/extensions/dashboard-client/dist/assets/index-Cucgohga.js.map +0 -1
@@ -0,0 +1,470 @@
1
+ /**
2
+ * SetupTab/EmbedderSetup.tsx — Embedder setup section (P0b).
3
+ *
4
+ * Shows current embedder configuration, warns about trigram recall quality,
5
+ * and mirrors the /megasetup command with detection results. Extracted from
6
+ * SetupTab.tsx to respect the extensions/ 500-line file limit.
7
+ *
8
+ * PREVENT-PI-004: all data comes from localhost dashboard API endpoints —
9
+ * no external network calls.
10
+ */
11
+ import type React from "react";
12
+ import { useState, useEffect, useCallback } from "react";
13
+ import type { SetupStatusResponse, SetupDetectResponse, SetupConfigureResponse } from "@contracts";
14
+ import { fetchSetupStatus, fetchSetupDetect, configureEmbedder } from "../../api/client";
15
+ import EmbedderHealthCard from "./EmbedderHealthCard";
16
+ import RagSettingsCard from "./RagSettingsCard";
17
+
18
+ const styles: Record<string, React.CSSProperties> = {
19
+ container: {
20
+ padding: "1rem",
21
+ maxWidth: "720px",
22
+ margin: "0 auto",
23
+ fontFamily: "system-ui, sans-serif",
24
+ color: "#e0e0e0",
25
+ },
26
+ section: {
27
+ background: "#1a1a2e",
28
+ borderRadius: "8px",
29
+ padding: "1rem",
30
+ marginBottom: "1rem",
31
+ border: "1px solid #2a2a4e",
32
+ },
33
+ sectionTitle: {
34
+ fontSize: "1.1rem",
35
+ fontWeight: 700,
36
+ marginTop: 0,
37
+ marginBottom: "0.75rem",
38
+ color: "#e0e0e0",
39
+ borderBottom: "1px solid #333",
40
+ paddingBottom: "0.5rem",
41
+ },
42
+ label: { fontWeight: 600, color: "#a0a0c0", marginRight: "0.5rem" },
43
+ value: { color: "#e0e0e0" },
44
+ row: { marginBottom: "0.4rem", fontSize: "0.9rem" },
45
+ warning: {
46
+ background: "#3a2a00",
47
+ border: "1px solid #665500",
48
+ borderRadius: "8px",
49
+ padding: "0.75rem",
50
+ marginTop: "0.5rem",
51
+ color: "#ffcc00",
52
+ fontSize: "0.85rem",
53
+ },
54
+ badge: {
55
+ display: "inline-block",
56
+ padding: "0.15rem 0.5rem",
57
+ borderRadius: "4px",
58
+ fontSize: "0.8rem",
59
+ fontWeight: 600,
60
+ marginLeft: "0.5rem",
61
+ },
62
+ detectRow: {
63
+ display: "flex",
64
+ justifyContent: "space-between",
65
+ alignItems: "center",
66
+ padding: "0.5rem 0",
67
+ borderBottom: "1px solid #2a2a4e",
68
+ },
69
+ button: {
70
+ background: "#3a5a9f",
71
+ color: "#fff",
72
+ border: "none",
73
+ borderRadius: "6px",
74
+ padding: "0.5rem 1rem",
75
+ cursor: "pointer",
76
+ fontSize: "0.9rem",
77
+ fontWeight: 600,
78
+ },
79
+ };
80
+
81
+ export default function EmbedderSetup(): React.ReactElement {
82
+ const [status, setStatus] = useState<SetupStatusResponse | null>(null);
83
+ const [detect, setDetect] = useState<SetupDetectResponse | null>(null);
84
+ const [statusError, setStatusError] = useState<string | null>(null);
85
+ const [detectError, setDetectError] = useState<string | null>(null);
86
+ const [runningDetect, setRunningDetect] = useState(false);
87
+ const [configuring, setConfiguring] = useState<string | null>(null);
88
+ const [configResult, setConfigResult] = useState<SetupConfigureResponse | null>(null);
89
+ const [configError, setConfigError] = useState<string | null>(null);
90
+ const [customUrl, setCustomUrl] = useState("");
91
+
92
+ const loadStatus = useCallback(() => {
93
+ fetchSetupStatus()
94
+ .then(setStatus)
95
+ .catch((e: unknown) =>
96
+ setStatusError(e instanceof Error ? e.message : String(e)),
97
+ );
98
+ }, []);
99
+
100
+ const applyEmbedder = useCallback((embedder: "ollama" | "llama" | "trigram" | "custom", url?: string) => {
101
+ setConfiguring(embedder);
102
+ setConfigError(null);
103
+ setConfigResult(null);
104
+ configureEmbedder({ embedder, url })
105
+ .then((r) => {
106
+ setConfigResult(r);
107
+ setConfiguring(null);
108
+ loadStatus();
109
+ })
110
+ .catch((e: unknown) => {
111
+ setConfigError(e instanceof Error ? e.message : String(e));
112
+ setConfiguring(null);
113
+ });
114
+ }, [loadStatus]);
115
+
116
+ const runDetect = useCallback(() => {
117
+ setRunningDetect(true);
118
+ setDetectError(null);
119
+ fetchSetupDetect()
120
+ .then((d) => {
121
+ setDetect(d);
122
+ setRunningDetect(false);
123
+ })
124
+ .catch((e: unknown) => {
125
+ setDetectError(e instanceof Error ? e.message : String(e));
126
+ setRunningDetect(false);
127
+ });
128
+ }, []);
129
+
130
+ useEffect(() => {
131
+ loadStatus();
132
+ }, [loadStatus]);
133
+
134
+ // Poll status every 30s
135
+ useEffect(() => {
136
+ const id = setInterval(loadStatus, 30000);
137
+ return () => clearInterval(id);
138
+ }, [loadStatus]);
139
+
140
+ const embedderLabel = (e: string): string => {
141
+ switch (e) {
142
+ case "trigram":
143
+ return "TrigramEmbedder (heuristic, default)";
144
+ case "http":
145
+ return "HTTP Embedder (BYO localhost)";
146
+ case "minilm":
147
+ return "MiniLM (experimental)";
148
+ default:
149
+ return "Unknown";
150
+ }
151
+ };
152
+
153
+ const trigramWarning = status?.currentEmbedder === "trigram" && (
154
+ <div style={styles.warning}>
155
+ <strong>Note:</strong> TrigramEmbedder is a heuristic-strength default
156
+ embedder. It works without any setup but recall quality may be lower
157
+ than a dedicated embedding backend. If you notice poor recall results,
158
+ consider installing Ollama and running the{" "}
159
+ <code>/megasetup</code> command, or set{" "}
160
+ <code>MEGACOMPACT_EMBEDDING_URL</code> to point at your own localhost
161
+ embedding server.
162
+ </div>
163
+ );
164
+
165
+ const detectBadge = (installed: boolean): React.ReactElement => {
166
+ const bg = installed ? "#1a5a1a" : "#3a1a1a";
167
+ const color = installed ? "#4caf50" : "#f44336";
168
+ return (
169
+ <span style={{ ...styles.badge, background: bg, color }}>
170
+ {installed ? "Detected" : "Not found"}
171
+ </span>
172
+ );
173
+ };
174
+
175
+ return (
176
+ <div style={styles.container}>
177
+ <h2 style={{ fontSize: "1.3rem", marginTop: 0, marginBottom: "1rem" }}>
178
+ Embedder Setup
179
+ </h2>
180
+
181
+ <EmbedderHealthCard />
182
+
183
+ {/* Current Config Section */}
184
+ <div style={styles.section}>
185
+ <h3 style={styles.sectionTitle}>Current Embedder Configuration</h3>
186
+ {statusError && (
187
+ <p style={{ color: "#f44336", fontSize: "0.85rem" }}>
188
+ Error: {statusError}
189
+ </p>
190
+ )}
191
+ {status && (
192
+ <>
193
+ <div style={styles.row}>
194
+ <span style={styles.label}>Active Embedder:</span>
195
+ <span style={styles.value}>
196
+ {embedderLabel(status.currentEmbedder)}
197
+ </span>
198
+ </div>
199
+ {"configuredEmbedder" in status && status.configuredEmbedder !== status.currentEmbedder && (
200
+ <div style={styles.warning}>
201
+ <strong>Configured but not active:</strong>{" "}
202
+ {embedderLabel(status.configuredEmbedder)} is configured in
203
+ .mega-compact.env but not yet loaded.{" "}
204
+ <strong>Restart pi</strong> to activate it.
205
+ {status.configuredUrl && (
206
+ <> ({status.configuredUrl})</>
207
+ )}
208
+ </div>
209
+ )}
210
+ {"restartRequired" in status && status.restartRequired && (
211
+ <div style={{ ...styles.row, color: "#ff9800" }}>
212
+ <span style={styles.label}>Status:</span>
213
+ <span style={styles.value}>
214
+ Restart required to activate the configured embedder
215
+ </span>
216
+ </div>
217
+ )}
218
+ <div style={styles.row}>
219
+ <span style={styles.label}>Embedding URL:</span>
220
+ <span style={styles.value}>
221
+ {status.embeddingUrl ?? (
222
+ <span style={{ color: "#888" }}>not set</span>
223
+ )}
224
+ </span>
225
+ </div>
226
+ <div style={styles.row}>
227
+ <span style={styles.label}>Embed Cache:</span>
228
+ <span style={styles.value}>
229
+ {status.embedCache ?? (
230
+ <span style={{ color: "#888" }}>not set</span>
231
+ )}
232
+ </span>
233
+ </div>
234
+ <div style={styles.row}>
235
+ <span style={styles.label}>MiniLM:</span>
236
+ <span style={styles.value}>{status.minilm ? "enabled" : "disabled"}</span>
237
+ </div>
238
+ {trigramWarning}
239
+ </>
240
+ )}
241
+ {!status && !statusError && (
242
+ <p style={{ color: "#888", fontSize: "0.85rem" }}>
243
+ Loading configuration...
244
+ </p>
245
+ )}
246
+ </div>
247
+
248
+ {/* Detection Section */}
249
+ <div style={styles.section}>
250
+ <h3 style={styles.sectionTitle}>Local Embedder Detection</h3>
251
+ <p style={{ fontSize: "0.85rem", color: "#a0a0c0", marginTop: 0 }}>
252
+ Detect which local embedding backends are available on this machine.
253
+ No software is installed — detection only.
254
+ </p>
255
+
256
+ {detect && (
257
+ <>
258
+ {/* Ollama */}
259
+ <div style={styles.detectRow}>
260
+ <span>
261
+ <strong>Ollama</strong>
262
+ </span>
263
+ {detect.ollama !== null ? (
264
+ <span>
265
+ {detectBadge(detect.ollama.installed)}
266
+ {detect.ollama.installed && (
267
+ <span style={{ fontSize: "0.8rem", color: "#a0a0c0", marginLeft: "0.5rem" }}>
268
+ {detect.ollama.running
269
+ ? `server running, ${detect.ollama.models.length} model(s)`
270
+ : "server not running"}
271
+ </span>
272
+ )}
273
+ </span>
274
+ ) : (
275
+ <span style={{ color: "#888", fontSize: "0.85rem" }}>
276
+ not checked
277
+ </span>
278
+ )}
279
+ </div>
280
+
281
+ {/* llama.cpp */}
282
+ <div style={styles.detectRow}>
283
+ <span>
284
+ <strong>llama.cpp</strong>
285
+ </span>
286
+ {detect.llamaCpp !== null ? (
287
+ <span>
288
+ {detectBadge(detect.llamaCpp.installed)}
289
+ {detect.llamaCpp.installed && detect.llamaCpp.detail && (
290
+ <span style={{ fontSize: "0.8rem", color: "#a0a0c0", marginLeft: "0.5rem" }}>
291
+ {detect.llamaCpp.detail}
292
+ </span>
293
+ )}
294
+ </span>
295
+ ) : (
296
+ <span style={{ color: "#888", fontSize: "0.85rem" }}>
297
+ not checked
298
+ </span>
299
+ )}
300
+ </div>
301
+
302
+ {/* ONNX */}
303
+ <div style={styles.detectRow}>
304
+ <span>
305
+ <strong>ONNX Runtime</strong>
306
+ </span>
307
+ {detect.onnx !== null ? (
308
+ <span>
309
+ {detectBadge(detect.onnx.installed)}
310
+ {detect.onnx.installed && detect.onnx.detail && (
311
+ <span style={{ fontSize: "0.8rem", color: "#a0a0c0", marginLeft: "0.5rem" }}>
312
+ {detect.onnx.detail}
313
+ </span>
314
+ )}
315
+ </span>
316
+ ) : (
317
+ <span style={{ color: "#888", fontSize: "0.85rem" }}>
318
+ not checked
319
+ </span>
320
+ )}
321
+ </div>
322
+
323
+ {detect.error && (
324
+ <p style={{ color: "#f44336", fontSize: "0.8rem", marginTop: "0.5rem" }}>
325
+ Detection error: {detect.error}
326
+ </p>
327
+ )}
328
+ </>
329
+ )}
330
+
331
+ {detectError && (
332
+ <p style={{ color: "#f44336", fontSize: "0.85rem" }}>
333
+ Error: {detectError}
334
+ </p>
335
+ )}
336
+
337
+ <div style={{ marginTop: "1rem" }}>
338
+ <button
339
+ style={styles.button}
340
+ onClick={runDetect}
341
+ disabled={runningDetect}
342
+ >
343
+ {runningDetect ? "Detecting..." : "Run Detection"}
344
+ </button>
345
+ <span style={{ fontSize: "0.8rem", color: "#888", marginLeft: "0.75rem" }}>
346
+ Or run <code>/megasetup</code> in the chat for an interactive wizard.
347
+ </span>
348
+ </div>
349
+
350
+ {/* Configure buttons — appear after detection runs */}
351
+ {detect && (
352
+ <div style={{ marginTop: "1rem", paddingTop: "0.75rem", borderTop: "1px solid #2a2a4e" }}>
353
+ <div style={{ fontSize: "0.9rem", fontWeight: 600, marginBottom: "0.5rem" }}>
354
+ Configure
355
+ </div>
356
+ <div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
357
+ <button
358
+ style={{ ...styles.button, opacity: detect.ollama?.installed ? 1 : 0.4 }}
359
+ onClick={() => applyEmbedder("ollama")}
360
+ disabled={!detect.ollama?.installed || configuring !== null}
361
+ >
362
+ {configuring === "ollama" ? "Writing..." : "Use Ollama"}
363
+ </button>
364
+ <button
365
+ style={{ ...styles.button, opacity: detect.llamaCpp?.installed ? 1 : 0.4 }}
366
+ onClick={() => applyEmbedder("llama")}
367
+ disabled={!detect.llamaCpp?.installed || configuring !== null}
368
+ >
369
+ {configuring === "llama" ? "Writing..." : "Use llama.cpp"}
370
+ </button>
371
+ <button
372
+ style={{ ...styles.button, background: "#444" }}
373
+ onClick={() => applyEmbedder("trigram")}
374
+ disabled={configuring !== null}
375
+ >
376
+ {configuring === "trigram" ? "Writing..." : "Use Trigram (default)"}
377
+ </button>
378
+ </div>
379
+ {configResult && (
380
+ <div style={styles.warning}>
381
+ {configResult.alreadyActive
382
+ ? "Already active — no restart needed."
383
+ : `Configured ${configResult.embedder}. Restart pi to activate (config written to ${configResult.envPath}).`}
384
+ </div>
385
+ )}
386
+ {configError && (
387
+ <p style={{ color: "#f44336", fontSize: "0.85rem", marginTop: "0.5rem" }}>
388
+ Configure error: {configError}
389
+ </p>
390
+ )}
391
+ </div>
392
+ )}
393
+ </div>
394
+
395
+ {/* Custom (remote) embedder — third-party / hosted endpoint */}
396
+ <div style={styles.section}>
397
+ <h3 style={styles.sectionTitle}>Custom Endpoint (remote / third-party)</h3>
398
+ <p style={{ fontSize: "0.85rem", color: "#a0a0c0", marginTop: 0 }}>
399
+ Point at any OpenAI-compatible embeddings API or hosted endpoint.
400
+ This opts in to a non-loopback connection (sets{" "}
401
+ <code>MEGACOMPACT_ALLOW_REMOTE_EMBEDDER=1</code>) — your prompts'
402
+ embedding requests will be sent to the URL you enter. Default is
403
+ loopback-only.
404
+ </p>
405
+ <div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap", alignItems: "center" }}>
406
+ <input
407
+ type="url"
408
+ placeholder="https://api.example.com/v1/embeddings"
409
+ value={customUrl}
410
+ onChange={(e) => setCustomUrl(e.target.value)}
411
+ style={{
412
+ flex: "1 1 300px",
413
+ background: "#12122a",
414
+ color: "#e0e0e0",
415
+ border: "1px solid #2a2a4e",
416
+ borderRadius: "6px",
417
+ padding: "0.4rem 0.6rem",
418
+ fontSize: "0.85rem",
419
+ fontFamily: "monospace",
420
+ }}
421
+ />
422
+ <button
423
+ style={{ ...styles.button, opacity: customUrl ? 1 : 0.4 }}
424
+ onClick={() => applyEmbedder("custom", customUrl)}
425
+ disabled={!customUrl || configuring !== null}
426
+ >
427
+ {configuring === "custom" ? "Writing..." : "Use Custom URL"}
428
+ </button>
429
+ </div>
430
+ <div style={styles.warning}>
431
+ <strong>Heads up:</strong> a remote endpoint receives the text you embed
432
+ (it does NOT receive your full conversation — only the strings passed to
433
+ <code> embed()</code> for recall/dedup). Verify the endpoint's privacy
434
+ policy before use.
435
+ </div>
436
+ </div>
437
+
438
+ {/* Help Section */}
439
+ <div style={styles.section}>
440
+ <h3 style={styles.sectionTitle}>How to Upgrade</h3>
441
+ <ul style={{ fontSize: "0.85rem", lineHeight: 1.6, paddingLeft: "1.25rem" }}>
442
+ <li>
443
+ <strong>Ollama:</strong> Install from{" "}
444
+ <a
445
+ href="https://ollama.com"
446
+ style={{ color: "#6a9fff" }}
447
+ target="_blank"
448
+ rel="noopener noreferrer"
449
+ >
450
+ ollama.com
451
+ </a>
452
+ , then <code>ollama pull nomic-embed-text</code> and restart pi.
453
+ Set <code>MEGACOMPACT_EMBEDDING_URL=http://localhost:11434/api/embeddings</code>.
454
+ </li>
455
+ <li>
456
+ <strong>llama.cpp:</strong> Build or install llama.cpp, run{" "}
457
+ <code>llama-server</code> with an embedding model, and set
458
+ the URL accordingly.
459
+ </li>
460
+ <li>
461
+ <strong>ONNX Runtime:</strong> Install{" "}
462
+ <code>onnxruntime-node</code> in the project root. Not yet
463
+ integrated — see docs for manual setup.
464
+ </li>
465
+ </ul>
466
+ </div>
467
+ <RagSettingsCard />
468
+ </div>
469
+ );
470
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * SetupTab/RagSettingsCard.tsx — RAG feature flag toggles (S57 B1–B5).
3
+ *
4
+ * Shows each RAG flag as a checkbox toggle. Reads/writes the .mega-compact.env
5
+ * file via the /api/rag-settings endpoint. HyDE (B5) is greyed out when no
6
+ * LLM embedder (HttpEmbedder) is active — it requires an LLM to function.
7
+ *
8
+ * PREVENT-PI-004: all data comes from localhost dashboard API endpoints.
9
+ */
10
+ import type React from "react";
11
+ import { useState, useEffect, useCallback } from "react";
12
+ import type { RagSettingsResponse } from "@contracts";
13
+ import { fetchRagSettings, postRagSettings } from "../../api/client";
14
+
15
+ const styles: Record<string, React.CSSProperties> = {
16
+ section: {
17
+ background: "#1a1a2e",
18
+ borderRadius: "8px",
19
+ padding: "1rem",
20
+ marginBottom: "1rem",
21
+ border: "1px solid #2a2a4e",
22
+ },
23
+ sectionTitle: {
24
+ fontSize: "1.1rem",
25
+ fontWeight: 700,
26
+ marginTop: 0,
27
+ marginBottom: "0.75rem",
28
+ color: "#e0e0e0",
29
+ borderBottom: "1px solid #333",
30
+ paddingBottom: "0.5rem",
31
+ },
32
+ flagRow: {
33
+ display: "flex",
34
+ alignItems: "flex-start",
35
+ gap: "0.5rem",
36
+ padding: "0.5rem 0",
37
+ borderBottom: "1px solid #2a2a4e",
38
+ },
39
+ checkbox: {
40
+ marginTop: "0.15rem",
41
+ cursor: "pointer",
42
+ },
43
+ label: {
44
+ fontWeight: 600,
45
+ color: "#e0e0e0",
46
+ fontSize: "0.9rem",
47
+ },
48
+ description: {
49
+ fontSize: "0.8rem",
50
+ color: "#a0a0c0",
51
+ marginTop: "0.15rem",
52
+ },
53
+ hint: {
54
+ fontSize: "0.75rem",
55
+ color: "#ff9800",
56
+ marginTop: "0.15rem",
57
+ },
58
+ banner: {
59
+ background: "#3a2a00",
60
+ border: "1px solid #665500",
61
+ borderRadius: "6px",
62
+ padding: "0.5rem 0.75rem",
63
+ marginTop: "0.5rem",
64
+ color: "#ffcc00",
65
+ fontSize: "0.8rem",
66
+ },
67
+ };
68
+
69
+ export default function RagSettingsCard(): React.ReactElement {
70
+ const [settings, setSettings] = useState<RagSettingsResponse | null>(null);
71
+ const [error, setError] = useState<string | null>(null);
72
+ const [saving, setSaving] = useState(false);
73
+ const [restartBanner, setRestartBanner] = useState(false);
74
+
75
+ const load = useCallback(() => {
76
+ fetchRagSettings()
77
+ .then(setSettings)
78
+ .catch((e: unknown) =>
79
+ setError(e instanceof Error ? e.message : String(e)),
80
+ );
81
+ }, []);
82
+
83
+ useEffect(() => {
84
+ load();
85
+ }, [load]);
86
+
87
+ useEffect(() => {
88
+ const id = setInterval(load, 30000);
89
+ return () => clearInterval(id);
90
+ }, [load]);
91
+
92
+ const toggle = useCallback(
93
+ (key: string, enabled: boolean) => {
94
+ if (!settings) return;
95
+ const flag = settings.flags.find((f) => f.key === key);
96
+ if (!flag || (flag.requiresLlm && !settings.llmActive)) return;
97
+ setSaving(true);
98
+ postRagSettings({ flags: { [key]: enabled } })
99
+ .then(() => {
100
+ setRestartBanner(true);
101
+ setSaving(false);
102
+ load();
103
+ })
104
+ .catch((e: unknown) => {
105
+ setError(e instanceof Error ? e.message : String(e));
106
+ setSaving(false);
107
+ });
108
+ },
109
+ [settings, load],
110
+ );
111
+
112
+ return (
113
+ <div style={styles.section}>
114
+ <h3 style={styles.sectionTitle}>RAG Settings</h3>
115
+ <p style={{ fontSize: "0.8rem", color: "#a0a0c0", marginTop: 0 }}>
116
+ Recall pipeline features. All default ON — toggle off to disable.
117
+ Changes take effect after restart.
118
+ </p>
119
+ {error && (
120
+ <p style={{ color: "#f44336", fontSize: "0.85rem" }}>Error: {error}</p>
121
+ )}
122
+ {settings?.flags.map((flag) => {
123
+ const locked = flag.requiresLlm && !settings.llmActive;
124
+ return (
125
+ <div key={flag.key} style={styles.flagRow}>
126
+ <input
127
+ type="checkbox"
128
+ style={{
129
+ ...styles.checkbox,
130
+ opacity: locked ? 0.4 : 1,
131
+ cursor: locked ? "not-allowed" : "pointer",
132
+ }}
133
+ checked={flag.enabled && !locked}
134
+ disabled={locked || saving}
135
+ onChange={(e) => toggle(flag.key, e.currentTarget.checked)}
136
+ />
137
+ <div>
138
+ <div style={styles.label}>{flag.label}</div>
139
+ <div style={styles.description}>{flag.description}</div>
140
+ {locked && (
141
+ <div style={styles.hint}>
142
+ Requires an LLM embedder (Ollama/HTTP). Configure one in
143
+ the Embedder section above first.
144
+ </div>
145
+ )}
146
+ </div>
147
+ </div>
148
+ );
149
+ })}
150
+ {!settings && !error && (
151
+ <p style={{ color: "#888", fontSize: "0.85rem" }}>Loading...</p>
152
+ )}
153
+ {restartBanner && (
154
+ <div style={styles.banner}>
155
+ Settings saved. <strong>Restart pi</strong> to apply changes.
156
+ </div>
157
+ )}
158
+ </div>
159
+ );
160
+ }