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
@@ -1 +0,0 @@
1
- :root{--bg: #0d1117;--panel: #161b22;--border: #30363d;--text: #e6edf3;--muted: #8b949e;--accent: #58a6ff;--ok: #3fb950;--warn: #d29922;--err: #f85149;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:clamp(13px,.9vw,16px)}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text)}.dashboard-app{max-width:min(1600px,96vw);margin:0 auto;padding:clamp(8px,2vw,24px)}.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:clamp(8px,1.5vw,16px)}.dashboard-header h1{font-size:clamp(16px,1.4vw,22px);font-weight:600;margin:0 0 clamp(8px,1vw,16px)}.dashboard-header .tier,.dashboard-header .version-pill{display:inline-block;margin-left:8px;padding:2px 8px;font-size:clamp(10px,.8vw,12px);border-radius:10px;background:var(--panel);border:1px solid var(--border);color:var(--muted)}.dashboard-header .tier{color:var(--accent)}.tab-bar{display:flex;gap:4px;border-bottom:1px solid var(--border);margin-bottom:clamp(8px,1vw,16px);overflow-x:auto;flex-wrap:nowrap}.tab-bar button{background:none;border:none;color:var(--muted);padding:8px 14px;cursor:pointer;font-size:clamp(12px,.85vw,14px);border-bottom:2px solid transparent;white-space:nowrap}.tab-bar button.active{color:var(--text);border-bottom-color:var(--accent)}.tab-bar button:hover{color:var(--text)}.tab-bar .advanced-toggle{background:none;border:none;color:var(--muted);padding:8px 14px;cursor:pointer;font-size:clamp(12px,.85vw,14px);border-bottom:2px solid transparent;white-space:nowrap;margin-left:6px}.tab-bar .advanced-toggle:hover{color:var(--text)}.tab-bar .advanced-toggle[aria-expanded=true]{color:var(--text);border-bottom-color:var(--border)}.tab-bar .advanced-tabs{display:flex;gap:4px;flex-basis:100%;border-top:1px dashed var(--border);padding-top:6px;margin-top:-1px}.dashboard-content{min-height:400px}.loading-spinner{display:flex;align-items:center;justify-content:center;padding:48px;color:var(--muted)}.error-fallback{padding:24px;border:1px solid var(--err);border-radius:8px;background:#f8514914}.error-fallback button{margin-top:12px;padding:6px 14px;background:var(--panel);border:1px solid var(--border);color:var(--text);border-radius:6px;cursor:pointer}.tab-stub{padding:32px;color:var(--muted);border:1px dashed var(--border);border-radius:8px;text-align:center}.repos{width:100%;border-collapse:collapse;font-size:clamp(12px,.8vw,14px)}.repos th,.repos td{padding:6px 10px;border-bottom:1px solid var(--border-soft, var(--border));text-align:left}.repos th{background:var(--bg);position:sticky;top:0}.table-wrap{overflow-x:auto}@media (max-width: 640px){.card-grid{grid-template-columns:1fr}.tab-bar button{padding:6px 10px;font-size:12px}}@media (min-width: 641px) and (max-width: 1024px){.card-grid{grid-template-columns:repeat(2,1fr)}}@media (min-width: 1025px){.card-grid{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}}@media (min-width: 1601px){.dashboard-app{max-width:min(1800px,96vw)}.card-grid{grid-template-columns:repeat(4,1fr)}}.overview-tab{display:flex;flex-direction:column;gap:12px}.overview-header{display:flex;align-items:center;gap:12px}.tier-pill{padding:2px 10px;font-size:12px;border-radius:10px;background:var(--panel);border:1px solid var(--border);color:var(--accent)}.updated{color:var(--muted);font-size:12px}.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px}.card{padding:14px 16px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.card h3{margin:0 0 10px;font-size:13px;color:var(--muted);font-weight:600}.gauge-bar{height:10px;background:var(--bg);border-radius:5px;overflow:hidden;border:1px solid var(--border)}.gauge-fill{height:100%;transition:width .4s ease}.gauge-green .gauge-fill{background:var(--ok)}.gauge-yellow .gauge-fill{background:var(--warn)}.gauge-red .gauge-fill{background:var(--err)}.gauge-label{margin:8px 0 0;font-size:12px;color:var(--muted)}.stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.stat{display:flex;flex-direction:column;gap:2px}.stat-label{font-size:11px;color:var(--muted);text-transform:uppercase}.stat-value{font-size:16px;font-weight:600}.stat-highlight .stat-value{color:var(--ok)}.bullet-row{display:flex;gap:14px;margin-bottom:8px}.bullet{display:flex;align-items:center;gap:6px;font-size:13px}.bullet-dot{width:8px;height:8px;border-radius:50%;background:var(--muted)}.bullet-on .bullet-dot{background:var(--ok);box-shadow:0 0 6px var(--ok)}.bullet-off .bullet-dot{background:var(--border)}.bullet-on .bullet-label{color:var(--text)}.bullet-off .bullet-label{color:var(--muted)}.trigger-detail{margin:4px 0;font-size:12px;color:var(--muted)}.state-badge{display:inline-block;padding:2px 10px;font-size:12px;border-radius:10px;background:var(--bg);border:1px solid var(--border)}.state-idle,.state-none{color:var(--muted)}.state-compacting{color:var(--warn);border-color:var(--warn)}.persisted-tag{margin-left:8px;font-size:11px;color:var(--ok)}.events-tab{display:flex;flex-direction:column;gap:10px}.events-header{display:flex;align-items:center;gap:14px}.sse-status{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.sse-dot{width:8px;height:8px;border-radius:50%;background:var(--muted)}.sse-connected .sse-dot{background:var(--ok);box-shadow:0 0 6px var(--ok)}.sse-connecting .sse-dot{background:var(--warn)}.sse-disconnected .sse-dot,.sse-error .sse-dot{background:var(--err)}.event-count{color:var(--muted);font-size:12px}.event-filters{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:8px}.filter-chip{padding:3px 10px;font-size:11px;border:1px solid var(--border);background:var(--bg);color:var(--muted);border-radius:12px;cursor:pointer}.filter-chip.active{color:var(--text);border-color:var(--accent);background:var(--panel)}.event-list{list-style:none;margin:0;padding:0;max-height:60vh;overflow-y:auto}.event-row{display:grid;grid-template-columns:70px 150px 1fr;gap:8px;padding:6px 10px;border-bottom:1px solid var(--border);font-size:12px;cursor:pointer}.event-row:hover{background:var(--panel)}.ev-time{color:var(--muted)}.ev-type{font-size:11px;padding:1px 6px;border-radius:8px;background:var(--bg);border:1px solid var(--border);color:var(--muted);text-align:center}.ev-compact .ev-type{color:var(--accent);border-color:var(--accent)}.ev-trigger .ev-type{color:var(--warn);border-color:var(--warn)}.ev-tier .ev-type{color:var(--muted)}.ev-checkpoint .ev-type{color:var(--ok);border-color:var(--ok)}.ev-recall .ev-type{color:#d2a8ff;border-color:#d2a8ff}.ev-config .ev-type{color:var(--text)}.ev-crew .ev-type{color:#79c0ff;border-color:#79c0ff}.ev-game .ev-type{color:var(--warn)}.ev-summary{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ev-detail{grid-column:1 / -1;margin:6px 0 0;padding:8px;background:var(--bg);border-radius:4px;font-size:11px;color:var(--muted);white-space:pre-wrap}.event-empty{padding:24px;color:var(--muted);text-align:center}@media (max-width: 768px){.card-grid{grid-template-columns:1fr}.event-row{grid-template-columns:60px 110px 1fr;font-size:11px}}.summary-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:16px}.tile{display:flex;flex-direction:column;gap:4px;padding:12px 14px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.tile-label{font-size:11px;color:var(--muted);text-transform:uppercase}.tile-value{font-size:20px;font-weight:600}.tile-highlight .tile-value{color:var(--ok)}.repo-table-wrap{overflow-x:auto}.repo-search{width:100%;padding:8px 10px;margin-bottom:10px;background:var(--panel);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:13px}.repo-table{width:100%;border-collapse:collapse;font-size:13px}.repo-table th{text-align:left;padding:6px 10px;border-bottom:1px solid var(--border)}.repo-table td{padding:8px 10px;border-bottom:1px solid var(--border)}.repo-table tr{cursor:pointer}.repo-table tbody tr:hover{background:var(--panel)}.sort-header{background:none;border:none;color:var(--muted);font-size:12px;font-weight:600;cursor:pointer;padding:0}.sort-header.active-asc,.sort-header.active-desc{color:var(--text)}.sort-arrow{color:var(--accent)}.repo-name{font-weight:600}.repo-model{color:var(--muted)}.modal-backdrop{position:fixed;inset:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:100}.modal-card{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:20px 24px;max-width:560px;width:90%;max-height:80vh;overflow-y:auto}.modal-header{display:flex;justify-content:space-between;align-items:center}.modal-header h2{margin:0;font-size:18px}.modal-close{background:none;border:none;color:var(--muted);font-size:22px;cursor:pointer;padding:0 4px}.modal-close:hover{color:var(--text)}.modal-path{font-size:11px;color:var(--muted);margin:4px 0 12px;word-break:break-all}.modal-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}.modal-stat{display:flex;flex-direction:column;gap:2px}.modal-label{font-size:11px;color:var(--muted);text-transform:uppercase}.modal-value{font-size:16px;font-weight:600}.modal-highlight .modal-value{color:var(--ok)}.modal-card h3{font-size:13px;color:var(--muted);margin:16px 0 6px}.modal-dl{display:grid;grid-template-columns:130px 1fr;gap:4px 12px;margin:0}.modal-dl dt{color:var(--muted);font-size:12px}.modal-dl dd{margin:0;font-size:13px}.model-badge{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,160px),1fr));gap:8px;padding:12px 14px;background:var(--panel);border:1px solid var(--border);border-radius:8px;margin-bottom:12px}.model-field{display:flex;flex-direction:column;gap:2px}.model-field-label{font-size:11px;color:var(--muted);text-transform:uppercase}.model-field-value{font-size:14px;font-weight:600}.perf-chart{display:flex;flex-direction:column;gap:12px}.perf-header{display:flex;justify-content:space-between;align-items:center}.perf-header h3{margin:0;font-size:13px;color:var(--muted)}.perf-window{font-size:11px;color:var(--muted)}.perf-grid,.perf-resources{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px}.perf-resources{padding-top:10px;border-top:1px solid var(--border)}.perf-metric{display:flex;flex-direction:column;gap:4px;padding:10px 12px;background:var(--panel);border:1px solid var(--border);border-radius:6px}.perf-label{font-size:11px;color:var(--muted)}.perf-value{font-size:15px;font-weight:600}.perf-bar-track{height:6px;background:var(--bg);border-radius:3px;overflow:hidden}.perf-bar-fill{height:100%;transition:width .4s ease}.perf-blue .perf-bar-fill{background:var(--accent)}.perf-purple .perf-bar-fill{background:#d2a8ff}.perf-green .perf-bar-fill{background:var(--ok)}.perf-yellow .perf-bar-fill{background:var(--warn)}.perf-diag{display:flex;flex-wrap:wrap;gap:14px;padding-top:10px;border-top:1px solid var(--border)}@media (max-width: 768px){.modal-grid,.model-badge{grid-template-columns:1fr 1fr}}.section-header{font-size:13px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:20px 0 10px;font-weight:600}.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}.active-repos-table,.savings-table{width:100%;border-collapse:collapse;font-size:13px}.active-repos-table th,.savings-table th{text-align:left;padding:6px 10px;border-bottom:1px solid var(--border);white-space:nowrap}.active-repos-table th.num,.savings-table th.num{text-align:right}.active-repos-table td,.savings-table td{padding:6px 10px;border-bottom:1px solid var(--border);white-space:nowrap}.active-repos-table td.num,.savings-table td.num{text-align:right;font-family:monospace}.active-repos-table tbody tr:hover,.savings-table tbody tr:hover{background:var(--panel)}.savings-table .repo-model{font-weight:600}.repo-empty{text-align:center;color:var(--muted);padding:24px}.active-repos-section{margin-bottom:8px}.savings-by-model{margin-bottom:16px}@media (max-width: 640px){.active-repos-table{min-width:900px}.savings-table{min-width:1200px}}@media (min-width: 641px) and (max-width: 1024px){.savings-table{min-width:1000px}}.overview-card-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}.ov-stat-row{display:flex;justify-content:space-between;align-items:baseline;padding:4px 0;border-bottom:1px solid var(--border);font-size:clamp(13px,1vw,17px)}.ov-stat-label{color:var(--muted);font-size:12px;cursor:help}.ov-stat-value{font-weight:600;color:var(--text);font-family:monospace}.ov-stat-value-green{color:var(--ok)}.ov-stat-value-yellow{color:var(--warn)}.ov-stat-value-red{color:var(--err)}.ov-value-ok{color:var(--ok)!important}.ov-compression-meter{margin-top:10px}.meter-track{height:clamp(6px,.6vw,10px);background:var(--bg);border-radius:5px;overflow:hidden;border:1px solid var(--border)}.meter-fill{height:100%;transition:width .4s ease;border-radius:4px}.meter-green{background:var(--ok)}.meter-yellow{background:var(--warn)}.meter-red{background:var(--err)}.meter-sub{display:block;margin-top:4px;font-size:11px;color:var(--muted)}.bullet-na .bullet-dot{background:var(--warn);box-shadow:0 0 6px var(--warn)}.bullet-na .bullet-label{color:var(--warn)}.trigger-state-text{margin:6px 0 0;font-size:12px;color:var(--muted)}.data-safety-card .safe-note{margin:10px 0 0;padding:8px;font-size:11px;color:var(--muted);background:#3fb9500f;border-radius:6px;border:1px solid rgba(63,185,80,.2)}.model-cost-card .ov-cost-usd{font-size:clamp(16px,1.4vw,22px);font-weight:700;color:#a371f7;margin-bottom:2px}.model-cost-card .ov-cost-sub{font-size:12px;color:var(--muted);margin-bottom:8px}.crew-card .ov-stat-value{font-family:inherit}.legend-card{grid-column:1 / -1}.legend-card details{cursor:pointer}.legend-card summary{font-size:13px;color:var(--muted);font-weight:600;margin-bottom:4px}.legend-list{margin:8px 0;padding-left:20px;font-size:12px;color:var(--muted);line-height:1.6}.legend-list li{margin-bottom:4px}.legend-list b{color:var(--text)}.legend-note{font-size:11px;color:var(--dim);font-style:italic}.cache-tab{display:flex;flex-direction:column;gap:12px}@media (max-width: 640px){.overview-card-grid{grid-template-columns:1fr}}@media (min-width: 1025px){.overview-card-grid{grid-template-columns:repeat(3,1fr)}}@media (min-width: 1601px){.overview-card-grid{grid-template-columns:repeat(4,1fr);font-size:clamp(13px,.9vw,16px)}}.config-tab{display:flex;flex-direction:column;gap:16px}.config-settings,.config-display{padding:14px 16px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.config-settings h3,.config-display h3{margin:0 0 12px;font-size:clamp(12px,1vw,14px);color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.5px}.settings-row{margin-bottom:10px}.settings-row:last-child{margin-bottom:0}.settings-row label{display:flex;align-items:center;gap:8px;font-size:clamp(13px,.9vw,15px);color:var(--text);cursor:pointer}.settings-row select{padding:4px 8px;font-size:clamp(12px,.85vw,14px);background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;cursor:pointer}.settings-row select:disabled{opacity:.5;cursor:not-allowed}.settings-row input[type=checkbox]{width:16px;height:16px;cursor:pointer}.config-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:10px}.config-item{display:flex;flex-direction:column;gap:3px;padding:8px 10px;background:var(--bg);border:1px solid var(--border);border-radius:6px}.config-label{font-size:clamp(11px,.75vw,13px);color:var(--muted);text-transform:uppercase;letter-spacing:.4px}.config-value{font-size:clamp(13px,1vw,16px);font-weight:600;color:var(--text)}.event-category-filter{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.category-chip{padding:3px 10px;font-size:clamp(11px,.75vw,13px);border:1px solid var(--border);background:var(--bg);color:var(--muted);border-radius:12px;cursor:pointer;text-transform:capitalize;transition:color .15s,border-color .15s,background .15s}.category-chip:hover{color:var(--text)}.category-chip.active{color:var(--text);border-color:var(--accent);background:var(--panel)}@media (max-width: 640px){.config-grid{grid-template-columns:1fr}.settings-row label{flex-direction:column;align-items:flex-start;gap:4px}.settings-row select{width:100%}}.perf-cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:12px;margin-top:12px}.perf-card{display:flex;flex-direction:column;gap:8px;padding:14px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.perf-card-title{margin:0 0 4px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}.perf-card-body{display:flex;flex-direction:column;gap:6px}.perf-card-note{font-size:11px;color:var(--muted);font-style:italic;margin-top:2px}.perf-card-body .perf-metric{padding:6px 8px;background:transparent;border:none;border-radius:0}.perf-footer{font-size:11px;color:var(--muted);margin-top:10px;padding-top:8px;border-top:1px solid var(--border)}@media (max-width: 640px){.perf-cards-grid{grid-template-columns:1fr}}:root{--mega: #f0883e;--mega-gold: #ffd700;--game-blue: #1f6feb;--game-purple: #a371f7}.game-tab{display:flex;flex-direction:column;gap:12px}.game-mode-on{--accent: var(--mega)}.mega-cache-banner{display:block;background:linear-gradient(135deg,var(--mega),var(--mega-gold));color:#1a1006;font-weight:700;padding:10px 14px;border-radius:8px;margin:12px 0;font-size:clamp(13px,1vw,16px);animation:mega-banner-shimmer 3s ease-in-out infinite}@keyframes mega-banner-shimmer{0%,to{filter:brightness(1)}50%{filter:brightness(1.15)}}.mega-cache-toast{display:none;position:fixed;top:16px;left:50%;transform:translate(-50%);background:var(--mega);color:#1a1006;font-weight:700;padding:10px 18px;border-radius:8px;z-index:1000;box-shadow:0 4px 20px #0008;max-width:92vw}.mega-cache-toast.show{display:block;animation:mega-flash .6s ease-in-out 2}@keyframes mega-flash{0%{background:transparent}25%{background:var(--mega-gold)}to{background:transparent}}.achievement-tile{display:none;background:linear-gradient(135deg,var(--mega),var(--mega-gold));color:#1a1006;font-weight:700;padding:12px 16px;border-radius:8px;margin:12px 0;box-shadow:0 0 16px #f0883e88;font-size:clamp(13px,1vw,16px)}.achievement-tile.unlocked{display:block}.achievement-tile .ach-detail{display:block;font-weight:500;font-size:12px;margin-top:4px}.game-leaderboards{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px}.lb-card{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:14px}.lb-card h3{font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:0 0 10px;font-weight:600;display:flex;align-items:center;gap:4px}.lb-card table{width:100%;border-collapse:collapse;font-size:13px}.lb-card td{padding:4px 8px;border-bottom:1px solid var(--border)}.lb-card td.num{text-align:right;font-family:monospace;color:var(--text);font-weight:600}.lb-card .lb-meta{color:var(--muted);font-size:11px;margin-left:6px}.lb-empty{color:var(--muted);font-size:12px;padding:8px 0}.lvl-badge{display:inline-block;background:var(--game-blue);color:#fff;font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px;margin-left:8px}.repos-badge-line{margin-top:8px}.repos-badge{display:inline-block;background:var(--game-blue);color:#fff;font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px}.game-empty{color:var(--muted);font-style:italic;padding:12px 0}.ach-section{position:relative}.ach-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:8px;margin:8px 0 16px}.ach-tile{padding:10px 12px;border-radius:8px;border:1px solid var(--border);font-size:12px;background:var(--panel)}.ach-tile.unlocked{background:linear-gradient(135deg,var(--mega),var(--mega-gold));color:#1a1006;font-weight:700;box-shadow:0 0 12px #f0883e66}.ach-tile.locked{opacity:.55}.ach-tile.just-unlocked{animation:ach-unlock-pulse .6s ease-out}.ach-tile .ach-detail{display:block;font-weight:500;font-size:11px;margin-top:3px}@keyframes ach-unlock-pulse{0%{transform:scale(.9);opacity:.4}60%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}.ach-toast{display:none;position:fixed;top:16px;left:50%;transform:translate(-50%);background:var(--game-blue);color:#fff;font-weight:700;padding:10px 18px;border-radius:8px;z-index:1000;box-shadow:0 4px 20px #0008;max-width:92vw}.ach-toast.show{display:block}.achievements-tab{display:flex;flex-direction:column;gap:12px}.achievements-tab h2{font-size:clamp(16px,1.4vw,22px);margin:0}@media (max-width: 640px){.game-leaderboards{grid-template-columns:1fr}}@media (min-width: 1601px){.game-leaderboards{gap:20px}}.sessions-tab{display:flex;flex-direction:column;gap:14px}.sessions-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 0}.sessions-toolbar h2{margin:0;font-size:14px;font-weight:600;color:var(--text)}.sessions-window-select{display:inline-flex;gap:2px;padding:2px;background:var(--panel);border:1px solid var(--border);border-radius:6px}.sessions-window-btn{padding:4px 10px;background:transparent;border:none;border-radius:4px;color:var(--muted);font-size:12px;cursor:pointer;transition:background .15s,color .15s}.sessions-window-btn:hover{color:var(--text)}.sessions-window-btn.active{background:var(--accent);color:#0d1117;font-weight:600}.sessions-summary-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px}.sessions-chart{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:12px}.sessions-chart-empty,.sessions-empty{display:flex;align-items:center;justify-content:center;min-height:160px;color:var(--muted);font-size:14px;background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:32px;text-align:center}.sessions-table-scroll{overflow-x:auto;background:var(--panel);border:1px solid var(--border);border-radius:8px}.sessions-table{width:100%;border-collapse:collapse;font-size:13px}.sessions-table th,.sessions-table td{padding:8px 10px;text-align:left;border-bottom:1px solid var(--border);white-space:nowrap}.sessions-table th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);background:#ffffff05;position:sticky;top:0}.sessions-table td.num{text-align:right;font-variant-numeric:tabular-nums}.sessions-table tr:last-child td{border-bottom:none}.sessions-table tr:hover td{background:#58a6ff0f}.sessions-empty-row td{color:var(--muted);font-style:italic;text-align:center}.sessions-pct-pill{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums}.sessions-pct-ok{background:#3fb95026;color:var(--ok)}.sessions-pct-warn{background:#d2992226;color:var(--warn)}.sessions-pct-err{background:#f8514926;color:var(--err)}.sessions-sparkline{display:inline-block;vertical-align:middle}.sessions-sparkline-empty{color:var(--muted);font-size:11px}.sessions-meta{font-size:11px;color:var(--muted)}.sessions-footer{font-size:11px;color:var(--muted);margin-top:6px}@media (max-width: 640px){.sessions-summary-tiles{grid-template-columns:1fr}.sessions-table th,.sessions-table td{font-size:12px;padding:6px 8px}}.repo-stack-card{display:flex;flex-direction:column;gap:10px}.repo-stack-card h3{margin:0;font-size:14px;font-weight:600;color:var(--text)}.repo-stack-bar{display:flex;width:100%;height:22px;border-radius:6px;overflow:hidden;border:1px solid var(--border);background:var(--bg)}.repo-stack-segment{height:100%;min-width:2px;transition:opacity .15s,filter .15s}.repo-stack-segment:hover{opacity:.85;filter:brightness(1.15)}.repo-stack-total{font-size:13px;color:var(--text);font-variant-numeric:tabular-nums}.repo-stack-total .pct{color:var(--muted)}.repo-stack-legend{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:6px}.repo-stack-legend-item{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}.repo-stack-legend-swatch{flex-shrink:0;width:12px;height:12px;border-radius:3px;border:1px solid var(--border)}.repo-stack-legend-name{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media (max-width: 640px){.repo-stack-legend{grid-template-columns:1fr}}.session-gauges-card{grid-column:1 / -1}.session-gauges-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px}.session-gauge{display:flex;flex-direction:column;gap:6px;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:6px}.session-gauge-self{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent);background:color-mix(in srgb,var(--accent) 8%,var(--bg))}.session-gauge-head{display:flex;justify-content:space-between;align-items:baseline;gap:6px}.session-gauge-label{font-size:12px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:70%}.session-gauge-self .session-gauge-label{color:var(--accent)}.session-gauge-pct{font-size:12px;font-weight:600;color:var(--muted);white-space:nowrap}.session-gauges-grid .gauge-bar{height:8px}.session-gauge-sub{margin:0}.session-gauge-meta{margin:0;font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media (max-width: 640px){.session-gauges-grid{grid-template-columns:1fr}}.turns-tab h3{margin-bottom:.5em}.turns-tab h4{margin:1em 0 .4em;font-size:1em}.turns-notice{background:var(--accent-bg, #1e2a3a);border:1px solid var(--accent-border, #2a3f5a);border-radius:4px;padding:.4em .6em;margin:.5em 0;font-size:.9em}.turns-intents{background:#ffc80014;border:1px solid rgba(255,200,0,.3);border-radius:4px;padding:.5em .8em;margin:.5em 0}.turns-intents ul{margin:.3em 0;padding-left:1.2em;font-size:.88em}.turns-table,.turns-detail-table{width:100%;border-collapse:collapse;font-size:.88em}.turns-table th,.turns-detail-table th{text-align:left;padding:.35em .5em;border-bottom:1px solid var(--border, #333);color:var(--muted, #888);font-weight:600}.turns-table td,.turns-detail-table td{padding:.3em .5em;border-bottom:1px solid var(--border-soft, #222);vertical-align:top}.turns-row.active{background:#50b4ff0f}.pill{display:inline-block;margin-left:.5em;padding:0 .4em;font-size:.75em;border-radius:8px;background:#50b4ff2e;color:var(--accent, #6cf)}.band{display:inline-block;padding:0 .4em;border-radius:3px;font-size:.78em;font-weight:600}.band-green{background:#00c8002e;color:#5f5}.band-yellow{background:#ffc8002e;color:#fd5}.band-red{background:#ff3c3c2e;color:#f77}.recall-list{list-style:none;margin:0;padding:0;font-size:.82em}.recall-list li{white-space:nowrap}.muted{color:var(--muted, #888)}.recall-cell{max-width:320px}.mini-btn{margin-right:.3em;padding:.1em .5em;font-size:.78em;cursor:pointer;border:1px solid var(--border, #444);border-radius:3px;background:var(--btn-bg, #1a1a1a);color:var(--text, #ddd)}.mini-btn:disabled{opacity:.45;cursor:default}.topics-search{width:100%;max-width:480px;padding:.35em .5em;margin:.5em 0 1em;background:var(--input-bg, #1a1a1a);border:1px solid var(--border, #444);border-radius:4px;color:var(--text, #ddd)}.topic-row:hover{background:#50b4ff0f}.topic-drilldown h4{margin-bottom:.5em}.link-btn{background:none;border:none;color:var(--accent, #6cf);cursor:pointer;font-size:.9em;padding:0}.maintenance-tab{display:flex;flex-direction:column;gap:12px}.card-header{font-size:13px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:10px;display:flex;align-items:center;gap:8px}.card-body{font-size:13px}.stat-section{margin-bottom:12px}.stat-section:last-child{margin-bottom:0}.stat-label{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px}.stat-row{display:flex;justify-content:space-between;align-items:baseline;padding:3px 0;border-bottom:1px solid var(--border);font-size:13px}.num{text-align:right;font-family:monospace;font-weight:600}.compact-table{width:100%;border-collapse:collapse;font-size:13px}.compact-table th{text-align:left;padding:4px 6px;border-bottom:1px solid var(--border);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}.compact-table th.num{text-align:right}.compact-table td{padding:3px 6px;border-bottom:1px solid var(--border)}.compact-table td.num{text-align:right;font-family:monospace;font-weight:600}.compact-table tbody tr:last-child td{border-bottom:none}.text-muted{color:var(--muted)}.text-error{color:var(--err)}.text-ok{color:var(--ok)}.text-warn{color:var(--warn)}.text-mono{font-family:monospace;font-size:12px}.badge{display:inline-block;padding:1px 8px;font-size:10px;font-weight:700;border-radius:8px;text-transform:uppercase;letter-spacing:.3px}.badge-ok{background:color-mix(in srgb,var(--ok) 20%,transparent);color:var(--ok);border:1px solid var(--ok)}.badge-bad{background:color-mix(in srgb,var(--err) 20%,transparent);color:var(--err);border:1px solid var(--err)}.badge-warn{background:color-mix(in srgb,var(--warn) 20%,transparent);color:var(--warn);border:1px solid var(--warn)}.action-grid{display:grid;grid-template-columns:1fr;gap:8px}.action-item{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:6px}.action-info{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.action-label{font-size:13px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}.action-desc{font-size:11px;color:var(--muted)}.action-result{font-size:11px;margin-top:2px}.action-controls{display:flex;align-items:center;gap:8px;flex-shrink:0}.btn{padding:5px 14px;font-size:12px;font-weight:600;border:none;border-radius:6px;cursor:pointer;white-space:nowrap;transition:opacity .15s}.btn:disabled{opacity:.5;cursor:not-allowed}.btn-primary{background:var(--accent);color:#0d1117}.btn-danger{background:var(--err);color:#fff}.days-input{width:60px;padding:4px 6px;font-size:12px;background:var(--panel);border:1px solid var(--border);border-radius:4px;color:var(--text);text-align:center}.days-input:disabled{opacity:.5}@media (max-width: 640px){.action-item{flex-direction:column;align-items:stretch;gap:8px}.action-controls{justify-content:flex-end}}.ov-stripe-health-summary{display:flex;gap:12px;align-items:center;margin-bottom:12px;font-size:clamp(11px,.85vw,14px);flex-wrap:wrap}.ov-stripe-health-badge{display:inline-block;padding:2px 10px;border-radius:10px;background:var(--panel);border:1px solid var(--border);font-weight:600;text-transform:capitalize}.ov-text-green{color:var(--ok)}.ov-text-yellow{color:var(--warn)}.ov-text-orange{color:#d4761e}.ov-text-red{color:var(--err)}.ov-text-gray,.ov-stripe-health-score,.ov-stripe-churn,.ov-stripe-total{color:var(--muted)}.ov-stripe-bars{display:flex;flex-direction:column;gap:6px}.ov-stripe-row{display:grid;grid-template-columns:80px 1fr 40px 48px;align-items:center;gap:8px;font-size:clamp(11px,.8vw,13px)}.ov-stripe-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}.ov-bar-track{height:18px;background:var(--bg);border-radius:4px;overflow:hidden;position:relative}.ov-bar-fill{height:100%;border-radius:4px;transition:width .5s ease;min-width:2px}.ov-bar-green{background:var(--ok)}.ov-bar-blue{background:var(--accent)}.ov-bar-teal{background:#3d9cb0}.ov-bar-yellow{background:var(--warn)}.ov-bar-gray{background:var(--muted)}.ov-bar-red{background:var(--err)}.ov-bar-orange{background:#d4761e}.ov-bar-latest{box-shadow:0 0 6px #ffffff80}.ov-stripe-count{text-align:right;color:var(--text);font-variant-numeric:tabular-nums}.ov-stripe-stability{color:var(--muted);font-size:clamp(10px,.75vw,12px)}.ov-stripe-footer{margin-top:10px;font-size:clamp(10px,.75vw,12px);color:var(--muted);display:flex;gap:8px}.ov-perf-summary{display:flex;gap:14px;align-items:center;margin-bottom:10px;font-size:clamp(11px,.85vw,14px);flex-wrap:wrap}.ov-perf-stat strong{font-variant-numeric:tabular-nums}.ov-sparkline{display:flex;align-items:flex-end;gap:3px;height:60px;padding:4px 2px;margin-bottom:6px}.ov-sparkline-bar{flex:1;min-width:4px;border-radius:2px 2px 0 0;transition:height .4s ease}.ov-empty-state{font-size:clamp(11px,.8vw,13px);color:var(--muted);padding:16px 0;text-align:center}.ov-card-footer{font-size:clamp(10px,.75vw,12px);color:var(--muted);margin-top:4px}.ov-card{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:clamp(8px,1.5vw,16px)}.ov-card-title{margin:0 0 10px;font-size:clamp(13px,.9vw,15px);font-weight:600}
@@ -1,2 +0,0 @@
1
- const n={"claude-sonnet-4":3e-6,"claude-3.5-sonnet":3e-6,"claude-3-opus":15e-6,"claude-3-haiku":25e-8,"claude-3.5-haiku":8e-7,"gpt-4o":25e-7,"gpt-4o-mini":15e-8,"gpt-4-turbo":1e-5,"gpt-3.5-turbo":5e-7,"gemini-2.5-pro":125e-8,"gemini-2.5-flash":15e-8,"gemini-2.0-flash":1e-7,"deepseek-chat":14e-8,"deepseek-reasoner":55e-8,codestral:3e-7,"mistral-large":2e-6,"llama-3.1-405b":133e-8,"llama-3.1-70b":8e-7,"llama-3.1-8b":5e-8};function r(e){if(n[e]!=null)return n[e];for(const[a,t]of Object.entries(n))if(e.startsWith(a))return t}function s(e,a,t){if(t<=0)return{cacheReadSaved:0,cacheWriteCost:0,netSaved:0};const c=e*t*.9,o=a*t*.25;return{cacheReadSaved:c,cacheWriteCost:o,netSaved:c-o}}export{s as c,r as l};
2
- //# sourceMappingURL=pricing-CvE4NllQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pricing-CvE4NllQ.js","sources":["../../../../src/pricing.ts"],"sourcesContent":["/**\n * pricing.ts — Reusable pricing constants and cache-savings computation.\n *\n * Single source of truth for provider prompt-cache pricing multipliers and\n * known model input rates. Extracted from routes-cache.ts inline arithmetic.\n *\n * PREVENT-PI-004: compute-only, zero network. No SQL, no IO.\n */\n\n// ─── Cache Pricing Multipliers ──────────────────────────────────────────────\n\n/**\n * Fraction of input cost saved per cache-read token.\n * Cache reads cost 10% of full input → you save 90% of the input cost.\n */\nexport const CACHE_READ_MULTIPLIER = 0.9;\n\n/**\n * Fraction of input cost incurred as a premium per cache-write token.\n * Cache writes cost 125% of full input → a 25% premium over a normal input token.\n */\nexport const CACHE_WRITE_MULTIPLIER = 0.25;\n\n// ─── Known Model Input Rates ─────────────────────────────────────────────────\n// USD per input token. Exact-match first, then prefix-match.\n\nexport const MODEL_INPUT_RATES: Record<string, number> = {\n\t\"claude-sonnet-4\": 3e-6, // $3/Mtok\n\t\"claude-3.5-sonnet\": 3e-6,\n\t\"claude-3-opus\": 15e-6,\n\t\"claude-3-haiku\": 0.25e-6,\n\t\"claude-3.5-haiku\": 0.8e-6,\n\t\"gpt-4o\": 2.5e-6,\n\t\"gpt-4o-mini\": 0.15e-6,\n\t\"gpt-4-turbo\": 10e-6,\n\t\"gpt-3.5-turbo\": 0.5e-6,\n\t\"gemini-2.5-pro\": 1.25e-6,\n\t\"gemini-2.5-flash\": 0.15e-6,\n\t\"gemini-2.0-flash\": 0.1e-6,\n\t\"deepseek-chat\": 0.14e-6,\n\t\"deepseek-reasoner\": 0.55e-6,\n\tcodestral: 0.3e-6,\n\t\"mistral-large\": 2e-6,\n\t\"llama-3.1-405b\": 1.33e-6,\n\t\"llama-3.1-70b\": 0.8e-6,\n\t\"llama-3.1-8b\": 0.05e-6,\n};\n\n/**\n * Look up the input-token rate (USD) for a model string.\n * Exact match first, then prefix match (e.g. \"claude-sonnet-4-20250514\" → 3e-6).\n */\nexport function lookupModelInputRate(model: string): number | undefined {\n\t// exact match first\n\tif (MODEL_INPUT_RATES[model] != null) return MODEL_INPUT_RATES[model];\n\t// prefix match\n\tfor (const [key, rate] of Object.entries(MODEL_INPUT_RATES)) {\n\t\tif (model.startsWith(key)) return rate;\n\t}\n\treturn undefined;\n}\n\n// ─── Cache Savings Computation ──────────────────────────────────────────────\n\nexport interface CacheSavings {\n\treadonly cacheReadSaved: number;\n\treadonly cacheWriteCost: number;\n\treadonly netSaved: number;\n}\n\n/**\n * Compute dollar savings from provider prompt cache read/write token counts.\n *\n * @param totalCacheRead — total cache-read tokens over the lifetime.\n * @param totalCacheWrite — total cache-write tokens over the lifetime.\n * @param inputRate — the model's input-token rate in USD (e.g. 3e-6 for Sonnet).\n * @returns `{ cacheReadSaved, cacheWriteCost, netSaved }` — or all zeros when\n * `inputRate` is zero or negative.\n */\nexport function computeCacheSavings(\n\ttotalCacheRead: number,\n\ttotalCacheWrite: number,\n\tinputRate: number,\n): CacheSavings {\n\tif (inputRate <= 0) {\n\t\treturn { cacheReadSaved: 0, cacheWriteCost: 0, netSaved: 0 };\n\t}\n\tconst cacheReadSaved = totalCacheRead * inputRate * CACHE_READ_MULTIPLIER;\n\tconst cacheWriteCost = totalCacheWrite * inputRate * CACHE_WRITE_MULTIPLIER;\n\treturn {\n\t\tcacheReadSaved,\n\t\tcacheWriteCost,\n\t\tnetSaved: cacheReadSaved - cacheWriteCost,\n\t};\n}\n"],"names":["MODEL_INPUT_RATES","lookupModelInputRate","model","key","rate","computeCacheSavings","totalCacheRead","totalCacheWrite","inputRate","cacheReadSaved","cacheWriteCost"],"mappings":"AA0BO,MAAMA,EAA4C,CACxD,kBAAmB,KACnB,oBAAqB,KACrB,gBAAiB,MACjB,iBAAkB,MAClB,mBAAoB,KACpB,SAAU,MACV,cAAe,MACf,cAAe,KACf,gBAAiB,KACjB,iBAAkB,OAClB,mBAAoB,MACpB,mBAAoB,KACpB,gBAAiB,MACjB,oBAAqB,MACrB,UAAW,KACX,gBAAiB,KACjB,iBAAkB,OAClB,gBAAiB,KACjB,eAAgB,IACjB,EAMO,SAASC,EAAqBC,EAAmC,CAEvE,GAAIF,EAAkBE,CAAK,GAAK,KAAM,OAAOF,EAAkBE,CAAK,EAEpE,SAAW,CAACC,EAAKC,CAAI,IAAK,OAAO,QAAQJ,CAAiB,EACzD,GAAIE,EAAM,WAAWC,CAAG,EAAG,OAAOC,CAGpC,CAmBO,SAASC,EACfC,EACAC,EACAC,EACe,CACf,GAAIA,GAAa,EAChB,MAAO,CAAE,eAAgB,EAAG,eAAgB,EAAG,SAAU,CAAA,EAE1D,MAAMC,EAAiBH,EAAiBE,EAAY,GAC9CE,EAAiBH,EAAkBC,EAAY,IACrD,MAAO,CACN,eAAAC,EACA,eAAAC,EACA,SAAUD,EAAiBC,CAAA,CAE7B"}
@@ -1,69 +0,0 @@
1
- /**
2
- * dashboard-client/src/styles/metrics-extra.css — Perf card grid for Metrics tab.
3
- *
4
- * Builds on the perf-metric classes from repos-metrics.css. Adds the
5
- * 5-card grid layout with titled cards (model latency, throughput,
6
- * process, snapshot cost, TUI lag proxy).
7
- */
8
-
9
- .perf-cards-grid {
10
- display: grid;
11
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
12
- gap: 12px;
13
- margin-top: 12px;
14
- }
15
-
16
- .perf-card {
17
- display: flex;
18
- flex-direction: column;
19
- gap: 8px;
20
- padding: 14px;
21
- background: var(--panel);
22
- border: 1px solid var(--border);
23
- border-radius: 8px;
24
- }
25
-
26
- .perf-card-title {
27
- margin: 0 0 4px;
28
- font-size: 12px;
29
- font-weight: 600;
30
- text-transform: uppercase;
31
- letter-spacing: 0.5px;
32
- color: var(--muted);
33
- }
34
-
35
- .perf-card-body {
36
- display: flex;
37
- flex-direction: column;
38
- gap: 6px;
39
- }
40
-
41
- .perf-card-note {
42
- font-size: 11px;
43
- color: var(--muted);
44
- font-style: italic;
45
- margin-top: 2px;
46
- }
47
-
48
- /* Inherit perf-metric layout from repos-metrics.css but make them
49
- borderless inside cards to avoid double borders. */
50
- .perf-card-body .perf-metric {
51
- padding: 6px 8px;
52
- background: transparent;
53
- border: none;
54
- border-radius: 0;
55
- }
56
-
57
- .perf-footer {
58
- font-size: 11px;
59
- color: var(--muted);
60
- margin-top: 10px;
61
- padding-top: 8px;
62
- border-top: 1px solid var(--border);
63
- }
64
-
65
- @media (max-width: 640px) {
66
- .perf-cards-grid {
67
- grid-template-columns: 1fr;
68
- }
69
- }
@@ -1,142 +0,0 @@
1
- /* turns.css — S52 turn-by-turn memory tracking + recall tab */
2
-
3
- .turns-tab h3 {
4
- margin-bottom: 0.5em;
5
- }
6
- .turns-tab h4 {
7
- margin: 1em 0 0.4em;
8
- font-size: 1em;
9
- }
10
-
11
- .turns-notice {
12
- background: var(--accent-bg, #1e2a3a);
13
- border: 1px solid var(--accent-border, #2a3f5a);
14
- border-radius: 4px;
15
- padding: 0.4em 0.6em;
16
- margin: 0.5em 0;
17
- font-size: 0.9em;
18
- }
19
-
20
- .turns-intents {
21
- background: rgba(255, 200, 0, 0.08);
22
- border: 1px solid rgba(255, 200, 0, 0.3);
23
- border-radius: 4px;
24
- padding: 0.5em 0.8em;
25
- margin: 0.5em 0;
26
- }
27
- .turns-intents ul {
28
- margin: 0.3em 0;
29
- padding-left: 1.2em;
30
- font-size: 0.88em;
31
- }
32
-
33
- .turns-table,
34
- .turns-detail-table {
35
- width: 100%;
36
- border-collapse: collapse;
37
- font-size: 0.88em;
38
- }
39
- .turns-table th,
40
- .turns-detail-table th {
41
- text-align: left;
42
- padding: 0.35em 0.5em;
43
- border-bottom: 1px solid var(--border, #333);
44
- color: var(--muted, #888);
45
- font-weight: 600;
46
- }
47
- .turns-table td,
48
- .turns-detail-table td {
49
- padding: 0.3em 0.5em;
50
- border-bottom: 1px solid var(--border-soft, #222);
51
- vertical-align: top;
52
- }
53
- .turns-row.active {
54
- background: rgba(80, 180, 255, 0.06);
55
- }
56
- .pill {
57
- display: inline-block;
58
- margin-left: 0.5em;
59
- padding: 0 0.4em;
60
- font-size: 0.75em;
61
- border-radius: 8px;
62
- background: rgba(80, 180, 255, 0.18);
63
- color: var(--accent, #6cf);
64
- }
65
-
66
- .band {
67
- display: inline-block;
68
- padding: 0 0.4em;
69
- border-radius: 3px;
70
- font-size: 0.78em;
71
- font-weight: 600;
72
- }
73
- .band-green {
74
- background: rgba(0, 200, 0, 0.18);
75
- color: #5f5;
76
- }
77
- .band-yellow {
78
- background: rgba(255, 200, 0, 0.18);
79
- color: #fd5;
80
- }
81
- .band-red {
82
- background: rgba(255, 60, 60, 0.18);
83
- color: #f77;
84
- }
85
-
86
- .recall-list {
87
- list-style: none;
88
- margin: 0;
89
- padding: 0;
90
- font-size: 0.82em;
91
- }
92
- .recall-list li {
93
- white-space: nowrap;
94
- }
95
- .muted {
96
- color: var(--muted, #888);
97
- }
98
-
99
- .recall-cell {
100
- max-width: 320px;
101
- }
102
-
103
- .mini-btn {
104
- margin-right: 0.3em;
105
- padding: 0.1em 0.5em;
106
- font-size: 0.78em;
107
- cursor: pointer;
108
- border: 1px solid var(--border, #444);
109
- border-radius: 3px;
110
- background: var(--btn-bg, #1a1a1a);
111
- color: var(--text, #ddd);
112
- }
113
- .mini-btn:disabled {
114
- opacity: 0.45;
115
- cursor: default;
116
- }
117
-
118
- /* topics / wiki (S52 polish) */
119
- .topics-search {
120
- width: 100%;
121
- max-width: 480px;
122
- padding: 0.35em 0.5em;
123
- margin: 0.5em 0 1em;
124
- background: var(--input-bg, #1a1a1a);
125
- border: 1px solid var(--border, #444);
126
- border-radius: 4px;
127
- color: var(--text, #ddd);
128
- }
129
- .topic-row:hover {
130
- background: rgba(80, 180, 255, 0.06);
131
- }
132
- .topic-drilldown h4 {
133
- margin-bottom: 0.5em;
134
- }
135
- .link-btn {
136
- background: none;
137
- border: none;
138
- color: var(--accent, #6cf);
139
- cursor: pointer;
140
- font-size: 0.9em;
141
- padding: 0;
142
- }
@@ -1,160 +0,0 @@
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
- }