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.
Files changed (234) hide show
  1. package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +50 -0
  2. package/dist/extensions/dashboard-server/api-contracts/rag-metrics.js +1 -0
  3. package/dist/extensions/dashboard-server/api-contracts/rag-settings.js +3 -3
  4. package/dist/extensions/dashboard-server/api-contracts/wiki.js +1 -0
  5. package/dist/extensions/dashboard-server/index-reader.js +3 -1
  6. package/dist/extensions/dashboard-server/resolve-snapshot.js +81 -0
  7. package/dist/extensions/dashboard-server/routes-core.js +8 -3
  8. package/dist/extensions/dashboard-server/routes-rag-metrics.js +60 -0
  9. package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +167 -0
  10. package/dist/extensions/dashboard-server/routes-rag-settings.js +136 -77
  11. package/dist/extensions/dashboard-server/routes-repo.js +5 -1
  12. package/dist/extensions/dashboard-server/routes-sessions.js +6 -3
  13. package/dist/extensions/dashboard-server/routes-wiki-helpers.js +97 -0
  14. package/dist/extensions/dashboard-server/routes-wiki.js +330 -0
  15. package/dist/extensions/dashboard-server/routes.js +2 -0
  16. package/dist/extensions/dashboard-server/server.js +17 -3
  17. package/dist/extensions/mega-events/context-handler/afterCompact.js +35 -2
  18. package/dist/extensions/mega-pipeline/recall.js +31 -0
  19. package/dist/extensions/mega-runtime/capture-model.js +5 -2
  20. package/dist/extensions/mega-turn-store.js +2 -1
  21. package/dist/src/config/turns.js +10 -0
  22. package/dist/src/config.js +2 -0
  23. package/dist/src/pricing.js +8 -0
  24. package/dist/src/recall/async.js +10 -1
  25. package/dist/src/recall/format.js +10 -1
  26. package/dist/src/recall/hydeTelemetry.js +22 -0
  27. package/dist/src/recall/sync.js +28 -2
  28. package/dist/src/store/turns/hydeStore.js +32 -0
  29. package/dist/src/store/turns/index.js +1 -0
  30. package/dist/src/store/turns/schema.js +102 -1
  31. package/dist/src/store/turns/sqlite-store/rows.js +23 -0
  32. package/dist/src/store/turns/sqlite-store/write.js +7 -3
  33. package/dist/src/topics/durability.js +187 -0
  34. package/dist/src/topics/index.js +2 -1
  35. package/dist/src/topics/store.js +28 -9
  36. package/dist/src/wiki/curation-helpers.js +71 -0
  37. package/dist/src/wiki/curation.js +147 -0
  38. package/dist/src/wiki/incremental.js +126 -0
  39. package/dist/src/wiki/index.js +5 -0
  40. package/extensions/dashboard-client/dist/assets/AreaChart-j2VOSRp6.js +70 -0
  41. package/extensions/dashboard-client/dist/assets/{SessionsTab-C30AwyoF.js.map → AreaChart-j2VOSRp6.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/CacheTab-Dr1HeMfc.js +2 -0
  43. package/extensions/dashboard-client/dist/assets/CacheTab-Dr1HeMfc.js.map +1 -0
  44. package/extensions/dashboard-client/dist/assets/EventsTab-DRG2k7FS.js +2 -0
  45. package/extensions/dashboard-client/dist/assets/EventsTab-DRG2k7FS.js.map +1 -0
  46. package/extensions/dashboard-client/dist/assets/HealthTab-DGE9PpW3.js +2 -0
  47. package/extensions/dashboard-client/dist/assets/HealthTab-DGE9PpW3.js.map +1 -0
  48. package/extensions/dashboard-client/dist/assets/MaintenanceTab-DeYRhF4q.js +2 -0
  49. package/extensions/dashboard-client/dist/assets/MaintenanceTab-DeYRhF4q.js.map +1 -0
  50. package/extensions/dashboard-client/dist/assets/MemoryMapTab-DSnSO3nG.js +2 -0
  51. package/extensions/dashboard-client/dist/assets/MemoryMapTab-DSnSO3nG.js.map +1 -0
  52. package/extensions/dashboard-client/dist/assets/MetricsTab-RIzNc1Uj.js +2 -0
  53. package/extensions/dashboard-client/dist/assets/MetricsTab-RIzNc1Uj.js.map +1 -0
  54. package/extensions/dashboard-client/dist/assets/OverviewTab-_1BJ4Bmh.js +2 -0
  55. package/extensions/dashboard-client/dist/assets/OverviewTab-_1BJ4Bmh.js.map +1 -0
  56. package/extensions/dashboard-client/dist/assets/ReposTab-DkU7ywZB.js +2 -0
  57. package/extensions/dashboard-client/dist/assets/ReposTab-DkU7ywZB.js.map +1 -0
  58. package/extensions/dashboard-client/dist/assets/SessionsTab-Bq_F_aOk.js +2 -0
  59. package/extensions/dashboard-client/dist/assets/SessionsTab-Bq_F_aOk.js.map +1 -0
  60. package/extensions/dashboard-client/dist/assets/SetupTab-BkBD2Y97.js +2 -0
  61. package/extensions/dashboard-client/dist/assets/SetupTab-BkBD2Y97.js.map +1 -0
  62. package/extensions/dashboard-client/dist/assets/TimeSavedCard-BXzFKU7C.js +2 -0
  63. package/extensions/dashboard-client/dist/assets/TimeSavedCard-BXzFKU7C.js.map +1 -0
  64. package/extensions/dashboard-client/dist/assets/TurnsTab-Bjpp3vBH.js +5 -0
  65. package/extensions/dashboard-client/dist/assets/TurnsTab-Bjpp3vBH.js.map +1 -0
  66. package/extensions/dashboard-client/dist/assets/WikiTab-dBN2EA5G.js +2 -0
  67. package/extensions/dashboard-client/dist/assets/WikiTab-dBN2EA5G.js.map +1 -0
  68. package/extensions/dashboard-client/dist/assets/button-Bt0b5QVp.js +2 -0
  69. package/extensions/dashboard-client/dist/assets/button-Bt0b5QVp.js.map +1 -0
  70. package/extensions/dashboard-client/dist/assets/card-D5CafXtg.js +2 -0
  71. package/extensions/dashboard-client/dist/assets/card-D5CafXtg.js.map +1 -0
  72. package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +1 -0
  73. package/extensions/dashboard-client/dist/assets/index-GPHRnEN7.js +137 -0
  74. package/extensions/dashboard-client/dist/assets/index-GPHRnEN7.js.map +1 -0
  75. package/extensions/dashboard-client/dist/assets/pricing-DkYp8-vi.js +2 -0
  76. package/extensions/dashboard-client/dist/assets/pricing-DkYp8-vi.js.map +1 -0
  77. package/extensions/dashboard-client/dist/assets/switch-CY5Gwj1o.js +2 -0
  78. package/extensions/dashboard-client/dist/assets/switch-CY5Gwj1o.js.map +1 -0
  79. package/extensions/dashboard-client/dist/assets/toggle-C9HpkIfH.js +2 -0
  80. package/extensions/dashboard-client/dist/assets/toggle-C9HpkIfH.js.map +1 -0
  81. package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js → useSSE-2JFrLDlE.js} +2 -2
  82. package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js.map → useSSE-2JFrLDlE.js.map} +1 -1
  83. package/extensions/dashboard-client/dist/index.html +2 -2
  84. package/extensions/dashboard-client/package-lock.json +1995 -191
  85. package/extensions/dashboard-client/package.json +12 -1
  86. package/extensions/dashboard-client/postcss.config.js +6 -0
  87. package/extensions/dashboard-client/src/App.tsx +127 -88
  88. package/extensions/dashboard-client/src/api/client.ts +109 -10
  89. package/extensions/dashboard-client/src/components/ActiveReposTable.tsx +15 -7
  90. package/extensions/dashboard-client/src/components/ActiveSessionsTable.tsx +67 -55
  91. package/extensions/dashboard-client/src/components/CacheHitRateTrendCard.tsx +17 -13
  92. package/extensions/dashboard-client/src/components/CacheHitsCard.tsx +35 -30
  93. package/extensions/dashboard-client/src/components/CacheStatusPerModel.tsx +33 -28
  94. package/extensions/dashboard-client/src/components/EventCategoryFilter.tsx +5 -6
  95. package/extensions/dashboard-client/src/components/EventStream.tsx +17 -13
  96. package/extensions/dashboard-client/src/components/HydeDetailPanel.tsx +173 -0
  97. package/extensions/dashboard-client/src/components/LegendCard.tsx +16 -9
  98. package/extensions/dashboard-client/src/components/PerfCards.tsx +28 -20
  99. package/extensions/dashboard-client/src/components/PerfChart.tsx +9 -6
  100. package/extensions/dashboard-client/src/components/ProviderCacheCard.tsx +15 -7
  101. package/extensions/dashboard-client/src/components/RagDashboard.tsx +253 -0
  102. package/extensions/dashboard-client/src/components/RepoAllSessionsCard.tsx +15 -10
  103. package/extensions/dashboard-client/src/components/RepoContextStack.tsx +24 -16
  104. package/extensions/dashboard-client/src/components/RepoDetailModal.tsx +52 -49
  105. package/extensions/dashboard-client/src/components/RepoTable.tsx +26 -17
  106. package/extensions/dashboard-client/src/components/SessionContextGauges.tsx +11 -14
  107. package/extensions/dashboard-client/src/components/SessionInfo.tsx +20 -15
  108. package/extensions/dashboard-client/src/components/SessionsMemoryChart.tsx +8 -5
  109. package/extensions/dashboard-client/src/components/SummaryTiles.tsx +26 -17
  110. package/extensions/dashboard-client/src/components/TabBar.tsx +1 -3
  111. package/extensions/dashboard-client/src/components/layout/AppShell.tsx +42 -0
  112. package/extensions/dashboard-client/src/components/layout/BottomBar.tsx +88 -0
  113. package/extensions/dashboard-client/src/components/layout/Sidebar.tsx +83 -0
  114. package/extensions/dashboard-client/src/components/ui/badge.tsx +30 -0
  115. package/extensions/dashboard-client/src/components/ui/button.tsx +44 -0
  116. package/extensions/dashboard-client/src/components/ui/card.tsx +32 -0
  117. package/extensions/dashboard-client/src/components/ui/select.tsx +64 -0
  118. package/extensions/dashboard-client/src/components/ui/switch.tsx +26 -0
  119. package/extensions/dashboard-client/src/components/ui/tabs.tsx +36 -0
  120. package/extensions/dashboard-client/src/components/ui/toggle.tsx +28 -0
  121. package/extensions/dashboard-client/src/components/ui/tooltip.tsx +27 -0
  122. package/extensions/dashboard-client/src/config.ts +10 -0
  123. package/extensions/dashboard-client/src/main.tsx +2 -2
  124. package/extensions/dashboard-client/src/memory-map-layout.ts +1 -2
  125. package/extensions/dashboard-client/src/styles/index.css +79 -0
  126. package/extensions/dashboard-client/src/tabs/CacheTab.tsx +33 -26
  127. package/extensions/dashboard-client/src/tabs/EventsTab.tsx +22 -7
  128. package/extensions/dashboard-client/src/tabs/HealthTab.tsx +77 -46
  129. package/extensions/dashboard-client/src/tabs/MaintenanceTab/ActionsCard.tsx +60 -50
  130. package/extensions/dashboard-client/src/tabs/MaintenanceTab/DbStatsCard.tsx +61 -35
  131. package/extensions/dashboard-client/src/tabs/MaintenanceTab/DebugBundleCard.tsx +34 -23
  132. package/extensions/dashboard-client/src/tabs/MaintenanceTab/HealthMitigationCard.tsx +62 -43
  133. package/extensions/dashboard-client/src/tabs/MaintenanceTab/SchemaHealthCard.tsx +53 -32
  134. package/extensions/dashboard-client/src/tabs/MaintenanceTab.tsx +2 -2
  135. package/extensions/dashboard-client/src/tabs/MemoryMapTab/MemoryMapView.tsx +29 -46
  136. package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +10 -34
  137. package/extensions/dashboard-client/src/tabs/MemoryMapTab.tsx +14 -34
  138. package/extensions/dashboard-client/src/tabs/MetricsTab.tsx +5 -2
  139. package/extensions/dashboard-client/src/tabs/OverviewTab.tsx +11 -5
  140. package/extensions/dashboard-client/src/tabs/ReposTab.tsx +5 -5
  141. package/extensions/dashboard-client/src/tabs/SessionsTab.tsx +47 -33
  142. package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetup.tsx +6 -2
  143. package/extensions/dashboard-client/src/tabs/SetupTab/RagHealthCard.tsx +78 -0
  144. package/extensions/dashboard-client/src/tabs/SetupTab/SettingsPanel.tsx +198 -0
  145. package/extensions/dashboard-client/src/tabs/SetupTab/SettingsSection.tsx +50 -0
  146. package/extensions/dashboard-client/src/tabs/SetupTab.tsx +21 -59
  147. package/extensions/dashboard-client/src/tabs/TopicsTab.tsx +75 -40
  148. package/extensions/dashboard-client/src/tabs/TurnsTab.tsx +150 -112
  149. package/extensions/dashboard-client/src/tabs/WikiTab/TopicEvolutionGraph.tsx +274 -0
  150. package/extensions/dashboard-client/src/tabs/WikiTab/TopicEvolutionView.tsx +71 -0
  151. package/extensions/dashboard-client/src/tabs/WikiTab/TopicTimeline.tsx +103 -0
  152. package/extensions/dashboard-client/src/tabs/WikiTab/WikiPage.tsx +213 -0
  153. package/extensions/dashboard-client/src/tabs/WikiTab/WikiPageControls.tsx +188 -0
  154. package/extensions/dashboard-client/src/tabs/WikiTab.tsx +222 -0
  155. package/extensions/dashboard-client/src/tabs/registry.ts +57 -0
  156. package/extensions/dashboard-client/src/utils/cn.ts +7 -0
  157. package/extensions/dashboard-client/tailwind.config.js +46 -0
  158. package/extensions/dashboard-server/api-contracts/core.ts +59 -0
  159. package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +79 -0
  160. package/extensions/dashboard-server/api-contracts/index.ts +48 -2
  161. package/extensions/dashboard-server/api-contracts/rag-metrics.ts +22 -0
  162. package/extensions/dashboard-server/api-contracts/rag-settings.ts +30 -20
  163. package/extensions/dashboard-server/api-contracts/wiki.ts +138 -0
  164. package/extensions/dashboard-server/index-reader.ts +3 -1
  165. package/extensions/dashboard-server/resolve-snapshot.ts +98 -0
  166. package/extensions/dashboard-server/routes-core.ts +8 -3
  167. package/extensions/dashboard-server/routes-rag-metrics.ts +82 -0
  168. package/extensions/dashboard-server/routes-rag-settings-helpers.ts +314 -0
  169. package/extensions/dashboard-server/routes-rag-settings.ts +147 -97
  170. package/extensions/dashboard-server/routes-repo.ts +5 -1
  171. package/extensions/dashboard-server/routes-sessions.ts +6 -3
  172. package/extensions/dashboard-server/routes-wiki-helpers.ts +126 -0
  173. package/extensions/dashboard-server/routes-wiki.ts +376 -0
  174. package/extensions/dashboard-server/routes.ts +2 -0
  175. package/extensions/dashboard-server/server.ts +18 -2
  176. package/extensions/mega-events/context-handler/afterCompact.ts +44 -1
  177. package/extensions/mega-pipeline/recall.ts +31 -0
  178. package/extensions/mega-runtime/capture-model.ts +5 -2
  179. package/extensions/mega-turn-store.ts +13 -0
  180. package/package.json +1 -1
  181. package/src/config/turns.ts +17 -0
  182. package/src/config.ts +3 -0
  183. package/src/pricing.ts +8 -0
  184. package/src/recall/async.ts +10 -1
  185. package/src/recall/format.ts +15 -2
  186. package/src/recall/hydeTelemetry.ts +44 -0
  187. package/src/recall/sync.ts +34 -2
  188. package/src/recall/types.ts +36 -0
  189. package/src/store/turns/hydeStore.ts +82 -0
  190. package/src/store/turns/index.ts +4 -0
  191. package/src/store/turns/schema.ts +126 -1
  192. package/src/store/turns/sqlite-store/rows.ts +25 -0
  193. package/src/store/turns/sqlite-store/write.ts +20 -2
  194. package/src/store/turns/types.ts +33 -0
  195. package/src/topics/durability.ts +231 -0
  196. package/src/topics/index.ts +7 -1
  197. package/src/topics/store.ts +35 -9
  198. package/src/wiki/curation-helpers.ts +140 -0
  199. package/src/wiki/curation.ts +217 -0
  200. package/src/wiki/incremental.ts +164 -0
  201. package/src/wiki/index.ts +13 -0
  202. package/extensions/dashboard-client/dist/assets/CacheTab-Cqnc7lMg.js +0 -2
  203. package/extensions/dashboard-client/dist/assets/CacheTab-Cqnc7lMg.js.map +0 -1
  204. package/extensions/dashboard-client/dist/assets/EventsTab-tYk3VFAp.js +0 -2
  205. package/extensions/dashboard-client/dist/assets/EventsTab-tYk3VFAp.js.map +0 -1
  206. package/extensions/dashboard-client/dist/assets/HealthTab-D2_kjgxw.js +0 -2
  207. package/extensions/dashboard-client/dist/assets/HealthTab-D2_kjgxw.js.map +0 -1
  208. package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js +0 -2
  209. package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js.map +0 -1
  210. package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js +0 -2
  211. package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js.map +0 -1
  212. package/extensions/dashboard-client/dist/assets/MetricsTab-DT_XfL96.js +0 -2
  213. package/extensions/dashboard-client/dist/assets/MetricsTab-DT_XfL96.js.map +0 -1
  214. package/extensions/dashboard-client/dist/assets/OverviewTab-BY6KZCme.js +0 -2
  215. package/extensions/dashboard-client/dist/assets/OverviewTab-BY6KZCme.js.map +0 -1
  216. package/extensions/dashboard-client/dist/assets/ReposTab-CeS-tpDM.js +0 -2
  217. package/extensions/dashboard-client/dist/assets/ReposTab-CeS-tpDM.js.map +0 -1
  218. package/extensions/dashboard-client/dist/assets/SessionsTab-C30AwyoF.js +0 -70
  219. package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js +0 -2
  220. package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js.map +0 -1
  221. package/extensions/dashboard-client/dist/assets/TimeSavedCard-p55K1tFP.js +0 -2
  222. package/extensions/dashboard-client/dist/assets/TimeSavedCard-p55K1tFP.js.map +0 -1
  223. package/extensions/dashboard-client/dist/assets/TopicsTab-D8FqyAbK.js +0 -2
  224. package/extensions/dashboard-client/dist/assets/TopicsTab-D8FqyAbK.js.map +0 -1
  225. package/extensions/dashboard-client/dist/assets/TurnsTab-ju-nXDys.js +0 -2
  226. package/extensions/dashboard-client/dist/assets/TurnsTab-ju-nXDys.js.map +0 -1
  227. package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js +0 -42
  228. package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js.map +0 -1
  229. package/extensions/dashboard-client/dist/assets/index-CUNn22iV.css +0 -1
  230. package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js +0 -2
  231. package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js.map +0 -1
  232. package/extensions/dashboard-client/src/styles/metrics-extra.css +0 -69
  233. package/extensions/dashboard-client/src/styles/turns.css +0 -142
  234. package/extensions/dashboard-client/src/tabs/SetupTab/RagSettingsCard.tsx +0 -160
@@ -11,14 +11,25 @@
11
11
  "typecheck": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
+ "@radix-ui/react-select": "^2.1.0",
15
+ "@radix-ui/react-switch": "^1.1.0",
16
+ "@radix-ui/react-tabs": "^1.1.0",
17
+ "@radix-ui/react-tooltip": "^1.1.0",
18
+ "class-variance-authority": "^0.7.0",
19
+ "clsx": "^2.1.0",
20
+ "lucide-react": "^0.400.0",
14
21
  "react": "^18.3.1",
15
22
  "react-dom": "^18.3.1",
16
- "recharts": "^2.15.4"
23
+ "recharts": "^2.15.4",
24
+ "tailwind-merge": "^2.5.0"
17
25
  },
18
26
  "devDependencies": {
19
27
  "@types/react": "^18.3.12",
20
28
  "@types/react-dom": "^18.3.1",
21
29
  "@vitejs/plugin-react": "^4.3.4",
30
+ "autoprefixer": "^10.4.0",
31
+ "postcss": "^8.4.0",
32
+ "tailwindcss": "^3.4.0",
22
33
  "typescript": "^5.6.3",
23
34
  "vite": "^5.4.11"
24
35
  },
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * SPRINT-B1: React scaffold with tab routing, header, error boundary.
5
5
  * SPRINT-C1+: tabs wired progressively with real content.
6
+ * SPRINT-V2: NEW_UI flag splits OldDashboard (legacy) from NewDashboard (AppShell).
6
7
  */
7
8
 
8
9
  import React, { useState, useCallback } from "react";
@@ -12,6 +13,15 @@ import { LoadingSpinner } from "./components/LoadingSpinner";
12
13
  import { useApi } from "./hooks/useApi";
13
14
  import { fetchSnapshot } from "./api/client";
14
15
  import type { SnapshotResponse } from "@contracts";
16
+ import { NEW_UI } from "./config";
17
+ import { AppShell } from "./components/layout/AppShell";
18
+ import {
19
+ PRIMARY_TABS,
20
+ ADVANCED_TABS,
21
+ ADVANCED_TAB_IDS as advancedTabIds,
22
+ type TabId,
23
+ } from "./tabs/registry";
24
+ export type { TabId };
15
25
 
16
26
  // Tab components — lazy-loaded. C1 fills Overview + Events; C2/C3 fill the rest.
17
27
  const OverviewTab = React.lazy(() => import("./tabs/OverviewTab"));
@@ -21,105 +31,134 @@ const SetupTab = React.lazy(() => import("./tabs/SetupTab"));
21
31
  const MetricsTab = React.lazy(() => import("./tabs/MetricsTab"));
22
32
  const CacheTab = React.lazy(() => import("./tabs/CacheTab"));
23
33
  const SessionsTab = React.lazy(() => import("./tabs/SessionsTab"));
24
- const TopicsTab = React.lazy(() => import("./tabs/TopicsTab"));
34
+ const WikiTab = React.lazy(() => import("./tabs/WikiTab"));
25
35
  const TurnsTab = React.lazy(() => import("./tabs/TurnsTab"));
26
36
  const MaintenanceTab = React.lazy(() => import("./tabs/MaintenanceTab"));
27
37
  const MemoryMapTab = React.lazy(() => import("./tabs/MemoryMapTab"));
28
38
  const HealthTab = React.lazy(() => import("./tabs/HealthTab"));
29
39
 
30
- export type TabId =
31
- | "overview"
32
- | "repos"
33
- | "events"
34
- | "setup"
35
- | "metrics"
36
- | "cache"
37
- | "sessions"
38
- | "topics"
39
- | "turns"
40
- | "maintenance"
41
- | "memory-map"
42
- | "health";
40
+ interface AppState {
41
+ snapshot: SnapshotResponse | null;
42
+ loading: boolean;
43
+ error: Error | null;
44
+ }
43
45
 
44
- type TabDef = { id: TabId; label: string };
46
+ function TabContent({
47
+ activeTab,
48
+ snapshot,
49
+ loading,
50
+ error,
51
+ }: AppState & { activeTab: TabId }): React.ReactElement {
52
+ return (
53
+ <React.Suspense fallback={<LoadingSpinner />}>
54
+ {activeTab === "overview" && (
55
+ <OverviewTab snapshot={snapshot} loading={loading} error={error} />
56
+ )}
57
+ {activeTab === "repos" && <ReposTab />}
58
+ {activeTab === "events" && <EventsTab />}
59
+ {activeTab === "setup" && <SetupTab />}
60
+ {activeTab === "metrics" && <MetricsTab />}
61
+ {activeTab === "cache" && <CacheTab />}
62
+ {activeTab === "sessions" && <SessionsTab />}
63
+ {activeTab === "wiki" && <WikiTab />}
64
+ {activeTab === "turns" && <TurnsTab />}
65
+ {activeTab === "maintenance" && <MaintenanceTab />}
66
+ {activeTab === "memory-map" && <MemoryMapTab />}
67
+ {activeTab === "health" && <HealthTab />}
68
+ </React.Suspense>
69
+ );
70
+ }
45
71
 
46
- const PRIMARY_TABS: TabDef[] = [
47
- { id: "overview", label: "Overview" },
48
- { id: "cache", label: "Cache" },
49
- { id: "sessions", label: "Sessions" },
50
- { id: "turns", label: "Turns" },
51
- { id: "health", label: "Health" },
52
- ];
72
+ function OldDashboard({
73
+ activeTab,
74
+ setActiveTab,
75
+ snapshot,
76
+ loading,
77
+ error,
78
+ }: AppState & {
79
+ activeTab: TabId;
80
+ setActiveTab: (id: TabId) => void;
81
+ }): React.ReactElement {
82
+ const tier = snapshot?.tier ?? "unknown";
83
+ const version = snapshot?.model?.name ?? "";
53
84
 
54
- const ADVANCED_TABS: TabDef[] = [
55
- { id: "repos", label: "Repos" },
56
- { id: "events", label: "Events" },
57
- { id: "setup", label: "Setup" },
58
- { id: "metrics", label: "Metrics" },
59
- { id: "topics", label: "Topics" },
60
- { id: "maintenance", label: "Maintenance" },
61
- { id: "memory-map", label: "Memory Map" },
62
- ];
85
+ return (
86
+ <ErrorBoundary>
87
+ <div className="dashboard-app">
88
+ <header className="dashboard-header">
89
+ <h1>
90
+ mega-compact dashboard
91
+ <span className="tier">{tier}</span>
92
+ {version && <span className="version-pill">{version}</span>}
93
+ </h1>
94
+ </header>
95
+ <TabBar
96
+ primaryTabs={PRIMARY_TABS}
97
+ advancedTabs={ADVANCED_TABS}
98
+ advancedTabIds={advancedTabIds}
99
+ active={activeTab}
100
+ onTabChange={setActiveTab}
101
+ />
102
+ <main className="dashboard-content">
103
+ <TabContent activeTab={activeTab} snapshot={snapshot} loading={loading} error={error} />
104
+ </main>
105
+ </div>
106
+ </ErrorBoundary>
107
+ );
108
+ }
63
109
 
64
- const advancedTabIds = new Set<TabId>(ADVANCED_TABS.map((t) => t.id));
110
+ function NewDashboard({
111
+ activeTab,
112
+ setActiveTab,
113
+ snapshot,
114
+ loading,
115
+ error,
116
+ }: AppState & {
117
+ activeTab: TabId;
118
+ setActiveTab: (id: TabId) => void;
119
+ }): React.ReactElement {
120
+ return (
121
+ <ErrorBoundary>
122
+ <AppShell active={activeTab} onTabChange={setActiveTab} snapshot={snapshot}>
123
+ <TabContent activeTab={activeTab} snapshot={snapshot} loading={loading} error={error} />
124
+ </AppShell>
125
+ </ErrorBoundary>
126
+ );
127
+ }
65
128
 
66
129
  export default function App(): React.ReactElement {
67
- const [activeTab, setActiveTab] = useState<TabId>("overview");
68
- const {
69
- data: snapshot,
70
- loading,
71
- error,
72
- } = useApi<SnapshotResponse>(
73
- useCallback(() => fetchSnapshot(), []),
74
- {
75
- // Poll every 5s so Overview stays live without SSE. D1 will add retry/stale.
76
- pollInterval: 5000,
77
- },
78
- );
130
+ const [activeTab, setActiveTab] = useState<TabId>("overview");
131
+ const {
132
+ data: snapshot,
133
+ loading,
134
+ error,
135
+ } = useApi<SnapshotResponse>(
136
+ useCallback(() => fetchSnapshot(), []),
137
+ {
138
+ // Poll every 5s so Overview stays live without SSE. D1 will add retry/stale.
139
+ pollInterval: 5000,
140
+ },
141
+ );
79
142
 
80
- const tier = snapshot?.tier ?? "unknown";
81
- const version = snapshot?.model?.name ?? "";
143
+ if (NEW_UI()) {
144
+ return (
145
+ <NewDashboard
146
+ activeTab={activeTab}
147
+ setActiveTab={setActiveTab}
148
+ snapshot={snapshot}
149
+ loading={loading}
150
+ error={error}
151
+ />
152
+ );
153
+ }
82
154
 
83
- return (
84
- <ErrorBoundary>
85
- <div className="dashboard-app">
86
- <header className="dashboard-header">
87
- <h1>
88
- mega-compact dashboard
89
- <span className="tier">{tier}</span>
90
- {version && <span className="version-pill">{version}</span>}
91
- </h1>
92
- </header>
93
- <TabBar
94
- primaryTabs={PRIMARY_TABS}
95
- advancedTabs={ADVANCED_TABS}
96
- advancedTabIds={advancedTabIds}
97
- active={activeTab}
98
- onTabChange={setActiveTab}
99
- />
100
- <main className="dashboard-content">
101
- <React.Suspense fallback={<LoadingSpinner />}>
102
- {activeTab === "overview" && (
103
- <OverviewTab
104
- snapshot={snapshot}
105
- loading={loading}
106
- error={error}
107
- />
108
- )}
109
- {activeTab === "repos" && <ReposTab />}
110
- {activeTab === "events" && <EventsTab />}
111
- {activeTab === "setup" && <SetupTab />}
112
- {activeTab === "metrics" && <MetricsTab />}
113
- {activeTab === "cache" && <CacheTab />}
114
- {activeTab === "sessions" && <SessionsTab />}
115
- {activeTab === "topics" && <TopicsTab />}
116
- {activeTab === "turns" && <TurnsTab />}
117
- {activeTab === "maintenance" && <MaintenanceTab />}
118
- {activeTab === "memory-map" && <MemoryMapTab />}
119
- {activeTab === "health" && <HealthTab />}
120
- </React.Suspense>
121
- </main>
122
- </div>
123
- </ErrorBoundary>
124
- );
155
+ return (
156
+ <OldDashboard
157
+ activeTab={activeTab}
158
+ setActiveTab={setActiveTab}
159
+ snapshot={snapshot}
160
+ loading={loading}
161
+ error={error}
162
+ />
163
+ );
125
164
  }
@@ -48,9 +48,18 @@ import type {
48
48
  SetupConfigureResponse,
49
49
  EmbedderHealthResponse,
50
50
  RaptorTreeResponse,
51
- RagSettingsResponse,
52
- RagSettingsRequest,
53
- RagSettingsResponsePost,
51
+ SettingsResponse,
52
+ SettingsUpdateRequest,
53
+ SettingsResponsePost,
54
+ RagMetricsResponse,
55
+ WikiIndexResponse,
56
+ WikiPageResponse,
57
+ CurationResult,
58
+ RenameTopicRequest,
59
+ MergeTopicsRequest,
60
+ SplitTopicRequest,
61
+ TopicTimelineResponse,
62
+ TopicEvolutionResponse,
54
63
  } from "@contracts";
55
64
 
56
65
  /** Error thrown when a dashboard API response is not 2xx. */
@@ -329,14 +338,104 @@ export function fetchEmbedderHealth(): Promise<EmbedderHealthResponse> {
329
338
 
330
339
  // ─── RAG Settings ─────────────────────────────────────────────────────
331
340
 
332
- /** GET /api/rag-settings — read the current state of all RAG feature flags. */
333
- export function fetchRagSettings(): Promise<RagSettingsResponse> {
334
- return getJson<RagSettingsResponse>(ENDPOINTS.ragSettings.path);
341
+ /** GET /api/rag-settings — read all adjustable settings grouped by category. */
342
+ export function fetchSettings(): Promise<SettingsResponse> {
343
+ return getJson<SettingsResponse>(ENDPOINTS.ragSettings.path);
335
344
  }
336
345
 
337
- /** POST /api/rag-settings — toggle RAG feature flags (writes _DISABLED env vars). */
346
+ /** POST /api/rag-settings — update a single setting (writes the env file). */
347
+ export function postSetting(
348
+ body: SettingsUpdateRequest,
349
+ ): Promise<SettingsResponsePost> {
350
+ return postJson<SettingsResponsePost>(ENDPOINTS.ragSettingsUpdate.path, body);
351
+ }
352
+
353
+ /** @deprecated Use fetchSettings instead. */
354
+ export function fetchRagSettings(): Promise<SettingsResponse> {
355
+ return fetchSettings();
356
+ }
357
+
358
+ /** @deprecated Use postSetting instead. */
338
359
  export function postRagSettings(
339
- body: RagSettingsRequest,
340
- ): Promise<RagSettingsResponsePost> {
341
- return postJson<RagSettingsResponsePost>(ENDPOINTS.ragSettingsUpdate.path, body);
360
+ body: SettingsUpdateRequest,
361
+ ): Promise<SettingsResponsePost> {
362
+ return postSetting(body);
363
+ }
364
+
365
+ /** GET /api/rag-metrics — HyDE + recall-quality telemetry aggregates (H2). */
366
+ export function fetchRagMetrics(): Promise<RagMetricsResponse> {
367
+ return getJson<RagMetricsResponse>(ENDPOINTS.ragMetrics.path);
368
+ }
369
+
370
+ // ─── Wiki Revival (W3) ────────────────────────────────────────────────
371
+
372
+ /** GET /api/wiki/index — wiki landing (topics with resolved labels + badges). */
373
+ export function fetchWikiIndex(): Promise<WikiIndexResponse> {
374
+ return getJson<WikiIndexResponse>(ENDPOINTS.wikiIndex.path);
375
+ }
376
+
377
+ /** GET /api/wiki/topic/:topicId — single topic page + provenance. */
378
+ export function fetchWikiTopic(topicId: string): Promise<WikiPageResponse> {
379
+ return getJson<WikiPageResponse>(
380
+ ENDPOINTS.wikiTopic.path.replace(
381
+ ":topicId",
382
+ encodeURIComponent(topicId),
383
+ ),
384
+ );
385
+ }
386
+
387
+ /** PUT /api/wiki/topic/:topicId/label — rename a topic (user curation). */
388
+ export function renameTopic(
389
+ topicId: string,
390
+ label: string,
391
+ ): Promise<CurationResult> {
392
+ return putJson<CurationResult>(
393
+ ENDPOINTS.renameTopic.path.replace(
394
+ ":topicId",
395
+ encodeURIComponent(topicId),
396
+ ),
397
+ { label } satisfies RenameTopicRequest,
398
+ );
399
+ }
400
+
401
+ /** POST /api/wiki/merge — merge source topic into target. */
402
+ export function mergeTopics(
403
+ sourceTopicId: string,
404
+ targetTopicId: string,
405
+ ): Promise<CurationResult> {
406
+ return postJson<CurationResult>(ENDPOINTS.mergeTopics.path, {
407
+ sourceTopicId,
408
+ targetTopicId,
409
+ } satisfies MergeTopicsRequest);
410
+ }
411
+
412
+ /** POST /api/wiki/topic/:topicId/split — carve listed memories into a new topic. */
413
+ export function splitTopic(
414
+ topicId: string,
415
+ memoryIds: string[],
416
+ ): Promise<CurationResult> {
417
+ return postJson<CurationResult>(
418
+ ENDPOINTS.splitTopic.path.replace(
419
+ ":topicId",
420
+ encodeURIComponent(topicId),
421
+ ),
422
+ { memoryIds } satisfies SplitTopicRequest,
423
+ );
424
+ }
425
+
426
+ /** GET /api/wiki/topic/:topicId/timeline — per-topic memory-addition buckets. */
427
+ export function fetchTopicTimeline(
428
+ topicId: string,
429
+ ): Promise<TopicTimelineResponse> {
430
+ return getJson<TopicTimelineResponse>(
431
+ ENDPOINTS.topicTimeline.path.replace(
432
+ ":topicId",
433
+ encodeURIComponent(topicId),
434
+ ),
435
+ );
436
+ }
437
+
438
+ /** GET /api/wiki/evolution — global D3 topic-evolution graph feed. */
439
+ export function fetchTopicEvolution(): Promise<TopicEvolutionResponse> {
440
+ return getJson<TopicEvolutionResponse>(ENDPOINTS.topicEvolution.path);
342
441
  }
@@ -10,6 +10,7 @@
10
10
  import type React from "react";
11
11
  import type { ServerEntry } from "@contracts";
12
12
  import { fmtTokens } from "@/utils/format.ts";
13
+ import { Card, CardContent } from "../components/ui/card";
13
14
 
14
15
  export interface ActiveReposTableProps {
15
16
  servers: ServerEntry[];
@@ -44,18 +45,24 @@ export function ActiveReposTable({
44
45
  servers,
45
46
  }: ActiveReposTableProps): React.ReactElement {
46
47
  return (
47
- <div className="active-repos-section">
48
- <p className="legend-note">
48
+ <Card>
49
+ <CardContent>
50
+ <p className="mb-3 text-xs text-muted-foreground">
49
51
  Repos seen within the last 30 minutes, with their per-repo cache-hit,
50
52
  compaction, and time-saved (est.) totals pulled live from each
51
53
  repo&apos;s dashboard.json.
52
54
  </p>
53
- <div className="table-scroll">
54
- <table className="active-repos-table">
55
+ <div className="overflow-x-auto">
56
+ <table className="w-full border-collapse text-sm">
55
57
  <thead>
56
58
  <tr>
57
59
  {HEADERS.map((h, i) => (
58
- <th key={h} className={i >= 3 && i !== 4 ? "num" : undefined}>
60
+ <th
61
+ key={h}
62
+ className={`border-b border-border px-3 py-2 text-left font-medium text-muted-foreground${
63
+ i >= 3 && i !== 4 ? " text-right" : ""
64
+ }`}
65
+ >
59
66
  {h}
60
67
  </th>
61
68
  ))}
@@ -64,7 +71,7 @@ export function ActiveReposTable({
64
71
  <tbody>
65
72
  {servers.length === 0 && (
66
73
  <tr>
67
- <td colSpan={HEADERS.length} className="repo-empty">
74
+ <td colSpan={HEADERS.length} className="px-3 py-4 text-muted-foreground">
68
75
  No active repositories.
69
76
  </td>
70
77
  </tr>
@@ -132,6 +139,7 @@ export function ActiveReposTable({
132
139
  </tbody>
133
140
  </table>
134
141
  </div>
135
- </div>
142
+ </CardContent>
143
+ </Card>
136
144
  );
137
145
  }
@@ -10,6 +10,7 @@
10
10
 
11
11
  import type React from "react";
12
12
  import type { ActiveSession, SessionSeries } from "@contracts";
13
+ import { Card, CardContent } from "../components/ui/card";
13
14
 
14
15
  export interface ActiveSessionsTableProps {
15
16
  /** Active sessions, sorted by lastSeen descending (from /api/sessions). */
@@ -123,63 +124,74 @@ export function ActiveSessionsTable({
123
124
  const now = Date.now();
124
125
 
125
126
  return (
126
- <div className="sessions-table-scroll">
127
- <table className="sessions-table">
128
- <thead>
129
- <tr>
130
- {HEADERS.map((h, i) => (
131
- <th
132
- key={h}
133
- className={i >= 3 && i !== 6 ? "num" : undefined}
134
- >
135
- {h}
136
- </th>
137
- ))}
138
- </tr>
139
- </thead>
140
- <tbody>
141
- {sessions.length === 0 && (
142
- <tr className="sessions-empty-row">
143
- <td colSpan={HEADERS.length}>No active sessions.</td>
144
- </tr>
145
- )}
146
- {sessions.map((s) => {
147
- const srs = seriesById.get(s.sessionId);
148
- const sparkPts =
149
- srs?.data.map((d) => d.tokens) ?? [];
150
- const color = srs?.color ?? "#58a6ff";
151
- return (
152
- <tr key={`${s.pid}:${s.sessionId}`}>
153
- <td className="num">{s.pid}</td>
154
- <td title={s.repoRoot ?? undefined}>
155
- {s.displayName || s.repoRoot || "\u2014"}
156
- </td>
157
- <td>{s.model ?? "\u2014"}</td>
158
- <td className="num">
159
- <span className={`sessions-pct-pill ${pctClass(s.percent)}`}>
160
- {fmtPct(s.percent)}
161
- </span>
162
- </td>
163
- <td className="num">
164
- {fmtWindow(s.tokens, s.ctxWindow)}
165
- </td>
166
- <td className="num">{fmtAge(now - s.lastSeen)}</td>
167
- <td
168
- title={s.stateDir ?? undefined}
169
- className="sessions-meta"
127
+ <Card>
128
+ <CardContent>
129
+ <div className="overflow-x-auto">
130
+ <table className="w-full border-collapse text-sm">
131
+ <thead>
132
+ <tr>
133
+ {HEADERS.map((h, i) => (
134
+ <th
135
+ key={h}
136
+ className={`border-b border-border px-3 py-2 text-left font-medium text-muted-foreground${
137
+ i >= 3 && i !== 6 ? " text-right" : ""
138
+ }`}
170
139
  >
171
- {s.stateDir
172
- ? s.stateDir.split("/").pop() || s.stateDir
173
- : "\u2014"}
174
- </td>
175
- <td>
176
- <Sparkline points={sparkPts} color={color} />
140
+ {h}
141
+ </th>
142
+ ))}
143
+ </tr>
144
+ </thead>
145
+ <tbody>
146
+ {sessions.length === 0 && (
147
+ <tr>
148
+ <td colSpan={HEADERS.length} className="px-3 py-4 text-muted-foreground">
149
+ No active sessions.
177
150
  </td>
178
151
  </tr>
179
- );
180
- })}
181
- </tbody>
182
- </table>
183
- </div>
152
+ )}
153
+ {sessions.map((s) => {
154
+ const srs = seriesById.get(s.sessionId);
155
+ const sparkPts =
156
+ srs?.data.map((d) => d.tokens) ?? [];
157
+ const color = srs?.color ?? "#58a6ff";
158
+ return (
159
+ <tr
160
+ key={`${s.pid}:${s.sessionId}`}
161
+ className="border-b border-border/50 hover:bg-bg-elevated/40"
162
+ >
163
+ <td className="px-3 py-2 text-right font-mono">{s.pid}</td>
164
+ <td className="px-3 py-2" title={s.repoRoot ?? undefined}>
165
+ {s.displayName || s.repoRoot || "\u2014"}
166
+ </td>
167
+ <td className="px-3 py-2">{s.model ?? "\u2014"}</td>
168
+ <td className="px-3 py-2 text-right">
169
+ <span className={`sessions-pct-pill ${pctClass(s.percent)}`}>
170
+ {fmtPct(s.percent)}
171
+ </span>
172
+ </td>
173
+ <td className="px-3 py-2 text-right">
174
+ {fmtWindow(s.tokens, s.ctxWindow)}
175
+ </td>
176
+ <td className="px-3 py-2 text-right">{fmtAge(now - s.lastSeen)}</td>
177
+ <td
178
+ title={s.stateDir ?? undefined}
179
+ className="px-3 py-2 font-mono text-muted-foreground"
180
+ >
181
+ {s.stateDir
182
+ ? s.stateDir.split("/").pop() || s.stateDir
183
+ : "\u2014"}
184
+ </td>
185
+ <td className="px-3 py-2">
186
+ <Sparkline points={sparkPts} color={color} />
187
+ </td>
188
+ </tr>
189
+ );
190
+ })}
191
+ </tbody>
192
+ </table>
193
+ </div>
194
+ </CardContent>
195
+ </Card>
184
196
  );
185
197
  }
@@ -12,6 +12,7 @@
12
12
 
13
13
  import type React from "react";
14
14
  import type { PerfResponse, CacheHitSample } from "@contracts";
15
+ import { Card, CardContent, CardHeader, CardTitle } from "../components/ui/card";
15
16
 
16
17
  export interface CacheHitRateTrendCardProps {
17
18
  perf: PerfResponse;
@@ -45,19 +46,21 @@ export const CacheHitRateTrendCard: React.FC<CacheHitRateTrendCardProps> = ({
45
46
  c.samples && c.samples.length > 0 ? c.samples : [];
46
47
 
47
48
  return (
48
- <div className="ov-card cache-trend-card">
49
- <h3 className="ov-card-title">Cache Hit-Rate Trend</h3>
50
-
49
+ <Card className="electric-hover">
50
+ <CardHeader>
51
+ <CardTitle>Cache Hit-Rate Trend</CardTitle>
52
+ </CardHeader>
53
+ <CardContent>
51
54
  {/* Metric summary */}
52
- <div className="ov-perf-summary">
53
- <div className="ov-perf-stat">
54
- Avg: <strong>{fmtPct(c.avg)}</strong>
55
+ <div className="mb-3 flex gap-4 text-sm text-muted-foreground">
56
+ <div>
57
+ Avg: <strong className="text-foreground">{fmtPct(c.avg)}</strong>
55
58
  </div>
56
- <div className="ov-perf-stat">
57
- Latest: <strong>{fmtPct(c.latest)}</strong>
59
+ <div>
60
+ Latest: <strong className="text-foreground">{fmtPct(c.latest)}</strong>
58
61
  </div>
59
- <div className="ov-perf-stat">
60
- Samples: <strong>{c.n}</strong>
62
+ <div>
63
+ Samples: <strong className="text-foreground">{c.n}</strong>
61
64
  </div>
62
65
  </div>
63
66
 
@@ -83,7 +86,7 @@ export const CacheHitRateTrendCard: React.FC<CacheHitRateTrendCardProps> = ({
83
86
  );
84
87
  })}
85
88
  </div>
86
- <div className="ov-card-footer">
89
+ <div className="mt-1 text-xs text-muted-foreground">
87
90
  {samples.length} sample{samples.length !== 1 ? "s" : ""} over{" "}
88
91
  {samples.length > 1
89
92
  ? `${Math.round(
@@ -93,8 +96,9 @@ export const CacheHitRateTrendCard: React.FC<CacheHitRateTrendCardProps> = ({
93
96
  </div>
94
97
  </>
95
98
  ) : (
96
- <div className="ov-empty-state">No cache-hit samples yet</div>
99
+ <div className="text-sm text-muted-foreground">No cache-hit samples yet</div>
97
100
  )}
98
- </div>
101
+ </CardContent>
102
+ </Card>
99
103
  );
100
104
  };