pi-mega-compact 0.20.60 → 0.20.61

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 (91) hide show
  1. package/dist/config/vector-cortex-dash-0d.js +26 -0
  2. package/dist/config/vector-cortex.js +2 -0
  3. package/dist/config.js +1 -1
  4. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
  5. package/dist/src/config/vector-cortex-dash-0d.js +26 -0
  6. package/dist/src/config/vector-cortex.js +2 -0
  7. package/dist/src/config.js +1 -1
  8. package/extensions/dashboard-client/dist/assets/AdminTab-DEjVnlwe.js +2 -0
  9. package/extensions/dashboard-client/dist/assets/AdminTab-DEjVnlwe.js.map +1 -0
  10. package/extensions/dashboard-client/dist/assets/{AreaChart-B5Is2_EN.js → AreaChart-B1PoTqKJ.js} +2 -2
  11. package/extensions/dashboard-client/dist/assets/{AreaChart-B5Is2_EN.js.map → AreaChart-B1PoTqKJ.js.map} +1 -1
  12. package/extensions/dashboard-client/dist/assets/{BarChart-Bj2oT871.js → BarChart-DaoONT_V.js} +2 -2
  13. package/extensions/dashboard-client/dist/assets/{BarChart-Bj2oT871.js.map → BarChart-DaoONT_V.js.map} +1 -1
  14. package/extensions/dashboard-client/dist/assets/{CacheTab-DuhLeKHW.js → CacheTab-rD5sjlkW.js} +2 -2
  15. package/extensions/dashboard-client/dist/assets/{CacheTab-DuhLeKHW.js.map → CacheTab-rD5sjlkW.js.map} +1 -1
  16. package/extensions/dashboard-client/dist/assets/ConfigTab-BQkufK7t.js +2 -0
  17. package/extensions/dashboard-client/dist/assets/ConfigTab-BQkufK7t.js.map +1 -0
  18. package/extensions/dashboard-client/dist/assets/{EventsTab-BG6L8uWh.js → EventsTab-DGlQzJaT.js} +2 -2
  19. package/extensions/dashboard-client/dist/assets/{EventsTab-BG6L8uWh.js.map → EventsTab-DGlQzJaT.js.map} +1 -1
  20. package/extensions/dashboard-client/dist/assets/{HealthTab-CZmGCUJh.js → HealthTab-DW7kt4qm.js} +2 -2
  21. package/extensions/dashboard-client/dist/assets/{HealthTab-CZmGCUJh.js.map → HealthTab-DW7kt4qm.js.map} +1 -1
  22. package/extensions/dashboard-client/dist/assets/MaintenanceTab-CGiZ0OQ6.js +2 -0
  23. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CoZ1mSjU.js.map → MaintenanceTab-CGiZ0OQ6.js.map} +1 -1
  24. package/extensions/dashboard-client/dist/assets/MemoryMapTab-BwyrxjuW.js +2 -0
  25. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BwVaWniY.js.map → MemoryMapTab-BwyrxjuW.js.map} +1 -1
  26. package/extensions/dashboard-client/dist/assets/{MetricsCards-BCJoHe_n.js → MetricsCards-IZaCOOXU.js} +2 -2
  27. package/extensions/dashboard-client/dist/assets/{MetricsCards-BCJoHe_n.js.map → MetricsCards-IZaCOOXU.js.map} +1 -1
  28. package/extensions/dashboard-client/dist/assets/MetricsTab-wCxVpHlC.js +2 -0
  29. package/extensions/dashboard-client/dist/assets/{MetricsTab-UQSqUGXe.js.map → MetricsTab-wCxVpHlC.js.map} +1 -1
  30. package/extensions/dashboard-client/dist/assets/{OverviewTab-qi12IYvs.js → OverviewTab-DsH08Wr0.js} +2 -2
  31. package/extensions/dashboard-client/dist/assets/{OverviewTab-qi12IYvs.js.map → OverviewTab-DsH08Wr0.js.map} +1 -1
  32. package/extensions/dashboard-client/dist/assets/{ReposTab-CcHZPzOO.js → ReposTab-Dpb7sXWB.js} +2 -2
  33. package/extensions/dashboard-client/dist/assets/{ReposTab-CcHZPzOO.js.map → ReposTab-Dpb7sXWB.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/SessionsTab-DFMo7tKA.js +2 -0
  35. package/extensions/dashboard-client/dist/assets/SessionsTab-DFMo7tKA.js.map +1 -0
  36. package/extensions/dashboard-client/dist/assets/SetupTab-D2IEBt1u.js +3 -0
  37. package/extensions/dashboard-client/dist/assets/SetupTab-D2IEBt1u.js.map +1 -0
  38. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DhfdRM3_.js → TimeSavedCard-BGPvmVFG.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DhfdRM3_.js.map → TimeSavedCard-BGPvmVFG.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/TurnMemoryView-BZo09Jri.js +5 -0
  41. package/extensions/dashboard-client/dist/assets/TurnMemoryView-BZo09Jri.js.map +1 -0
  42. package/extensions/dashboard-client/dist/assets/TurnsTab-CosKNvMp.js +2 -0
  43. package/extensions/dashboard-client/dist/assets/TurnsTab-CosKNvMp.js.map +1 -0
  44. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-XGMW6u62.js → VcStatusBadge-UEZLL6Zj.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-XGMW6u62.js.map → VcStatusBadge-UEZLL6Zj.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BACHKLjU.js → VectorCortexTab-fDAgD2pN.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BACHKLjU.js.map → VectorCortexTab-fDAgD2pN.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{WikiTab-CGQWHuRq.js → WikiTab-7TIe2MkS.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{WikiTab-CGQWHuRq.js.map → WikiTab-7TIe2MkS.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/button-C9qrZYdn.js +2 -0
  51. package/extensions/dashboard-client/dist/assets/{button-SyOWCGkp.js.map → button-C9qrZYdn.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/{card-69DCTMel.js → card-DxZRNC4E.js} +2 -2
  53. package/extensions/dashboard-client/dist/assets/{card-69DCTMel.js.map → card-DxZRNC4E.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/client-extra-Dj7wJs6Z.js +2 -0
  55. package/extensions/dashboard-client/dist/assets/{client-extra-CgeDg1Md.js.map → client-extra-Dj7wJs6Z.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BwTtrqm5.js → generateCategoricalChart-Dj-DYUgL.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BwTtrqm5.js.map → generateCategoricalChart-Dj-DYUgL.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{index-BZcYzeCr.js → index-Bq2n15a4.js} +31 -31
  59. package/extensions/dashboard-client/dist/assets/index-Bq2n15a4.js.map +1 -0
  60. package/extensions/dashboard-client/dist/assets/switch-1sEgLPHu.js +2 -0
  61. package/extensions/dashboard-client/dist/assets/{switch-DhQfmSFD.js.map → switch-1sEgLPHu.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/toggle-jMzQoJ2C.js +2 -0
  63. package/extensions/dashboard-client/dist/assets/{toggle-B3gNAVog.js.map → toggle-jMzQoJ2C.js.map} +1 -1
  64. package/extensions/dashboard-client/dist/assets/{useSSE-BkkjZ4bO.js → useSSE-Dxy616R1.js} +2 -2
  65. package/extensions/dashboard-client/dist/assets/{useSSE-BkkjZ4bO.js.map → useSSE-Dxy616R1.js.map} +1 -1
  66. package/extensions/dashboard-client/dist/index.html +1 -1
  67. package/extensions/dashboard-client/src/App.tsx +150 -17
  68. package/extensions/dashboard-client/src/tabs/TurnsTab.tsx +9 -366
  69. package/extensions/dashboard-client/src/tabs/dashHashRouter.ts +76 -0
  70. package/extensions/dashboard-client/src/tabs/registry.ts +9 -1
  71. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
  72. package/package.json +1 -1
  73. package/src/config/vector-cortex-dash-0d.ts +28 -0
  74. package/src/config/vector-cortex.ts +2 -0
  75. package/src/config.ts +1 -0
  76. package/extensions/dashboard-client/dist/assets/HydeDetailPanel-B-P1jTtk.js +0 -5
  77. package/extensions/dashboard-client/dist/assets/HydeDetailPanel-B-P1jTtk.js.map +0 -1
  78. package/extensions/dashboard-client/dist/assets/MaintenanceTab-CoZ1mSjU.js +0 -2
  79. package/extensions/dashboard-client/dist/assets/MemoryMapTab-BwVaWniY.js +0 -2
  80. package/extensions/dashboard-client/dist/assets/MetricsTab-UQSqUGXe.js +0 -2
  81. package/extensions/dashboard-client/dist/assets/SessionsTab-nzd1408Z.js +0 -2
  82. package/extensions/dashboard-client/dist/assets/SessionsTab-nzd1408Z.js.map +0 -1
  83. package/extensions/dashboard-client/dist/assets/SetupTab-DPrG3s9V.js +0 -3
  84. package/extensions/dashboard-client/dist/assets/SetupTab-DPrG3s9V.js.map +0 -1
  85. package/extensions/dashboard-client/dist/assets/TurnsTab-oalBNLVr.js +0 -2
  86. package/extensions/dashboard-client/dist/assets/TurnsTab-oalBNLVr.js.map +0 -1
  87. package/extensions/dashboard-client/dist/assets/button-SyOWCGkp.js +0 -2
  88. package/extensions/dashboard-client/dist/assets/client-extra-CgeDg1Md.js +0 -2
  89. package/extensions/dashboard-client/dist/assets/index-BZcYzeCr.js.map +0 -1
  90. package/extensions/dashboard-client/dist/assets/switch-DhQfmSFD.js +0 -2
  91. package/extensions/dashboard-client/dist/assets/toggle-B3gNAVog.js +0 -2
@@ -0,0 +1,76 @@
1
+ /**
2
+ * dashboard-client/src/tabs/dashHashRouter.ts — DASH-0d additive hash→surface
3
+ * deep-link router.
4
+ *
5
+ * The dashboard has historically had NO URL-routing (single `useState<TabId>
6
+ * ("overview")` in App.tsx). DASH-0d adds an ADDITIVE hash listener so every
7
+ * legacy deep link (e.g. `#turns`, `#metrics`, `#repos`) still lands on a live
8
+ * consolidated surface, and an empty hash keeps the current behavior (the
9
+ * caller's default tab). It does NOT replace the existing tab state — App.tsx
10
+ * keeps `useState` and this hook only *points* at a surface when the hash maps
11
+ * to one.
12
+ *
13
+ * Mapping (DASH-0a `DEEP_LINK_TARGETS` + the DASH-0d release set):
14
+ * #sessions, #turns → sessions
15
+ * #cache, #metrics → cache-perf
16
+ * #repos, #wiki, #memory-map → memory-graph
17
+ * #events, #health, #vector-cortex → diagnostics
18
+ * #maintenance, #config → admin
19
+ * #setup, #overview → themselves
20
+ * (empty) → null (current behavior)
21
+ *
22
+ * PREVENT-PI-004: browser `location` + `hashchange` only — no network.
23
+ * PREVENT-011: no `any`. Pure client view concern; no endpoint reads added.
24
+ */
25
+
26
+ import { useEffect, useState } from "react";
27
+ import type { DashTabId } from "./registry";
28
+
29
+ /**
30
+ * The consolidated surface a legacy hash resolves to. Every key is a legacy
31
+ * deep-link fragment mapped onto the fixed 7 surfaces. `config`/`setup`/
32
+ * `overview` are explicit release aliases so no old bookmark goes dead.
33
+ */
34
+ export const HASH_TO_SURFACE: Readonly<Record<string, DashTabId>> = {
35
+ overview: "overview",
36
+ sessions: "sessions",
37
+ turns: "sessions",
38
+ cache: "cache-perf",
39
+ metrics: "cache-perf",
40
+ "memory-map": "memory-graph",
41
+ repos: "memory-graph",
42
+ wiki: "memory-graph",
43
+ "vector-cortex": "diagnostics",
44
+ events: "diagnostics",
45
+ health: "diagnostics",
46
+ setup: "setup",
47
+ config: "admin",
48
+ maintenance: "admin",
49
+ };
50
+
51
+ /** Resolve the current `location.hash` to a consolidated surface (null if empty). */
52
+ export function resolveHashToSurface(hash: string): DashTabId | null {
53
+ const clean = hash.replace(/^#/, "").trim();
54
+ if (!clean) return null;
55
+ const surface = HASH_TO_SURFACE[clean];
56
+ return surface ?? null;
57
+ }
58
+
59
+ /**
60
+ * Additive hash listener. Returns the consolidated `DashTabId` the current
61
+ * `location.hash` maps to, or `null` when the hash is empty (current behavior)
62
+ * or unmapped. Re-syncs whenever the hash changes.
63
+ */
64
+ export function useHashTab(): DashTabId | null {
65
+ const [surface, setSurface] = useState<DashTabId | null>(() =>
66
+ resolveHashToSurface(window.location.hash),
67
+ );
68
+
69
+ useEffect(() => {
70
+ const onHashChange = () => setSurface(resolveHashToSurface(window.location.hash));
71
+ window.addEventListener("hashchange", onHashChange);
72
+ return () => window.removeEventListener("hashchange", onHashChange);
73
+ }, []);
74
+
75
+ return surface;
76
+ }
@@ -66,7 +66,7 @@ export const ADVANCED_TAB_IDS: ReadonlySet<TabId> = new Set(
66
66
  * LEFT UNCHANGED (rollback-safe) — this constant documents the 7 surfaces the
67
67
  * DASH-0d rewire will navigate, and deliberately does NOT replace TabId.
68
68
  */
69
- export const DASH_SURFACE_IDS: readonly string[] = [
69
+ export const DASH_SURFACE_IDS = [
70
70
  "overview",
71
71
  "sessions",
72
72
  "cache-perf",
@@ -76,6 +76,14 @@ export const DASH_SURFACE_IDS: readonly string[] = [
76
76
  "admin",
77
77
  ] as const;
78
78
 
79
+ /** The fixed 7 consolidated navigational surface ids (DASH-0d navigation set).
80
+ * Distinct from the legacy 13-tab `TabId` union, which is retained for the
81
+ * flag-off (pre-rollup) surface set + the sidebar/AppShell nav types. */
82
+ export type DashTabId = (typeof DASH_SURFACE_IDS)[number];
83
+
84
+ /** Exactly 7 top-level navigational surfaces (DASH-0d tab-count contract). */
85
+ export const DASH_TAB_COUNT: number = DASH_SURFACE_IDS.length;
86
+
79
87
  /**
80
88
  * DASH-0c: labels for the consolidated surfaces. Additive — the 13-tab
81
89
  * `PRIMARY_TABS`/`ADVANCED_TABS` labels above stay untouched (rollback-safe;
@@ -348,5 +348,11 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
348
348
  "DASH-0c dashboard consolidation execution: (1) the Cache surface absorbs MetricsTab as a Performance section (CacheTab label becomes 'Cache+Performance'); (2) MaintenanceTab + ConfigTab combine under a new AdminTab delegate-shell with an AdminViews toggle (maintenance/config), and SetupTab hides its Config sub-tab. OFF = CacheTab renders only its cache sections, MetricsTab/MaintenanceTab/ConfigTab render as standalone surfaces, SetupTab keeps its Config sub-tab (byte-identical predecessor).",
349
349
  true,
350
350
  ),
351
+ boolDirect(
352
+ "MEGACOMPACT_DASH_0D",
353
+ "Dashboard Consolidation — Rollup / 7-surface",
354
+ "DASH-0d dashboard consolidation roll-up: App.tsx consolidates its lazy list + TabContent switch onto the 7 fixed navigational surfaces (Overview, Sessions, Cache+Performance, Memory Graph, Diagnostics, Setup, Admin) with an additive hash→surface deep-link router; the duplicate TurnsTab/MetricsTab indirection bodies are reconciled to their canonical homes. OFF = App.tsx reproduces the pre-rollup 13-tab surface set byte-identically (byte-identical DASH-0c predecessor).",
355
+ true,
356
+ ),
351
357
  ],
352
358
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.20.60",
3
+ "version": "0.20.61",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",
@@ -0,0 +1,28 @@
1
+ /**
2
+ * config/vector-cortex-dash-0d.ts — DASH-0d dashboard consolidation roll-up flag.
3
+ *
4
+ * Extracted to this sibling (per the vector-cortex-dash-0c.ts precedent) so
5
+ * src/config/vector-cortex.ts stays under the 300-line soft limit. The flag is
6
+ * positive, defaults ON, and `MEGACOMPACT_DASH_0D=0` is byte-identical to the
7
+ * predecessor (DASH-0c): App.tsx renders the pre-rollup 13-tab surface set and
8
+ * the registry holds the 13-tab union; no indirection name is removed and no
9
+ * audit/verifier script is invoked by CI. Registered as a visible
10
+ * VECTOR_CORTEX_SETTINGS boolDirect toggle, never EXCLUDED.
11
+ *
12
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
13
+ */
14
+
15
+ import { sprintFlag } from "./vector-cortex-flag.js";
16
+
17
+ /**
18
+ * DASH-0d — final DASH sprint, the roll-up that makes the 7-surface target
19
+ * externally provable: (1) App.tsx consolidates its lazy list to the 7 fixed
20
+ * navigational surfaces (Overview, Sessions, Cache+Performance, Memory Graph,
21
+ * Diagnostics, Setup, Admin) with an additive hash→surface router; (2) the
22
+ * duplicate TurnsTab/MetricsTab indirection bodies are reconciled to their
23
+ * canonical homes (TurnMemoryView / MetricsCards); (3) new dash-tab-count.mjs
24
+ * and dashboard-audit.mjs verifiers prove the consolidated surface count + a11y
25
+ * contract; (4) conformance fixtures DASH-0D-001..004 + evidence roll-up.
26
+ * `MEGACOMPACT_DASH_0D=0` renders the pre-rollup 13-surface set — byte-identical.
27
+ */
28
+ export const DASH_0D_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_DASH_0D");
@@ -75,6 +75,8 @@ export { DASH_0A_ENABLED } from "./vector-cortex-dash-0a.js";
75
75
  export { DASH_0B_ENABLED } from "./vector-cortex-dash-0b.js";
76
76
  // DASH-0c dashboard consolidation execution flag extracted to vector-cortex-dash-0c.ts.
77
77
  export { DASH_0C_ENABLED } from "./vector-cortex-dash-0c.js";
78
+ // DASH-0d dashboard consolidation roll-up flag extracted to vector-cortex-dash-0d.ts.
79
+ export { DASH_0D_ENABLED } from "./vector-cortex-dash-0d.js";
78
80
  export { ENC_1A_ENABLED } from "./vector-cortex-enc1a.js";
79
81
  export {
80
82
  ENC_1B_ENABLED,
package/src/config.ts CHANGED
@@ -208,6 +208,7 @@ export {
208
208
  DASH_0A_ENABLED,
209
209
  DASH_0B_ENABLED,
210
210
  DASH_0C_ENABLED,
211
+ DASH_0D_ENABLED,
211
212
  BREAKER_WINDOW_MS,
212
213
  BREAKER_MIN_ATTEMPTS,
213
214
  BREAKER_PERF_FAILURES,
@@ -1,5 +0,0 @@
1
- import{u as f,r as c,f as g,j as e,B as d}from"./index-BZcYzeCr.js";import{C as p}from"./card-69DCTMel.js";function x(s,r){return`${s}:${r}`}function j(s,r){const n=s.split(`
2
- `);return n.length>r?n.slice(0,r).join(`
3
- `):s}function y({row:s}){return s.recallScore>0||s.recallPass===1?e.jsxs("div",{className:"mt-2 rounded-md border border-border/60 bg-bg-elevated/40 p-2",children:[e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"font-medium text-muted-foreground",children:"Recall quality"}),e.jsx(d,{variant:s.recallPass===1?"success":"warning",children:s.recallPass===1?"pass":"fail"}),e.jsxs("span",{children:["score ",e.jsx("strong",{className:"text-foreground",children:s.recallScore.toFixed(2)})]})]}),e.jsxs("div",{className:"mt-1 flex flex-wrap gap-x-4 gap-y-0.5 text-xs text-muted-foreground",children:[e.jsxs("span",{children:["relevance ",s.recallRelevance.toFixed(2)]}),e.jsxs("span",{children:["coverage ",s.recallCoverage.toFixed(2)]}),e.jsxs("span",{children:["diversity ",s.recallDiversity.toFixed(2)]}),e.jsxs("span",{children:["specificity ",s.recallSpecificity.toFixed(2)]})]})]}):e.jsx("div",{className:"mt-2 text-xs text-muted-foreground",children:"No recall-quality metrics for this turn."})}const H=({conversationId:s,turnIndex:r})=>{const{data:n}=f(c.useMemo(()=>()=>g(),[]),{pollInterval:3e4}),[o,m]=c.useState(!1),t=c.useMemo(()=>n?.recent.find(l=>x(l.conversationId,l.turnIndex)===x(s,r))??null,[n,s,r]);if(!n)return e.jsx("div",{className:"text-xs text-muted-foreground",children:"Loading HyDE stats…"});if(!t)return e.jsx("div",{className:"text-xs text-muted-foreground",children:"No HyDE/recall telemetry recorded for this turn."});const a=t.hydeDoc??"",i=a.split(`
4
- `).length>3,h=o||!i?a:j(a,3);return e.jsxs(p,{className:"border border-border/60 bg-bg-elevated/20 p-3",children:[t.hydeRan===1?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-2 flex flex-wrap items-center gap-2 text-xs",children:[e.jsx(d,{variant:"accent",children:"HyDE ran"}),e.jsxs("span",{className:"text-muted-foreground",children:["gen ",e.jsxs("strong",{className:"text-foreground",children:[t.hydeGenerationMs,"ms"]})]}),e.jsxs("span",{className:"text-muted-foreground",children:["raw ",e.jsx("strong",{className:"text-foreground",children:t.hydeRawCount}),e.jsx(u,{}),"hyde ",e.jsx("strong",{className:"text-foreground",children:t.hydeHydeCount}),e.jsx(u,{}),"fused ",e.jsx("strong",{className:"text-foreground",children:t.hydeFusedCount})]}),e.jsxs("span",{className:"text-muted-foreground",children:["lift"," ",e.jsxs("strong",{className:"text-neon",children:[t.hydeLift.toFixed(2),"×"]})]})]}),a&&e.jsx("pre",{className:"max-h-40 overflow-auto whitespace-pre-wrap rounded-md border border-border/50 bg-bg-elevated/40 p-2 font-mono text-xs text-muted-foreground",children:h}),i&&e.jsx("button",{type:"button",className:"mt-1 text-xs text-accent underline",onClick:()=>m(l=>!l),children:o?"Show less":"Show full hypothetical doc"})]}):e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[e.jsx(d,{variant:"warning",children:"HyDE skipped"}),e.jsx("span",{className:"text-muted-foreground",children:N(t)})]}),e.jsx(y,{row:t})]})};function u(){return e.jsx("span",{className:"text-muted-foreground/60",children:" → "})}function N(s){switch(s.hydeReason){case"no-llm":return"No LLM embedder available (requires Ollama/HTTP embedder).";case"generation-failed":return"Hypothetical doc generation failed this turn.";case"disabled":return"HyDE is disabled (MEGACOMPACT_HYDE_DISABLED).";default:return"HyDE was not invoked for this turn."}}export{H};
5
- //# sourceMappingURL=HydeDetailPanel-B-P1jTtk.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HydeDetailPanel-B-P1jTtk.js","sources":["../../src/components/HydeDetailPanel.tsx"],"sourcesContent":["/**\n * dashboard-client/src/components/HydeDetailPanel.tsx — per-turn HyDE + recall\n * quality detail (H3.1).\n *\n * Fetches /api/rag-metrics once and indexes telemetry rows by the composite\n * `conversationId:turnIndex` key (the dashboard TurnRow has no DB id, so the\n * pair is the stable identifier). Renders one of three HyDE states:\n * - HyDE ran: hypothetical doc (collapsible), raw/hyde/fused hit counts,\n * lift multiplier, generation latency.\n * - HyDE skipped: reason (disabled / no-llm / generation-failed).\n * - No telemetry: nothing (the parent only renders us when flagged).\n * Plus a CRAG-style mini score line when recall metrics exist.\n *\n * PREVENT-PI-004: relative-path fetch to the same-origin dashboard server.\n */\n\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { useApi } from \"../hooks/useApi\";\nimport { fetchRagMetrics } from \"../api/client\";\nimport type { RagMetricsResponse } from \"@contracts\";\nimport { Card } from \"./ui/card\";\nimport { Badge } from \"./ui/badge\";\n\n/** Per-turn telemetry row shape derived from the rag-metrics contract. */\ntype TelemetryRow = RagMetricsResponse[\"recent\"][number];\n\nexport interface HydeDetailPanelProps {\n\tconversationId: string;\n\tturnIndex: number;\n}\n\n/** Composite key matching a telemetry row to a rendered turn. */\nfunction rowKey(conversationId: string, turnIndex: number): string {\n\treturn `${conversationId}:${turnIndex}`;\n}\n\n/** First N lines of the hypothetical doc (or full when expanded). */\nfunction truncateDoc(doc: string, maxLines: number): string {\n\tconst lines = doc.split(\"\\n\");\n\treturn lines.length > maxLines ? lines.slice(0, maxLines).join(\"\\n\") : doc;\n}\n\n/** CRAG-style mini score line when recall metrics were captured. */\nfunction ScoreLine({ row }: { row: TelemetryRow }): React.ReactElement {\n\tconst hasScore = row.recallScore > 0 || row.recallPass === 1;\n\tif (!hasScore) {\n\t\treturn (\n\t\t\t<div className=\"mt-2 text-xs text-muted-foreground\">\n\t\t\t\tNo recall-quality metrics for this turn.\n\t\t\t</div>\n\t\t);\n\t}\n\treturn (\n\t\t<div className=\"mt-2 rounded-md border border-border/60 bg-bg-elevated/40 p-2\">\n\t\t\t<div className=\"flex items-center gap-2 text-xs\">\n\t\t\t\t<span className=\"font-medium text-muted-foreground\">Recall quality</span>\n\t\t\t\t<Badge variant={row.recallPass === 1 ? \"success\" : \"warning\"}>\n\t\t\t\t\t{row.recallPass === 1 ? \"pass\" : \"fail\"}\n\t\t\t\t</Badge>\n\t\t\t\t<span>\n\t\t\t\t\tscore <strong className=\"text-foreground\">{row.recallScore.toFixed(2)}</strong>\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t<div className=\"mt-1 flex flex-wrap gap-x-4 gap-y-0.5 text-xs text-muted-foreground\">\n\t\t\t\t<span>relevance {row.recallRelevance.toFixed(2)}</span>\n\t\t\t\t<span>coverage {row.recallCoverage.toFixed(2)}</span>\n\t\t\t\t<span>diversity {row.recallDiversity.toFixed(2)}</span>\n\t\t\t\t<span>specificity {row.recallSpecificity.toFixed(2)}</span>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport const HydeDetailPanel: React.FC<HydeDetailPanelProps> = ({\n\tconversationId,\n\tturnIndex,\n}) => {\n\tconst { data: metrics } = useApi<RagMetricsResponse>(\n\t\tuseMemo(() => () => fetchRagMetrics(), []),\n\t\t{ pollInterval: 30_000 },\n\t);\n\tconst [showFullDoc, setShowFullDoc] = useState(false);\n\n\t// Rebuild the index whenever metrics arrive; rare enough that a full\n\t// rebuild on each render is cheaper than memoizing with a mutable dep.\n\tconst row = useMemo(\n\t\t() =>\n\t\t\tmetrics?.recent.find(\n\t\t\t\t(t) => rowKey(t.conversationId, t.turnIndex) === rowKey(conversationId, turnIndex),\n\t\t\t) ?? null,\n\t\t[metrics, conversationId, turnIndex],\n\t);\n\n\tif (!metrics) {\n\t\treturn <div className=\"text-xs text-muted-foreground\">Loading HyDE stats…</div>;\n\t}\n\tif (!row) {\n\t\treturn (\n\t\t\t<div className=\"text-xs text-muted-foreground\">\n\t\t\t\tNo HyDE/recall telemetry recorded for this turn.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst doc = row.hydeDoc ?? \"\";\n\tconst docLines = doc.split(\"\\n\").length;\n\tconst showDoc = docLines > 3;\n\tconst visibleDoc = showFullDoc || !showDoc ? doc : truncateDoc(doc, 3);\n\n\treturn (\n\t\t<Card className=\"border border-border/60 bg-bg-elevated/20 p-3\">\n\t\t\t{row.hydeRan === 1 ? (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"mb-2 flex flex-wrap items-center gap-2 text-xs\">\n\t\t\t\t\t\t<Badge variant=\"accent\">HyDE ran</Badge>\n\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\tgen <strong className=\"text-foreground\">{row.hydeGenerationMs}ms</strong>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\traw <strong className=\"text-foreground\">{row.hydeRawCount}</strong>\n\t\t\t\t\t\t\t<Arrow />\n\t\t\t\t\t\t\thyde <strong className=\"text-foreground\">{row.hydeHydeCount}</strong>\n\t\t\t\t\t\t\t<Arrow />\n\t\t\t\t\t\t\tfused <strong className=\"text-foreground\">{row.hydeFusedCount}</strong>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\tlift{\" \"}\n\t\t\t\t\t\t\t<strong className=\"text-neon\">{row.hydeLift.toFixed(2)}×</strong>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{doc && (\n\t\t\t\t\t\t<pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded-md border border-border/50 bg-bg-elevated/40 p-2 font-mono text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t{visibleDoc}\n\t\t\t\t\t\t</pre>\n\t\t\t\t\t)}\n\t\t\t\t\t{showDoc && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"mt-1 text-xs text-accent underline\"\n\t\t\t\t\t\t\tonClick={() => setShowFullDoc((v) => !v)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{showFullDoc ? \"Show less\" : \"Show full hypothetical doc\"}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex items-center gap-2 text-xs\">\n\t\t\t\t\t<Badge variant=\"warning\">HyDE skipped</Badge>\n\t\t\t\t\t<span className=\"text-muted-foreground\">{skipReason(row)}</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<ScoreLine row={row} />\n\t\t</Card>\n\t);\n};\n\nfunction Arrow(): React.ReactElement {\n\treturn <span className=\"text-muted-foreground/60\"> → </span>;\n}\n\nfunction skipReason(row: TelemetryRow): string {\n\tswitch (row.hydeReason) {\n\t\tcase \"no-llm\":\n\t\t\treturn \"No LLM embedder available (requires Ollama/HTTP embedder).\";\n\t\tcase \"generation-failed\":\n\t\t\treturn \"Hypothetical doc generation failed this turn.\";\n\t\tcase \"disabled\":\n\t\t\treturn \"HyDE is disabled (MEGACOMPACT_HYDE_DISABLED).\";\n\t\tdefault:\n\t\t\treturn \"HyDE was not invoked for this turn.\";\n\t}\n}\n"],"names":["rowKey","conversationId","turnIndex","truncateDoc","doc","maxLines","lines","ScoreLine","row","jsxs","jsx","Badge","HydeDetailPanel","metrics","useApi","useMemo","fetchRagMetrics","showFullDoc","setShowFullDoc","useState","t","showDoc","visibleDoc","Card","Fragment","Arrow","v","skipReason"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{j as e,B as k,r as a,V as E,W as R,_ as C,u as w,X as D,Y as A}from"./index-BZcYzeCr.js";import{C as p,a as j,b as f,c as y}from"./card-69DCTMel.js";import{B as g}from"./button-SyOWCGkp.js";import{S as B}from"./switch-DhQfmSFD.js";function T({columns:t}){const l=t.filter(s=>!s.present);return e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"text-xs font-semibold text-muted-foreground",children:["Column Audit (",t.length," columns, ",l.length," missing)"]}),e.jsxs("table",{className:"mt-1 w-full border-collapse text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"border-b border-border px-2 py-1 text-left font-medium text-muted-foreground",children:"Table"}),e.jsx("th",{className:"border-b border-border px-2 py-1 text-left font-medium text-muted-foreground",children:"Column"}),e.jsx("th",{className:"border-b border-border px-2 py-1 text-left font-medium text-muted-foreground",children:"Decl"}),e.jsx("th",{className:"border-b border-border px-2 py-1 text-left font-medium text-muted-foreground",children:"Status"})]})}),e.jsx("tbody",{children:t.map(s=>e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:s.table}),e.jsx("td",{className:"px-2 py-1",children:s.column}),e.jsx("td",{className:"px-2 py-1 font-mono",children:s.expectedDecl}),e.jsx("td",{className:`px-2 py-1 ${s.present?"text-emerald-400":"text-red-400"}`,children:s.present?"✓":"MISSING"})]},`${s.table}.${s.column}`))})]})]})}function L({data:t,loading:l,error:s}){return e.jsxs(p,{children:[e.jsxs(j,{className:"flex-row items-center justify-between space-y-0",children:[e.jsx(f,{children:"Schema Health"}),t&&e.jsx(k,{variant:t.healthy?"success":"danger",children:t.healthy?"HEALTHY":"DEGRADED"})]}),e.jsxs(y,{children:[l&&!t&&e.jsx("span",{className:"text-sm text-muted-foreground",children:"Loading…"}),s&&!t&&e.jsx("span",{className:"text-sm text-red-400",children:s.message}),t&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-baseline justify-between border-b border-border py-1 text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Schema version"}),e.jsx("span",{className:"font-semibold",children:t.schemaVersion})]}),e.jsxs("div",{className:"flex items-baseline justify-between border-b border-border py-1 text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Integrity"}),e.jsx("span",{className:t.integrity[0]==="ok"?"text-emerald-400":"text-red-400",children:t.integrity.join("; ")})]}),e.jsx(T,{columns:t.columns}),t.fkCheck.length>0&&e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"text-xs font-semibold text-amber-400",children:["FK Check (",t.fkCheck.length,")"]}),t.fkCheck.map((i,d)=>e.jsx("div",{className:"font-mono text-xs text-amber-400",children:i},d))]})]})]})]})}function b(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function O({files:t,pageSize:l,pageCount:s,freelistPages:i}){const d=t.dbBytes+t.walBytes+t.shmBytes;return e.jsxs("div",{className:"mt-3",children:[e.jsx("div",{className:"text-xs font-semibold text-muted-foreground",children:"File Sizes"}),e.jsx("table",{className:"mt-1 w-full border-collapse text-sm",children:e.jsxs("tbody",{children:[e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:"sqlite.db"}),e.jsx("td",{className:"px-2 py-1 text-right font-semibold",children:b(t.dbBytes)})]}),t.walBytes>0&&e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:".wal"}),e.jsx("td",{className:"px-2 py-1 text-right font-semibold",children:b(t.walBytes)})]}),t.shmBytes>0&&e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:".shm"}),e.jsx("td",{className:"px-2 py-1 text-right font-semibold",children:b(t.shmBytes)})]}),e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:"Total"}),e.jsx("td",{className:"px-2 py-1 text-right font-semibold",children:b(d)})]}),e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:"Page size"}),e.jsx("td",{className:"px-2 py-1 text-right font-semibold",children:b(l)})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1",children:"Pages"}),e.jsxs("td",{className:"px-2 py-1 text-right font-semibold",children:[s.toLocaleString()," (",i.toLocaleString()," ","free)"]})]})]})})]})}function _({tables:t}){const l=t.reduce((s,i)=>s+Math.max(0,i.rowCount),0);return e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"text-xs font-semibold text-muted-foreground",children:["Table Row Counts (",l.toLocaleString()," total)"]}),e.jsxs("table",{className:"mt-1 w-full border-collapse text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"border-b border-border px-2 py-1 text-left font-medium text-muted-foreground",children:"Table"}),e.jsx("th",{className:"border-b border-border px-2 py-1 text-right font-medium text-muted-foreground",children:"Rows"})]})}),e.jsx("tbody",{children:t.map(s=>e.jsxs("tr",{className:"border-b border-border/50",children:[e.jsx("td",{className:"px-2 py-1",children:s.table}),e.jsx("td",{className:"px-2 py-1 text-right",children:s.rowCount>=0?s.rowCount.toLocaleString():"—"})]},s.table))})]})]})}function M({data:t,loading:l,error:s}){return e.jsxs(p,{children:[e.jsx(j,{children:e.jsx(f,{children:"DB Stats"})}),e.jsxs(y,{children:[l&&!t&&e.jsx("span",{className:"text-sm text-muted-foreground",children:"Loading…"}),s&&!t&&e.jsx("span",{className:"text-sm text-red-400",children:s.message}),t&&e.jsxs(e.Fragment,{children:[e.jsx(O,{files:t.storage.files,pageSize:t.storage.pageSize,pageCount:t.storage.pageCount,freelistPages:t.storage.freelistPages}),e.jsx(_,{tables:t.tables})]})]})]})}const H=[{key:"integrity-check",label:"Integrity Check",desc:"Run PRAGMA integrity_check",dangerous:!1},{key:"reconcile-dedup",label:"Reconcile Dedup Mirror",desc:"Fix orphan dedup rows + backfill refs",dangerous:!1,confirm:"Reconcile dedup_mirror (safe read/write)?"},{key:"checkpoint",label:"WAL Checkpoint",desc:"Merge WAL into main DB (read-only)",dangerous:!1},{key:"vacuum",label:"VACUUM",desc:"Rebuild DB reclaiming free pages",dangerous:!0,confirm:"VACUUM rewrites the entire DB. Continue?"},{key:"reindex",label:"REINDEX",desc:"Rebuild all indexes",dangerous:!0,confirm:"REINDEX rebuilds indexes. Continue?"},{key:"fts5-rebuild",label:"FTS5 Rebuild",desc:"Rebuild full-text search index",dangerous:!0,confirm:"Rebuild FTS5 trigram index. Continue?"},{key:"prune",label:"Prune Old Rows",desc:"Delete transcripts + epochs older than N days",dangerous:!0,daysOld:!0,confirm:"Delete old raw_transcript rows. Continue?"}];function F(){const[t,l]=a.useState([]),[s,i]=a.useState(null),[d,m]=a.useState("30"),u=a.useCallback(async r=>{const h=r.daysOld?{action:"prune",daysOld:Number(d)}:{action:r.key};i(r.key);try{const c=await E(h);l(n=>[{...c,timestamp:Date.now()},...n].slice(0,20))}catch(c){l(n=>[{operation:r.key,success:!1,affected:0,reclaimedBytes:0,summary:c instanceof Error?c.message:String(c),timestamp:Date.now()},...n].slice(0,20))}finally{i(null)}},[d]);return e.jsxs(p,{children:[e.jsx(j,{children:e.jsx(f,{children:"Actions"})}),e.jsx("div",{className:"grid grid-cols-1 gap-3 lg:grid-cols-2",children:H.map(r=>{const h=s===r.key,c=t.find(n=>n.operation===r.key);return e.jsxs("div",{className:"flex items-start justify-between gap-3 rounded-lg border border-border/60 p-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-semibold",children:r.label}),r.dangerous&&e.jsx(k,{variant:"danger",children:"DESTRUCTIVE"})]}),e.jsx("div",{className:"mt-1 text-xs text-muted-foreground",children:r.desc}),c&&e.jsx("div",{className:`mt-1 text-xs ${c.success?"text-emerald-400":"text-red-400"}`,children:c.summary})]}),e.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[r.daysOld&&e.jsx("input",{type:"number",min:1,max:365,value:d,onChange:n=>m(n.target.value),className:"w-16 rounded-md border border-border bg-bg-elevated/50 px-2 py-1 text-sm outline-none focus:border-primary",disabled:h}),e.jsx(g,{type:"button",variant:r.dangerous?"ghost":"default",className:r.dangerous?"border border-red-500/50 text-red-400 hover:bg-red-500/10 hover:text-red-300":void 0,disabled:s!==null,onClick:()=>{r.confirm&&!window.confirm(r.confirm)||u(r)},children:h?"Running…":"Run"})]})]},r.key)})})]})}function I(){const[t,l]=a.useState(null),[s,i]=a.useState(!1),[d,m]=a.useState(null),[u,r]=a.useState(!1),h=a.useCallback(async()=>{i(!0),m(null);try{const o=await R();l(o),r(!0)}catch(o){m(o instanceof Error?o.message:String(o))}finally{i(!1)}},[]),c=a.useCallback(()=>{if(!t)return;const o=JSON.stringify(t,null,2);navigator.clipboard.writeText(o).catch(()=>{})},[t]),n=a.useCallback(()=>{if(!t)return;const o=JSON.stringify(t,null,2),S=new Blob([o],{type:"application/json"}),v=URL.createObjectURL(S),N=document.createElement("a");N.href=v,N.download=`mega-compact-debug-bundle-${t.builtAt}.json`,N.click(),URL.revokeObjectURL(v)},[t]),x=t?.criticalEvents.length??0;return e.jsxs(p,{children:[e.jsxs(j,{className:"flex-row items-center justify-between space-y-0",children:[e.jsx(f,{children:"Debug Bundle"}),x>0&&e.jsxs("span",{className:"text-xs text-amber-400",children:[x," critical event",x!==1?"s":""," found"]})]}),e.jsxs(y,{children:[e.jsx("p",{className:"mb-3 text-sm text-muted-foreground",children:"Gather a diagnostic bundle (recent events, config flags, schema health, store stats) to attach to a bug report. Critical/compaction events are highlighted."}),e.jsx(g,{type:"button",variant:"glass",onClick:h,disabled:s,children:s?"Gathering…":"Gather Debug Logs"}),d&&e.jsx("div",{className:"mt-2 text-sm text-red-400",children:d}),t&&u&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-2 mt-3 flex gap-2",children:[e.jsx(g,{type:"button",variant:"outline",size:"sm",onClick:c,children:"Copy to clipboard"}),e.jsx(g,{type:"button",variant:"outline",size:"sm",onClick:n,children:"Download JSON"}),e.jsx(g,{type:"button",variant:"outline",size:"sm",onClick:()=>r(o=>!o),children:u?"Hide":"Show"})]}),x>0&&e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"text-xs font-semibold text-amber-400",children:["Critical events (",x,")"]}),e.jsx("pre",{className:"max-h-48 overflow-auto rounded-md border border-border/60 bg-bg-elevated/40 p-3 font-mono text-xs",children:JSON.stringify(t.criticalEvents,null,2)})]}),e.jsx("pre",{className:"mt-3 max-h-96 overflow-auto rounded-md border border-border/60 bg-bg-elevated/40 p-3 font-mono text-xs",children:JSON.stringify(t,null,2)})]})]})]})}function P(){const[t,l]=a.useState(!1),[s,i]=a.useState(!0),[d,m]=a.useState(!1),[u,r]=a.useState(null),h=a.useCallback(async()=>{try{const{fetchHealthSettings:n}=await C(async()=>{const{fetchHealthSettings:o}=await import("./health-lSeDFTz7.js");return{fetchHealthSettings:o}},[],import.meta.url),x=await n();l(x.mitigate)}catch(n){r(n instanceof Error?n.message:String(n))}finally{i(!1)}},[]);a.useEffect(()=>{h()},[h]);const c=a.useCallback(async()=>{m(!0),r(null);try{const{setHealthMitigate:n}=await C(async()=>{const{setHealthMitigate:o}=await import("./health-lSeDFTz7.js");return{setHealthMitigate:o}},[],import.meta.url),x=!t;await n(x),l(x)}catch(n){r(n instanceof Error?n.message:String(n))}finally{m(!1)}},[t]);return e.jsxs(p,{children:[e.jsx(j,{children:e.jsx(f,{children:"Context Health Mitigation"})}),e.jsx(y,{children:s?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading…"}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(B,{checked:t,onCheckedChange:c,disabled:d,"aria-label":"Context health auto-mitigation"}),e.jsxs("span",{className:"text-sm",children:["Auto-mitigation ",t?"ON":"OFF"]})]}),e.jsxs("div",{className:"mt-3 space-y-2 text-sm",children:[e.jsxs("p",{children:["When ",e.jsx("strong",{children:"ON"}),", the extension automatically intervenes when context health degrades:"]}),e.jsxs("ul",{className:"list-disc space-y-1 pl-5",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Forced compaction"})," — when the composite health score drops below 0.4 (severe drift or garbled output), a compaction is triggered to flush the degraded context and rebuild from clean checkpoints, even if the context window isn't full."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Prefix break"})," — when KV cache poison is detected (score < 0.3), the cached prefix is invalidated to force a cache miss on the next turn, bypassing the corrupted KV state."]})]}),e.jsx("p",{className:"rounded-md border border-amber-500/30 bg-amber-500/5 p-3 text-amber-400",children:"WARNING: both interventions have costs — forced compaction discards live context, and prefix breaks kill cache savings. Only enable when you're seeing degraded output (garbled text, hallucinations, loss of coherence) and the Health tab confirms low scores."}),e.jsxs("p",{className:"text-muted-foreground",children:["Also settable via env var:"," ",e.jsx("code",{children:"MEGACOMPACT_CONTEXT_HEALTH_MITIGATE=1"}),". The dashboard toggle persists to the store and takes precedence."]}),u&&e.jsxs("p",{className:"text-sm text-red-400",children:["Error: ",u]})]})]})})]})}function J(){const{data:t,loading:l,error:s}=w(a.useCallback(()=>D(),[]),{pollInterval:15e3}),{data:i,loading:d,error:m}=w(a.useCallback(()=>A(),[]),{pollInterval:1e4});return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3",children:[e.jsx(L,{data:i,loading:d,error:m}),e.jsx(M,{data:t,loading:l,error:s})]}),e.jsx(F,{}),e.jsx(I,{}),e.jsx(P,{})]})}export{J as default};
2
- //# sourceMappingURL=MaintenanceTab-CoZ1mSjU.js.map
@@ -1,2 +0,0 @@
1
- import{j as e,r as u,a0 as V,a1 as z}from"./index-BZcYzeCr.js";import{T as P}from"./toggle-B3gNAVog.js";const S={checkpoint:"#6366f1",turn:"#58a6ff","turn-content":"#22c55e",memory:"#f59e0b"},U={checkpoint:"Checkpoint",turn:"Turn","turn-content":"Turn Content",memory:"Memory"};function Y(t,s){return`M 0,-${s} L ${t},0 L 0,${s} L -${t},0 Z`}function Q(t){return!t||t==="active"?1:.5}function X(t,s,l,h,n,p,c){const x=p?S[h]??"#6366f1":"#d1d5db",i=n?"#ef4444":"none",m=Q(c);switch(h){case"checkpoint":return e.jsx("circle",{cx:t,cy:s,r:n?l+3:l,fill:x,opacity:m,stroke:i,strokeWidth:n?2:0});case"turn":return e.jsx("circle",{cx:t,cy:s,r:n?l+3:l,fill:"none",stroke:x,strokeWidth:2.5,opacity:m});case"turn-content":return e.jsxs("g",{children:[e.jsx("circle",{cx:t,cy:s,r:n?l+3:l,fill:"none",stroke:x,strokeWidth:2.5,opacity:m}),e.jsx("circle",{cx:t,cy:s,r:Math.max(3,l*.3),fill:x,opacity:m})]});case"memory":const d=l*.85,g=l*.85;return e.jsx("path",{d:Y(d,g),transform:`translate(${t}, ${s})`,fill:x,opacity:m,stroke:i,strokeWidth:n?2:0})}}const Z=5e3,O=.005,D=.01,_=.9,J=.1,L=50;function K(t){const s=t.nodes.map((n,p)=>{const c=2*Math.PI*p/Math.max(t.nodes.length,1),x=200;return{...n,pos:{x:Math.cos(c)*x+300,y:Math.sin(c)*x+200},vx:0,vy:0,pinned:!1}}),l=new Map;s.forEach((n,p)=>l.set(n.id,p));const h=t.edges.map(n=>{const p=l.get(n.source),c=l.get(n.target);return p===void 0||c===void 0||p===c?null:{source:p,target:c,weight:n.weight,type:n.type}}).filter(n=>n!==null);return{nodes:s,edges:h}}function ee(t){const{nodes:s,edges:l}=t,h=s.length;if(h!==0)for(let n=0;n<h;n++){if(s[n].pinned)continue;let p=0,c=0;for(let i=0;i<h;i++){if(n===i)continue;const m=s[n].pos.x-s[i].pos.x,d=s[n].pos.y-s[i].pos.y,g=m*m+d*d||1,v=Z/g,y=Math.sqrt(g);p+=m/y*v,c+=d/y*v}for(const i of l){let m;if(i.source===n)m=i.target;else if(i.target===n)m=i.source;else continue;const d=s[m].pos.x-s[n].pos.x,g=s[m].pos.y-s[n].pos.y;p+=d*O*i.weight,c+=g*O*i.weight}p-=s[n].pos.x*D,c-=s[n].pos.y*D,s[n].vx=(s[n].vx+p)*_,s[n].vy=(s[n].vy+c)*_;const x=Math.sqrt(s[n].vx*s[n].vx+s[n].vy*s[n].vy);x>L&&(s[n].vx=s[n].vx/x*L,s[n].vy=s[n].vy/x*L),x>J&&(s[n].pos.x+=s[n].vx,s[n].pos.y+=s[n].vy)}}const te=300,re=.3,k=900,w=600,f=40;function M(t){switch(t){case"temporal":return"#6366f1";case"semantic":return"#22c55e";case"raptor_parent":return"#f59e0b"}}const N=({color:t,shape:s,label:l})=>{const h={display:"inline-block",width:"10px",height:"10px",verticalAlign:"middle",marginRight:"3px",borderRadius:s.startsWith("hollow")||s==="filled-circle"?"50%":void 0};let n;return s==="line"?e.jsx("span",{style:{color:t,marginRight:"6px"},children:l}):(s==="filled-circle"?n=e.jsx("span",{style:{...h,backgroundColor:t}}):s==="hollow-circle"?n=e.jsx("span",{style:{...h,border:`2px solid ${t}`,backgroundColor:"transparent"}}):s==="hollow-ring"?n=e.jsx("span",{style:{...h,border:`2px solid ${t}`,backgroundColor:"transparent",position:"relative"},children:e.jsx("span",{style:{display:"block",width:"4px",height:"4px",borderRadius:"50%",backgroundColor:t,margin:"2px auto"}})}):n=e.jsx("span",{style:{...h,clipPath:"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",backgroundColor:t}}),e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"memory-map-legend-item",children:[n,l]})," "]}))},se=()=>{const[t,s]=u.useState(null),[l,h]=u.useState(!0),[n,p]=u.useState(null),[c,x]=u.useState(null),[i,m]=u.useState(""),[d]=u.useState(""),[g,v]=u.useState(0),y=u.useRef(null),T=u.useRef(0);u.useEffect(()=>{let r=!1;const o=new URLSearchParams;return d&&o.set("sessionId",d),o.set("threshold","0.7"),o.set("maxEdgesPerNode","4"),h(!0),p(null),fetch(`/api/memory-map?${o.toString()}`).then(a=>{if(!a.ok)throw new Error(`HTTP ${a.status}`);return a.json()}).then(a=>{r||(s(a),y.current=K(a),v(1),h(!1))}).catch(a=>{r||(p(a instanceof Error?a.message:"Unknown error"),h(!1))}),()=>{r=!0,cancelAnimationFrame(T.current)}},[d]),u.useEffect(()=>{if(!y.current||g===0)return;const r=y.current;let o=0;const a=()=>{o>=te||(ee(r),o++,v(o),T.current=requestAnimationFrame(a))};return T.current=requestAnimationFrame(a),()=>cancelAnimationFrame(T.current)},[g]);const F=u.useCallback((r,o)=>{const a=y.current;a&&(a.nodes[o].pinned=!a.nodes[o].pinned,a.nodes[o].pinned||(a.nodes[o].vx=0,a.nodes[o].vy=0),x(b=>b?.id===r.id?null:r),v(b=>b+1))},[]),A=u.useMemo(()=>{const r=y.current;if(!r||!i)return null;const o=i.toLowerCase();return new Set(r.nodes.map((a,b)=>a.summaryTruncated.toLowerCase().includes(o)||a.label.toLowerCase().includes(o)?b:-1).filter(a=>a>=0))},[i]),C=u.useMemo(()=>{const r=t?.validation;return r?r.gatesPassed<r.gatesRun?{level:"red",label:"Gate failure"}:r.warnings.length>0?{level:"yellow",label:`${r.warnings.length} warning(s)`}:{level:"green",label:"Healthy"}:{level:"yellow",label:"No validation"}},[t?.validation]),W={green:"#22c55e",yellow:"#eab308",red:"#ef4444"},H=u.useMemo(()=>{const r=t?.validation;if(!r)return`${t?.metadata.totalNodes??0} nodes`;const o=[];return r.sources.checkpoint>0&&o.push(`${r.sources.checkpoint} checkpoints`),r.sources.turn>0&&o.push(`${r.sources.turn} turns`),r.sources.turnContent>0&&o.push(`${r.sources.turnContent} turn-content`),r.sources.memory>0&&o.push(`${r.sources.memory} memories`),o.length===0&&o.push(`${t?.metadata.totalNodes??0} nodes`),o.join(" · ")},[t?.validation,t?.metadata.totalNodes]),I=u.useMemo(()=>{const r=t?.validation;if(!r)return"";const o=[];return o.push(r.sources.checkpoint>0?"✓ checkpoints":"✗ checkpoints"),o.push(r.sources.turn>0?"✓ turns":"✗ turns"),o.push(r.sources.turnContent>0?"✓ turn-content":"✗ turn-content"),o.push(r.sources.memory>0?"✓ memories":"✗ memories"),o.join(" | ")},[t?.validation]),B=u.useMemo(()=>{const r=t?.validation;return r?r.sources.checkpoint===0&&r.sources.turn===0&&r.sources.turnContent===0&&r.sources.memory===0:t?.metadata.totalNodes===0},[t?.validation,t?.metadata.totalNodes]);if(l)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm text-muted-foreground",children:"Loading memory graph..."});if(n)return e.jsxs("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm",children:[e.jsxs("p",{className:"text-red-400",children:["Failed to load memory map: ",n]}),e.jsx("button",{className:"mt-3 rounded-md border border-border px-3 py-1.5 text-sm transition-colors hover:bg-bg-elevated hover:text-foreground",onClick:()=>v(r=>r+1),children:"Retry"})]});if(!t||!y.current||B)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-sm text-muted-foreground",children:e.jsx("p",{children:"Memories appear after your first compaction. The graph shows checkpoints (compaction summaries) linked by semantic similarity and time. Run a longer session or lower the compaction tier to see it sooner."})});const j=y.current;return e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{type:"text",placeholder:"Search memories...",value:i,onInput:r=>m(r.target.value),className:"w-56 rounded-md border border-border bg-bg-elevated/50 px-3 py-2 text-sm outline-none transition-colors focus:border-primary"}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[e.jsx("span",{children:H})," · ",e.jsxs("span",{children:[t.edges.length," edges"]})]}),e.jsx("span",{className:"ml-auto rounded-full px-2 py-1 text-[11px] font-semibold text-white",style:{backgroundColor:W[C.level]??"#6b7280"},title:`Validation: ${C.label}`,children:C.level==="green"?"Healthy":C.level==="yellow"?"Warnings":"Critical"})]}),I?e.jsx("div",{className:"text-[11px] text-muted-foreground",children:I}):null,e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1 rounded-lg border border-border/60 bg-bg-card px-3 py-2 text-xs",children:[e.jsx("span",{className:"font-semibold text-muted-foreground",children:"Nodes:"}),e.jsx(N,{type:"node",color:S.checkpoint,shape:"filled-circle",label:"Checkpoint"}),e.jsx(N,{type:"node",color:S.turn,shape:"hollow-circle",label:"Turn"}),e.jsx(N,{type:"node",color:S["turn-content"],shape:"hollow-ring",label:"Turn Content"}),e.jsx(N,{type:"node",color:S.memory,shape:"diamond",label:"Memory"}),e.jsx("span",{className:"font-semibold text-muted-foreground",children:"Edges:"}),e.jsx(N,{type:"edge",color:M("semantic"),shape:"line",label:"Semantic"}),e.jsx(N,{type:"edge",color:M("temporal"),shape:"line",label:"Temporal"}),e.jsx(N,{type:"edge",color:M("raptor_parent"),shape:"line",label:"Raptor"})]}),e.jsxs("svg",{width:k,height:w,viewBox:`0 0 ${k} ${w}`,className:"memory-map-svg",children:[j.edges.map((r,o)=>{const a=j.nodes[r.source],b=j.nodes[r.target],R=M(r.type),E=Math.max(1,r.weight*2.5);return e.jsx("line",{x1:f+a.pos.x/(j.nodes.length||1)*(k-2*f),y1:f+a.pos.y/(j.nodes.length||1)*(w-2*f),x2:f+b.pos.x/(j.nodes.length||1)*(k-2*f),y2:f+b.pos.y/(j.nodes.length||1)*(w-2*f),stroke:R,strokeWidth:E,opacity:re},`edge-${o}`)}),j.nodes.map((r,o)=>{const a=f+r.pos.x/(j.nodes.length||1)*(k-2*f),b=f+r.pos.y/(j.nodes.length||1)*(w-2*f),R=Math.min(20,8+r.tokenEstimate/500),E=A?A.has(o):!0,G=c?.id===r.id,q=r.label.length>20?r.label.slice(0,18)+"...":r.label;return e.jsxs("g",{className:"memory-map-node-group",onClick:()=>F(r,o),style:{cursor:"pointer"},children:[X(a,b,R,r.nodeType,G,E,r.dedupStatus),e.jsx("text",{x:a,y:b+R+12,textAnchor:"middle",fontSize:"9px",fill:"#374151",className:"memory-map-label",children:q})]},`node-${o}`)})]}),c?e.jsxs("div",{className:"rounded-lg border border-border/60 bg-bg-card p-4 text-sm",children:[e.jsxs("h3",{className:"font-heading text-base font-semibold",children:[e.jsx("span",{className:"mr-1.5 text-xs font-normal text-muted-foreground",children:U[c.nodeType]}),c.label]}),e.jsx("p",{className:"mt-1",children:c.summaryTruncated}),c.topicSummary?e.jsxs("p",{className:"mt-1",children:["Topic: ",c.topicSummary]}):null,e.jsxs("p",{className:"mt-1",children:["Tokens: ",c.tokenEstimate," | Decisions: ",c.decisionCount]}),e.jsxs("p",{children:["Session: ",c.sessionId]}),e.jsxs("p",{children:["Raptor Level: ",c.raptorLevel]}),e.jsx("p",{className:"mt-1 text-muted-foreground",children:c.textSnippet})]}):null]})};function ne(t){return t===0?"#d4a017":t===1?"#3b82f6":"#14b8a6"}function $(t){return t?new Date(t).toLocaleString():"—"}function oe({node:t}){const s=ne(t.level),l=t.children.length>0?`${t.children.length} child${t.children.length===1?"":"ren"}`:"leaf";return e.jsxs("div",{style:{background:"#14142b",border:`1px solid ${s}`,borderRadius:"8px",padding:"0.75rem 1rem",marginBottom:"0.6rem",marginLeft:t.level*24,maxWidth:"90%"},children:[e.jsxs("div",{style:{display:"flex",gap:"0.75rem",alignItems:"center",marginBottom:"0.35rem"},children:[e.jsxs("span",{style:{display:"inline-block",background:s,color:"#fff",borderRadius:"10px",padding:"1px 8px",fontSize:"11px",fontWeight:600},children:["L",t.level]}),e.jsxs("span",{style:{fontSize:"12px",color:"#6b7280"},children:[l," · ",t.tokenEstimate," tok · ",t.qualityMarker]}),e.jsx("span",{style:{fontSize:"12px",color:"#6b7280",marginLeft:"auto"},children:$(t.builtAt)})]}),e.jsx("div",{style:{fontSize:"0.92rem",color:"#e5e7eb"},children:t.summary})]})}function le(){const[t,s]=u.useState(null),[l,h]=u.useState(null),[n,p]=u.useState(!0),[c,x]=u.useState(null);if(u.useEffect(()=>{let d=!1;return p(!0),x(null),Promise.all([V(),z()]).then(([g,v])=>{d||(s(g),h(v),p(!1))}).catch(g=>{d||(x(g instanceof Error?g.message:"Unknown error"),p(!1))}),()=>{d=!0}},[]),n)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm text-muted-foreground",children:"Loading RAPTOR tree..."});if(c)return e.jsx("div",{className:"rounded-lg border border-dashed border-border bg-bg-card p-8 text-center text-sm",children:e.jsxs("p",{className:"text-red-400",children:["Failed to load RAPTOR tree: ",c]})});if(!t||t.empty||t.nodes.length===0)return e.jsx("div",{className:"rounded-lg border border-dashed border-border bg-bg-card p-8 text-center text-sm text-muted-foreground",children:e.jsx("p",{children:"No RAPTOR tree built yet — run a compaction (the tree builds during compaction)."})});const i=l&&!l.empty?l.builds[0]:null,m=i?.coherenceScore!=null?Math.round(i.coherenceScore*100):null;return e.jsxs("div",{className:"w-full p-4",children:[e.jsxs("div",{className:"mb-4 flex items-center gap-6 text-sm text-muted-foreground",children:[e.jsxs("span",{children:[e.jsx("strong",{children:t.nodes.length})," nodes"]}),e.jsxs("span",{children:[e.jsx("strong",{children:t.levels+1})," levels"]}),e.jsxs("span",{children:["Built ",$(t.builtAt??0)]}),i&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:["Coherence:"," ",e.jsx("strong",{style:{color:m!=null&&m>=70?"#22c55e":"#f59e0b"},children:m!=null?`${m}%`:"—"})]}),e.jsxs("span",{children:["Leaves: ",e.jsx("strong",{children:i.leafCount})]}),e.jsxs("span",{children:["Depth: ",e.jsx("strong",{children:i.depth})]}),i.timedOut&&e.jsx("span",{style:{color:"#ef4444"},children:"budget timeout"})]})]}),l&&!l.empty&&l.builds.length>1&&e.jsxs("details",{className:"mb-4",children:[e.jsxs("summary",{className:"cursor-pointer text-xs text-muted-foreground",children:["Build history (",l.builds.length," builds)"]}),e.jsx("div",{className:"mt-2 space-y-1",children:l.builds.slice(0,10).map(d=>e.jsxs("div",{className:"flex items-center gap-4 text-xs text-muted-foreground",children:[e.jsx("span",{children:$(d.completedAt)}),e.jsxs("span",{children:[d.nodeCount," nodes"]}),e.jsxs("span",{children:[d.leafCount," leaves"]}),e.jsxs("span",{children:["depth ",d.depth]}),e.jsxs("span",{children:["coherence"," ",d.coherenceScore!=null?`${Math.round(d.coherenceScore*100)}%`:"—"]}),d.timedOut&&e.jsx("span",{style:{color:"#ef4444"},children:"timeout"})]},d.buildId))})]}),t.nodes.map(d=>e.jsx(oe,{node:d},d.id))]})}const ie=()=>{const[t,s]=u.useState("map");return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("nav",{className:"flex gap-2 border-b border-border pb-2 pt-2","aria-label":"Memory map sections",children:[e.jsx(P,{pressed:t==="map",onClick:()=>s("map"),"aria-label":"Memory Map view",children:"Memory Map"}),e.jsx(P,{pressed:t==="raptor",onClick:()=>s("raptor"),"aria-label":"RAPTOR Tree view",children:"RAPTOR Tree"})]}),t==="map"&&e.jsx(se,{}),t==="raptor"&&e.jsx(le,{})]})};export{ie as default};
2
- //# sourceMappingURL=MemoryMapTab-BwVaWniY.js.map
@@ -1,2 +0,0 @@
1
- import{j as r}from"./index-BZcYzeCr.js";import{M as t}from"./MetricsCards-BCJoHe_n.js";import"./card-69DCTMel.js";import"./generateCategoricalChart-BwTtrqm5.js";import"./BarChart-Bj2oT871.js";import"./AreaChart-B5Is2_EN.js";function e(){return r.jsx(t,{})}export{e as default};
2
- //# sourceMappingURL=MetricsTab-UQSqUGXe.js.map
@@ -1,2 +0,0 @@
1
- import{r as d,j as e,u as v,D as B,E as P,F as _,G as H,H as W,B as $,o as z,b as O,I as G}from"./index-BZcYzeCr.js";import{u as K}from"./useSSE-BkkjZ4bO.js";import{C as h,c as f,a as S,b as C}from"./card-69DCTMel.js";import{R as V,C as X,X as Y,Y as q,T as U,a as Z,L as J}from"./generateCategoricalChart-BwTtrqm5.js";import{A as Q,a as ee}from"./AreaChart-B5Is2_EN.js";import{T as I}from"./toggle-B3gNAVog.js";import{B as A}from"./button-SyOWCGkp.js";import{H as te}from"./HydeDetailPanel-B-P1jTtk.js";function se(t,a){const r=new Map,n=t.map(s=>s.sessionId);for(const s of t)for(const o of s.data){let l=r.get(o.ts);if(!l){l={ts:o.ts,total:0};for(const x of n)l[x]=0;r.set(o.ts,l)}l[s.sessionId]=o.tokens}for(const s of a){let o=r.get(s.ts);if(!o){o={ts:s.ts,total:0};for(const l of n)o[l]=0;r.set(s.ts,o)}o.total=s.tokens}return[...r.values()].sort((s,o)=>s.ts-o.ts)}function M(t){return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}function D(t){const a=Number(t);return Number.isFinite(a)?a.toLocaleString():String(t)}function E(t){return`grad-${t.replace(/[^a-zA-Z0-9_-]/g,"_")}`}function re({series:t,totals:a}){const r=d.useMemo(()=>se(t,a),[t,a]);return t.length===0?e.jsx(h,{children:e.jsx(f,{children:"No token samples in this window yet."})}):e.jsx(h,{children:e.jsx(f,{children:e.jsx(V,{width:"100%",height:360,children:e.jsxs(Q,{data:r,margin:{top:8,right:16,left:0,bottom:0},children:[e.jsx("defs",{children:t.map(n=>e.jsxs("linearGradient",{id:E(n.sessionId),x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"5%",stopColor:n.color,stopOpacity:.7}),e.jsx("stop",{offset:"95%",stopColor:n.color,stopOpacity:.25})]},`${n.sessionId}-grad`))}),e.jsx(X,{strokeDasharray:"3 3",stroke:"#30363d"}),e.jsx(Y,{dataKey:"ts",type:"number",domain:["dataMin","dataMax"],tickFormatter:n=>M(n),stroke:"#8b949e",tick:{fontSize:11},scale:"time"}),e.jsx(q,{stroke:"#8b949e",tick:{fontSize:11},width:56,tickFormatter:n=>D(n)}),e.jsx(U,{labelFormatter:n=>M(n),formatter:n=>[D(n),"tokens"],contentStyle:{background:"#161b22",border:"1px solid #30363d",borderRadius:"6px",color:"#e6edf3"},labelStyle:{color:"#8b949e",fontSize:12}}),e.jsx(Z,{wrapperStyle:{fontSize:12}}),t.map(n=>e.jsx(ee,{type:"monotone",dataKey:n.sessionId,name:n.label,stackId:"1",stroke:n.color,fill:`url(#${E(n.sessionId)})`,fillOpacity:1,isAnimationActive:!1,dot:!1},n.sessionId)),e.jsx(J,{type:"monotone",dataKey:"total",name:"Total",stroke:"#e6edf3",strokeWidth:1.5,strokeDasharray:"4 2",dot:!1,isAnimationActive:!1})]})})})})}const L=["PID","Repo","Model","Context %","Tokens / Window","Last Heartbeat","State Dir","Trend"];function ne(t){const a=Math.max(0,Math.round(t/1e3));if(a<60)return`${a}s ago`;const r=Math.floor(a/60);return r<60?`${r}m ${a%60}s ago`:`${Math.floor(r/60)}h ${r%60}m ago`}function F(t){return t==null?"—":t>=1e5?`${(t/1e3).toFixed(0)}k`:t>=1e3?`${(t/1e3).toFixed(1)}k`:t.toLocaleString()}function oe(t){return t==null?"sessions-pct-ok":t>=85?"sessions-pct-err":t>=60?"sessions-pct-warn":"sessions-pct-ok"}function ae(t){return t==null?"—":`${Math.round(t)}%`}function le(t,a){return t==null?"—":`${F(t)} / ${F(a)}`}function ie({points:t,color:a}){if(t.length<2)return e.jsx("span",{className:"sessions-sparkline-empty",children:"—"});const r=Math.min(...t),s=Math.max(...t)-r||1,o=64,l=18,x=o/(t.length-1),b=t.map((p,g)=>{const j=g*x,y=l-(p-r)/s*l;return`${g===0?"M":"L"} ${j.toFixed(1)} ${y.toFixed(1)}`});return e.jsx("svg",{className:"sessions-sparkline",width:o,height:l,viewBox:`0 0 ${o} ${l}`,role:"img","aria-label":"token trend",children:e.jsx("path",{d:b.join(" "),fill:"none",stroke:a,strokeWidth:"1.5",strokeLinejoin:"round",strokeLinecap:"round"})})}function de(t){const a=new Map;for(const r of t)a.set(r.sessionId,r);return a}function ce({sessions:t,series:a}){const r=de(a),n=Date.now();return e.jsx(h,{children:e.jsx(f,{children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full border-collapse text-sm",children:[e.jsx("thead",{children:e.jsx("tr",{children:L.map((s,o)=>e.jsx("th",{className:`border-b border-border px-3 py-2 text-left font-medium text-muted-foreground${o>=3&&o!==6?" text-right":""}`,children:s},s))})}),e.jsxs("tbody",{children:[t.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:L.length,className:"px-3 py-4 text-muted-foreground",children:"No active sessions."})}),t.map(s=>{const o=r.get(s.sessionId),l=o?.data.map(b=>b.tokens)??[],x=o?.color??"#58a6ff";return e.jsxs("tr",{className:"border-b border-border/50 hover:bg-bg-elevated/40",children:[e.jsx("td",{className:"px-3 py-2 text-right font-mono",children:s.pid}),e.jsx("td",{className:"px-3 py-2",title:s.repoRoot??void 0,children:s.displayName||s.repoRoot||"—"}),e.jsx("td",{className:"px-3 py-2",children:s.model??"—"}),e.jsx("td",{className:"px-3 py-2 text-right",children:e.jsx("span",{className:`sessions-pct-pill ${oe(s.percent)}`,children:ae(s.percent)})}),e.jsx("td",{className:"px-3 py-2 text-right",children:le(s.tokens,s.ctxWindow)}),e.jsx("td",{className:"px-3 py-2 text-right",children:ne(n-s.lastSeen)}),e.jsx("td",{title:s.stateDir??void 0,className:"px-3 py-2 font-mono text-muted-foreground",children:s.stateDir?s.stateDir.split("/").pop()||s.stateDir:"—"}),e.jsx("td",{className:"px-3 py-2",children:e.jsx(ie,{points:l,color:x})})]},`${s.pid}:${s.sessionId}`)})]})]})})})})}function T(t){return t?new Date(t).toLocaleString():"—"}function xe(t){return t==="green"?"success":t==="yellow"?"warning":t==="red"?"danger":"default"}function ue(t){return t==="checkpoint"?"ckpt":t==="cluster_summary"?"raptor":"mem"}function me(){const{data:t,loading:a,error:r}=v(d.useCallback(()=>B(),[]),{pollInterval:1e4}),{data:n}=v(d.useCallback(()=>P(),[]),{pollInterval:5e3}),[s,o]=d.useState(null),[l,x]=d.useState(null),[b,p]=d.useState(!1),[g,j]=d.useState(null),[y,u]=d.useState(null),k=d.useCallback(async i=>{if(s===i){o(null),x(null);return}o(i),p(!0),x(null);try{const m=await _(i);x(m)}finally{p(!1)}},[s]),w=d.useCallback(async(i,m)=>{j(`fork:${i}:${m}`),u(null);try{const c=await H(i,m);u(`Forked → ${c.childConversationId} (${c.recalledCount} recalled)`)}catch(c){u(`Fork failed: ${c.message}`)}finally{j(null)}},[]),N=d.useCallback(async(i,m)=>{j(`rewind:${i}:${m}`),u(null);try{await W(i,m),u(`Rewind intent queued for turn ${m}`)}catch(c){u(`Rewind failed: ${c.message}`)}finally{j(null)}},[]);return r&&!t?e.jsxs("div",{className:"tab-stub",children:["Error loading turns: ",r.message]}):a&&!t?e.jsx("div",{className:"tab-stub",children:"Loading turns…"}):!t||t.conversations.length===0?e.jsxs("div",{className:"tab-stub",children:[e.jsx("h3",{children:"Turn-by-turn memory"}),e.jsxs("p",{children:["No turns recorded yet. Per-turn tracking starts when"," ",e.jsx("code",{children:"MEGACOMPACT_TURNS_DB=1"})," and the session runs through a compaction. Each turn records its context metrics + the checkpoints recalled into it."]})]}):e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("h3",{className:"font-heading text-lg font-semibold",children:"Turn-by-turn memory tracking + recall"}),y&&e.jsx($,{variant:"warning",children:y}),n&&n.intents.length>0&&e.jsxs(h,{children:[e.jsx(S,{children:e.jsxs(C,{children:["Pending rewind intents (",n.intents.length,")"]})}),e.jsx(f,{children:e.jsx("ul",{className:"list-disc space-y-1 pl-5",children:n.intents.map(i=>e.jsxs("li",{children:[T(i.createdAt)," — rewind"," ",e.jsx("code",{children:i.conversationId})," to turn ",i.targetTurnIndex]},i.id))})})]}),e.jsxs(h,{children:[e.jsx(S,{children:e.jsxs(C,{children:["Conversations (",t.conversations.length,")"]})}),e.jsx(f,{children:e.jsxs("table",{className:"w-full border-collapse text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Conversation"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Turns"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Recall"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Epochs"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Avg ctx%"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Last turn"}),e.jsx("th",{className:"border-b border-border px-3 py-2"})]})}),e.jsx("tbody",{children:t.conversations.map(i=>e.jsx(he,{c:i,active:t.activeConversationId===i.conversationId,expanded:s===i.conversationId,onExpand:()=>k(i.conversationId)},i.conversationId))})]})})]}),s&&e.jsxs(h,{children:[e.jsx(S,{children:e.jsxs(C,{children:["Turns in ",e.jsx("code",{children:s})]})}),e.jsx(f,{children:b?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Loading turns…"}):l?e.jsx(fe,{detail:l,busy:g,onFork:w,onRewind:N}):e.jsx("div",{className:"text-sm text-muted-foreground",children:"No detail."})})]})]})}function he({c:t,active:a,expanded:r,onExpand:n}){return e.jsx(e.Fragment,{children:e.jsxs("tr",{className:`border-b border-border/50 hover:bg-bg-elevated/40 ${a?"bg-primary/10":""}`,onClick:n,style:{cursor:"pointer"},children:[e.jsxs("td",{className:"px-3 py-2",children:[r?"▾":"▸"," ",e.jsx("code",{children:t.conversationId}),a&&e.jsx($,{variant:"accent",className:"ml-2",children:"active"})]}),e.jsx("td",{className:"px-3 py-2 text-right",children:t.turnCount}),e.jsx("td",{className:"px-3 py-2 text-right",children:t.totalRecall}),e.jsx("td",{className:"px-3 py-2 text-right",children:t.epochCount}),e.jsxs("td",{className:"px-3 py-2 text-right",children:[t.avgCtxPercent.toFixed(0),"%"]}),e.jsx("td",{className:"px-3 py-2",children:T(t.lastTurnAt)}),e.jsx("td",{className:"px-3 py-2"})]})})}function fe({detail:t,busy:a,onFork:r,onRewind:n}){return e.jsxs("table",{className:"w-full border-collapse text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"#"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Role"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Ctx"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Band"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Epoch"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Recalled checkpoints (memory recall)"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"HyDE"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Ended"}),e.jsx("th",{className:"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground",children:"Actions"})]})}),e.jsx("tbody",{children:t.turns.map(s=>e.jsxs("tr",{className:"border-b border-border/50 hover:bg-bg-elevated/40",children:[e.jsx("td",{className:"px-3 py-2 text-right",children:s.turnIndex}),e.jsx("td",{className:"px-3 py-2",children:s.role}),e.jsxs("td",{className:"px-3 py-2",children:[s.ctxTokens??"—",s.ctxPercent!=null&&e.jsxs("span",{className:"text-muted-foreground",children:[" ","· ",s.ctxPercent.toFixed(0),"%"]})]}),e.jsx("td",{className:"px-3 py-2",children:e.jsx($,{variant:xe(s.pressureBand),children:s.pressureBand??"—"})}),e.jsx("td",{className:"px-3 py-2",children:s.epochId?e.jsx("code",{children:s.epochId.slice(0,8)}):"—"}),e.jsx("td",{className:"px-3 py-2",children:s.recall.length===0?e.jsx("span",{className:"text-muted-foreground",children:"—"}):e.jsx("ul",{className:"space-y-1",children:s.recall.map(o=>e.jsxs("li",{children:[e.jsx("code",{children:o.checkpointId.slice(0,12)})," ",e.jsxs("span",{className:"text-muted-foreground",children:[ue(o.source)," · ",o.score.toFixed(2),o.raptorLevel!=null?` · L${o.raptorLevel}`:""]})]},o.checkpointId))})}),e.jsx("td",{className:"px-3 py-2 align-top",children:e.jsx(te,{conversationId:s.conversationId,turnIndex:s.turnIndex})}),e.jsx("td",{className:"px-3 py-2",children:T(s.endedAt)}),e.jsx("td",{className:"px-3 py-2",children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx(A,{type:"button",variant:"outline",size:"sm",disabled:a!==null,onClick:()=>r(s.conversationId,s.turnIndex),children:"fork"}),e.jsx(A,{type:"button",variant:"outline",size:"sm",disabled:a!==null,onClick:()=>n(s.conversationId,s.turnIndex),children:"rewind"})]})})]},`${s.conversationId}:${s.turnIndex}`))})]})}function pe(t){return t.type==="session_sample"}const je="MEGACOMPACT_DASH_0B";function be(t){if(!t)return!1;for(const a of t.categories)for(const r of a.settings)if(r.key===je&&r.type==="boolean")return r.value===!0;return!1}const R=[{value:5,label:"5m"},{value:15,label:"15m"},{value:30,label:"30m"},{value:60,label:"60m"}];function ge({sessions:t}){const a=t.sessions.length,r=t.sessions.reduce((o,l)=>o+(l.tokens??0),0),n=t.sessions.reduce((o,l)=>Math.max(o,l.ctxWindow),0),s=n>0?r/n*100:0;return e.jsxs("div",{className:"grid grid-cols-2 gap-4 md:grid-cols-4",children:[e.jsx(h,{children:e.jsxs(f,{children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"Active sessions"}),e.jsx("div",{className:"text-xl font-semibold",children:a})]})}),e.jsx(h,{children:e.jsxs(f,{children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"Combined tokens"}),e.jsx("div",{className:"text-xl font-semibold",children:r>=1e5?`${(r/1e3).toFixed(0)}k`:r.toLocaleString()})]})}),e.jsx(h,{children:e.jsxs(f,{children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"Combined % of max window"}),e.jsxs("div",{className:"text-xl font-semibold",children:[Math.round(s),"%"]})]})}),e.jsx(h,{children:e.jsxs(f,{children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"Pruned (stale)"}),e.jsx("div",{className:"text-xl font-semibold",children:t.pruned})]})})]})}function $e(){const[t,a]=d.useState(30),[r,n]=d.useState("active"),{data:s}=v(d.useCallback(()=>z(),[]),{pollInterval:0,maxRetries:0}),o=be(s),{data:l,error:x,refetch:b}=v(d.useCallback(()=>O(),[]),{pollInterval:2e3}),{data:p,error:g,refetch:j}=v(d.useCallback(()=>G(t),[t]),{pollInterval:2e3}),{events:y}=K(),u=d.useMemo(()=>y.filter(pe),[y]),k=d.useMemo(()=>u.length===0?null:u[u.length-1].ts,[u]);if(d.useEffect(()=>{k!=null&&(b(),j())},[k,b,j]),o&&r==="turns")return e.jsx(me,{});if(x&&!l)return e.jsxs("div",{className:"tab-stub",children:["Error loading sessions: ",x.message]});if(g&&!p)return e.jsxs("div",{className:"tab-stub",children:["Error loading timeseries: ",g.message]});if(!l)return e.jsx("div",{className:"tab-stub",children:"Loading sessions…"});const w=l.sessions,N=p?.series??[],i=p?.totals??[],m=R.find(c=>c.value===t)?.label??`${t}m`;return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Session Memory Graph"}),e.jsx("div",{className:"flex gap-2",children:R.map(c=>e.jsx(I,{pressed:t===c.value,onClick:()=>a(c.value),children:c.label},c.value))})]}),o&&e.jsxs("div",{className:"flex items-center gap-2",role:"tablist","aria-label":"Sessions views",children:[e.jsx(I,{pressed:r==="active",onClick:()=>n("active"),children:"Active Sessions"}),e.jsx(I,{pressed:r==="turns",onClick:()=>n("turns"),children:"Turn Memory"})]}),w.length===0?e.jsx("div",{className:"text-sm text-muted-foreground",children:"No active sessions."}):e.jsxs(e.Fragment,{children:[e.jsx(ge,{sessions:l}),e.jsx(re,{series:N,totals:i}),e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Active Sessions"}),e.jsx(ce,{sessions:w,series:N}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[N.length," series · ",i.length," timestamps ·"," ",m," window · updated"," ",p?.updatedAt??l.updatedAt]})]})]})}export{$e as default};
2
- //# sourceMappingURL=SessionsTab-nzd1408Z.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SessionsTab-nzd1408Z.js","sources":["../../src/components/SessionsMemoryChart.tsx","../../src/components/ActiveSessionsTable.tsx","../../src/tabs/SessionsTab/TurnMemoryView.tsx","../../src/tabs/SessionsTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/components/SessionsMemoryChart.tsx — Stacked memory graph (S39).\n *\n * Recharts stacked `<Area>` per session + total `<Line>` + `<Tooltip>` +\n * `<Legend>` + `<ResponsiveContainer>`. Data comes from `/api/sessions/timeseries`\n * which returns `SessionSeries[]` (per-session data points + stable hex color)\n * and a `totals[]` array (sum across all sessions per timestamp).\n *\n * PREVENT-PI-004: recharts is bundled into this localhost-served static\n * dashboard bundle; it makes no runtime network calls. Chart data arrives via\n * same-origin fetch to the dashboard server (loopback, ports 9320–9329).\n */\n\nimport type React from \"react\";\nimport { useMemo } from \"react\";\nimport {\n\tResponsiveContainer,\n\tAreaChart,\n\tArea,\n\tLine,\n\tXAxis,\n\tYAxis,\n\tCartesianGrid,\n\tTooltip,\n\tLegend,\n} from \"recharts\";\nimport type { SessionSeries } from \"@contracts\";\nimport { Card, CardContent } from \"../components/ui/card\";\n\nexport interface SessionsMemoryChartProps {\n\t/** Per-session series with stable colors (from /api/sessions/timeseries). */\n\tseries: SessionSeries[];\n\t/** Totals (sum across all sessions) per timestamp. */\n\ttotals: ReadonlyArray<{ ts: number; tokens: number }>;\n}\n\n/** A row in the pivoted data table passed to recharts `<AreaChart>`. */\ninterface PivotedRow {\n\t/** Unix timestamp (ms). */\n\tts: number;\n\t/** Total tokens across all sessions at this timestamp. */\n\ttotal: number;\n\t/** Per-session token count keyed by sessionId. */\n\t[sessionId: string]: number;\n}\n\n/**\n * Pivot the per-session series + totals into recharts' expected flat shape:\n * one row per unique timestamp, with each session's token count as a column\n * keyed by sessionId. Missing values for a session at a given timestamp are\n * filled with zero so the stack renders continuously.\n */\nfunction pivot(\n\tseries: SessionSeries[],\n\ttotals: ReadonlyArray<{ ts: number; tokens: number }>,\n): PivotedRow[] {\n\tconst map = new Map<number, PivotedRow>();\n\tconst sessionIds = series.map((s) => s.sessionId);\n\n\tfor (const s of series) {\n\t\tfor (const pt of s.data) {\n\t\t\tlet row = map.get(pt.ts);\n\t\t\tif (!row) {\n\t\t\t\trow = { ts: pt.ts, total: 0 } as PivotedRow;\n\t\t\t\tfor (const sid of sessionIds) row[sid] = 0;\n\t\t\t\tmap.set(pt.ts, row);\n\t\t\t}\n\t\t\trow[s.sessionId] = pt.tokens;\n\t\t}\n\t}\n\tfor (const t of totals) {\n\t\tlet row = map.get(t.ts);\n\t\tif (!row) {\n\t\t\trow = { ts: t.ts, total: 0 } as PivotedRow;\n\t\t\tfor (const sid of sessionIds) row[sid] = 0;\n\t\t\tmap.set(t.ts, row);\n\t\t}\n\t\trow.total = t.tokens;\n\t}\n\n\treturn [...map.values()].sort((a, b) => a.ts - b.ts);\n}\n\nfunction fmtTs(ts: number): string {\n\treturn new Date(ts).toLocaleTimeString([], {\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t});\n}\n\nfunction fmtTokens(value: number | string): string {\n\tconst n = Number(value);\n\treturn Number.isFinite(n) ? n.toLocaleString() : String(value);\n}\n\n/** Sanitize an arbitrary sessionId for use in an SVG gradient id. */\nfunction gradId(sessionId: string): string {\n\tconst safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\treturn `grad-${safe}`;\n}\n\nexport function SessionsMemoryChart({\n\tseries,\n\ttotals,\n}: SessionsMemoryChartProps): React.ReactElement {\n\tconst data = useMemo(\n\t\t() => pivot(series, totals),\n\t\t[series, totals],\n\t);\n\n\tif (series.length === 0) {\n\t\treturn (\n\t\t\t<Card>\n\t\t\t\t<CardContent>No token samples in this window yet.</CardContent>\n\t\t\t</Card>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Card>\n\t\t\t<CardContent>\n\t\t\t<ResponsiveContainer width=\"100%\" height={360}>\n\t\t\t\t<AreaChart\n\t\t\t\t\tdata={data}\n\t\t\t\t\tmargin={{ top: 8, right: 16, left: 0, bottom: 0 }}\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t{series.map((s) => (\n\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\tkey={`${s.sessionId}-grad`}\n\t\t\t\t\t\t\t\tid={gradId(s.sessionId)}\n\t\t\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t\t\tx2=\"0\"\n\t\t\t\t\t\t\t\ty2=\"1\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<stop offset=\"5%\" stopColor={s.color} stopOpacity={0.7} />\n\t\t\t\t\t\t\t\t<stop offset=\"95%\" stopColor={s.color} stopOpacity={0.25} />\n\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</defs>\n\t\t\t\t\t<CartesianGrid strokeDasharray=\"3 3\" stroke=\"#30363d\" />\n\t\t\t\t\t<XAxis\n\t\t\t\t\t\tdataKey=\"ts\"\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tdomain={[\"dataMin\", \"dataMax\"]}\n\t\t\t\t\t\ttickFormatter={(ts: number) => fmtTs(ts)}\n\t\t\t\t\t\tstroke=\"#8b949e\"\n\t\t\t\t\t\ttick={{ fontSize: 11 }}\n\t\t\t\t\t\tscale=\"time\"\n\t\t\t\t\t/>\n\t\t\t\t\t<YAxis\n\t\t\t\t\t\tstroke=\"#8b949e\"\n\t\t\t\t\t\ttick={{ fontSize: 11 }}\n\t\t\t\t\t\twidth={56}\n\t\t\t\t\t\ttickFormatter={(v: number) => fmtTokens(v)}\n\t\t\t\t\t/>\n\t\t\t\t\t<Tooltip\n\t\t\t\t\t\tlabelFormatter={(ts: number) => fmtTs(ts)}\n\t\t\t\t\t\tformatter={(value) =>\n\t\t\t\t\t\t\t[fmtTokens(value as number), \"tokens\"] as [string, string]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontentStyle={{\n\t\t\t\t\t\t\tbackground: \"#161b22\",\n\t\t\t\t\t\t\tborder: \"1px solid #30363d\",\n\t\t\t\t\t\t\tborderRadius: \"6px\",\n\t\t\t\t\t\t\tcolor: \"#e6edf3\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tlabelStyle={{ color: \"#8b949e\", fontSize: 12 }}\n\t\t\t\t\t/>\n\t\t\t\t\t<Legend wrapperStyle={{ fontSize: 12 }} />\n\t\t\t\t\t{series.map((s) => (\n\t\t\t\t\t\t<Area\n\t\t\t\t\t\t\tkey={s.sessionId}\n\t\t\t\t\t\t\ttype=\"monotone\"\n\t\t\t\t\t\t\tdataKey={s.sessionId}\n\t\t\t\t\t\t\tname={s.label}\n\t\t\t\t\t\t\tstackId=\"1\"\n\t\t\t\t\t\t\tstroke={s.color}\n\t\t\t\t\t\t\tfill={`url(#${gradId(s.sessionId)})`}\n\t\t\t\t\t\t\tfillOpacity={1}\n\t\t\t\t\t\t\tisAnimationActive={false}\n\t\t\t\t\t\t\tdot={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t\t<Line\n\t\t\t\t\t\ttype=\"monotone\"\n\t\t\t\t\t\tdataKey=\"total\"\n\t\t\t\t\t\tname=\"Total\"\n\t\t\t\t\t\tstroke=\"#e6edf3\"\n\t\t\t\t\t\tstrokeWidth={1.5}\n\t\t\t\t\t\tstrokeDasharray=\"4 2\"\n\t\t\t\t\t\tdot={false}\n\t\t\t\t\t\tisAnimationActive={false}\n\t\t\t\t\t/>\n\t\t\t\t</AreaChart>\n\t\t\t</ResponsiveContainer>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n","/**\n * dashboard-client/src/components/ActiveSessionsTable.tsx — Active sessions table (S39).\n *\n * Per-session rows: PID, Repo, Model, Context %, Tokens/Window,\n * Heartbeat age, State dir, Sparkline.\n *\n * Data from /api/sessions (active sessions list) and /api/sessions/timeseries\n * (per-session data points used to render inline sparklines).\n */\n\nimport type React from \"react\";\nimport type { ActiveSession, SessionSeries } from \"@contracts\";\nimport { Card, CardContent } from \"../components/ui/card\";\n\nexport interface ActiveSessionsTableProps {\n\t/** Active sessions, sorted by lastSeen descending (from /api/sessions). */\n\tsessions: ActiveSession[];\n\t/** Per-session timeseries used to render the inline sparkline column. */\n\tseries: SessionSeries[];\n}\n\nconst HEADERS = [\n\t\"PID\",\n\t\"Repo\",\n\t\"Model\",\n\t\"Context %\",\n\t\"Tokens / Window\",\n\t\"Last Heartbeat\",\n\t\"State Dir\",\n\t\"Trend\",\n] as const;\n\n/** Format a duration in milliseconds → human-readable age string. */\nfunction fmtAge(ms: number): string {\n\tconst s = Math.max(0, Math.round(ms / 1000));\n\tif (s < 60) return `${s}s ago`;\n\tconst m = Math.floor(s / 60);\n\tif (m < 60) return `${m}m ${s % 60}s ago`;\n\tconst h = Math.floor(m / 60);\n\treturn `${h}h ${m % 60}m ago`;\n}\n\nfunction fmtTokens(n: number | null): string {\n\tif (n == null) return \"\\u2014\";\n\tif (n >= 100_000) return `${(n / 1000).toFixed(0)}k`;\n\tif (n >= 1000) return `${(n / 1000).toFixed(1)}k`;\n\treturn n.toLocaleString();\n}\n\nfunction pctClass(pct: number | null): string {\n\tif (pct == null) return \"sessions-pct-ok\";\n\tif (pct >= 85) return \"sessions-pct-err\";\n\tif (pct >= 60) return \"sessions-pct-warn\";\n\treturn \"sessions-pct-ok\";\n}\n\nfunction fmtPct(pct: number | null): string {\n\tif (pct == null) return \"\\u2014\";\n\treturn `${Math.round(pct)}%`;\n}\n\nfunction fmtWindow(tokens: number | null, window: number): string {\n\tif (tokens == null) return \"\\u2014\";\n\treturn `${fmtTokens(tokens)} / ${fmtTokens(window)}`;\n}\n\ninterface SparklineProps {\n\t/** Token counts over time (oldest → newest). */\n\tpoints: number[];\n\t/** Stable hex color for the stroke. */\n\tcolor: string;\n}\n\nfunction Sparkline({ points, color }: SparklineProps): React.ReactElement {\n\tif (points.length < 2) {\n\t\treturn <span className=\"sessions-sparkline-empty\">{\"\\u2014\"}</span>;\n\t}\n\tconst min = Math.min(...points);\n\tconst max = Math.max(...points);\n\tconst range = max - min || 1;\n\tconst w = 64;\n\tconst h = 18;\n\tconst stepX = w / (points.length - 1);\n\tconst segments = points.map((p, i) => {\n\t\tconst x = i * stepX;\n\t\tconst y = h - ((p - min) / range) * h;\n\t\treturn `${i === 0 ? \"M\" : \"L\"} ${x.toFixed(1)} ${y.toFixed(1)}`;\n\t});\n\treturn (\n\t\t<svg\n\t\t\tclassName=\"sessions-sparkline\"\n\t\t\twidth={w}\n\t\t\theight={h}\n\t\t\tviewBox={`0 0 ${w} ${h}`}\n\t\t\trole=\"img\"\n\t\t\taria-label=\"token trend\"\n\t\t>\n\t\t\t<path\n\t\t\t\td={segments.join(\" \")}\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke={color}\n\t\t\t\tstrokeWidth=\"1.5\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\n/** Map sessionId → series for the sparkline column lookup. */\nfunction indexSeries(\n\tseries: SessionSeries[],\n): Map<string, SessionSeries> {\n\tconst m = new Map<string, SessionSeries>();\n\tfor (const s of series) m.set(s.sessionId, s);\n\treturn m;\n}\n\nexport function ActiveSessionsTable({\n\tsessions,\n\tseries,\n}: ActiveSessionsTableProps): React.ReactElement {\n\tconst seriesById = indexSeries(series);\n\tconst now = Date.now();\n\n\treturn (\n\t\t<Card>\n\t\t\t<CardContent>\n\t\t\t<div className=\"overflow-x-auto\">\n\t\t\t\t<table className=\"w-full border-collapse text-sm\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t{HEADERS.map((h, i) => (\n\t\t\t\t\t\t\t\t<th\n\t\t\t\t\t\t\t\t\tkey={h}\n\t\t\t\t\t\t\t\t\tclassName={`border-b border-border px-3 py-2 text-left font-medium text-muted-foreground${\n\t\t\t\t\t\t\t\t\t\ti >= 3 && i !== 6 ? \" text-right\" : \"\"\n\t\t\t\t\t\t\t\t\t}`}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{h}\n\t\t\t\t\t\t\t\t</th>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{sessions.length === 0 && (\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td colSpan={HEADERS.length} className=\"px-3 py-4 text-muted-foreground\">\n\t\t\t\t\t\t\t\t\tNo active sessions.\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{sessions.map((s) => {\n\t\t\t\t\t\t\tconst srs = seriesById.get(s.sessionId);\n\t\t\t\t\t\t\tconst sparkPts =\n\t\t\t\t\t\t\t\tsrs?.data.map((d) => d.tokens) ?? [];\n\t\t\t\t\t\t\tconst color = srs?.color ?? \"#58a6ff\";\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<tr\n\t\t\t\t\t\t\t\t\tkey={`${s.pid}:${s.sessionId}`}\n\t\t\t\t\t\t\t\t\tclassName=\"border-b border-border/50 hover:bg-bg-elevated/40\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2 text-right font-mono\">{s.pid}</td>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2\" title={s.repoRoot ?? undefined}>\n\t\t\t\t\t\t\t\t\t\t{s.displayName || s.repoRoot || \"\\u2014\"}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2\">{s.model ?? \"\\u2014\"}</td>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2 text-right\">\n\t\t\t\t\t\t\t\t\t\t<span className={`sessions-pct-pill ${pctClass(s.percent)}`}>\n\t\t\t\t\t\t\t\t\t\t\t{fmtPct(s.percent)}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2 text-right\">\n\t\t\t\t\t\t\t\t\t\t{fmtWindow(s.tokens, s.ctxWindow)}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2 text-right\">{fmtAge(now - s.lastSeen)}</td>\n\t\t\t\t\t\t\t\t\t<td\n\t\t\t\t\t\t\t\t\t\ttitle={s.stateDir ?? undefined}\n\t\t\t\t\t\t\t\t\t\tclassName=\"px-3 py-2 font-mono text-muted-foreground\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{s.stateDir\n\t\t\t\t\t\t\t\t\t\t\t? s.stateDir.split(\"/\").pop() || s.stateDir\n\t\t\t\t\t\t\t\t\t\t\t: \"\\u2014\"}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t\t\t\t\t\t<Sparkline points={sparkPts} color={color} />\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n","/**\n * dashboard-client/src/tabs/SessionsTab/TurnMemoryView.tsx — Turn-by-turn memory\n * tracking + recall (S52), moved VERBATIM from the top-level TurnsTab.tsx.\n *\n * DASH-0b: the Sessions surface absorbs the existent TurnsTab as a drill-down.\n * This file holds the byte-preserved turns body (the `TurnMemoryView`\n * component). The standalone `tabs/TurnsTab.tsx` is LEFT UNTOUCHED this sprint —\n * its copy stays live for flag-off / pre-DASH parity. A DASH-0d cleanup deletes\n * the standalone copy after a deep-link audit proves no live consumer points\n * at it. Only the export name changed (TurnsTab → TurnMemoryView); the render\n * body is otherwise identical.\n *\n * Fetches /api/turns (conversation list), expands the active conversation into\n * per-turn detail (/api/turns/conversation/:id), and renders:\n * - Conversation summary list (turn count, recall total, epochs, last turn).\n * - Per-turn rows: turn index, role, ctx tokens/percent + pressure band,\n * epoch id, and the injected-checkpoint recall set (the memory recalled\n * at each turn, with score + source).\n * - Pending rewind intents (S52A) + Fork action (S50C primitive).\n *\n * Read-mostly via /api/turns; fork/intent/prune via POST. No absolute URLs\n * (PREVENT-PI-004: loopback-only, same-origin static bundle).\n */\n\nimport type React from \"react\";\nimport { useCallback, useState } from \"react\";\nimport { useApi } from \"../../hooks/useApi\";\nimport {\n\tfetchTurns,\n\tfetchConversationTurns,\n\tfetchTurnIntents,\n\tpostFork,\n\tpostTurnIntent,\n} from \"../../api/client\";\nimport type {\n\tTurnsResponse,\n\tConversationTurnsResponse,\n\tRewindIntentsResponse,\n\tTurnRow,\n\tConversationSummary,\n} from \"@contracts\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"../../components/ui/card\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { HydeDetailPanel } from \"../../components/HydeDetailPanel\";\n\nfunction fmtTs(ms: number): string {\n\tif (!ms) return \"—\";\n\treturn new Date(ms).toLocaleString();\n}\n\nfunction bandVariant(band: TurnRow[\"pressureBand\"]): \"success\" | \"warning\" | \"danger\" | \"default\" {\n\tif (band === \"green\") return \"success\";\n\tif (band === \"yellow\") return \"warning\";\n\tif (band === \"red\") return \"danger\";\n\treturn \"default\";\n}\n\nfunction sourceLabel(s: TurnRow[\"recall\"][number][\"source\"]): string {\n\tif (s === \"checkpoint\") return \"ckpt\";\n\tif (s === \"cluster_summary\") return \"raptor\";\n\treturn \"mem\";\n}\n\nexport function TurnMemoryView(): React.ReactElement {\n\tconst {\n\t\tdata: turns,\n\t\tloading,\n\t\terror,\n\t} = useApi<TurnsResponse>(\n\t\tuseCallback(() => fetchTurns(), []),\n\t\t{\n\t\t\tpollInterval: 10_000,\n\t\t},\n\t);\n\tconst { data: intents } = useApi<RewindIntentsResponse>(\n\t\tuseCallback(() => fetchTurnIntents(), []),\n\t\t{ pollInterval: 5_000 },\n\t);\n\tconst [expanded, setExpanded] = useState<string | null>(null);\n\tconst [detail, setDetail] = useState<ConversationTurnsResponse | null>(null);\n\tconst [detailLoading, setDetailLoading] = useState(false);\n\tconst [busy, setBusy] = useState<string | null>(null);\n\tconst [notice, setNotice] = useState<string | null>(null);\n\n\tconst expand = useCallback(\n\t\tasync (conversationId: string) => {\n\t\t\tif (expanded === conversationId) {\n\t\t\t\tsetExpanded(null);\n\t\t\t\tsetDetail(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetExpanded(conversationId);\n\t\t\tsetDetailLoading(true);\n\t\t\tsetDetail(null);\n\t\t\ttry {\n\t\t\t\tconst d = await fetchConversationTurns(conversationId);\n\t\t\t\tsetDetail(d);\n\t\t\t} finally {\n\t\t\t\tsetDetailLoading(false);\n\t\t\t}\n\t\t},\n\t\t[expanded],\n\t);\n\n\tconst onFork = useCallback(\n\t\tasync (conversationId: string, turnIndex: number) => {\n\t\t\tsetBusy(`fork:${conversationId}:${turnIndex}`);\n\t\t\tsetNotice(null);\n\t\t\ttry {\n\t\t\t\tconst out = await postFork(conversationId, turnIndex);\n\t\t\t\tsetNotice(\n\t\t\t\t\t`Forked → ${out.childConversationId} (${out.recalledCount} recalled)`,\n\t\t\t\t);\n\t\t\t} catch (e) {\n\t\t\t\tsetNotice(`Fork failed: ${(e as Error).message}`);\n\t\t\t} finally {\n\t\t\t\tsetBusy(null);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst onRewind = useCallback(\n\t\tasync (conversationId: string, turnIndex: number) => {\n\t\t\tsetBusy(`rewind:${conversationId}:${turnIndex}`);\n\t\t\tsetNotice(null);\n\t\t\ttry {\n\t\t\t\tawait postTurnIntent(conversationId, turnIndex);\n\t\t\t\tsetNotice(`Rewind intent queued for turn ${turnIndex}`);\n\t\t\t} catch (e) {\n\t\t\t\tsetNotice(`Rewind failed: ${(e as Error).message}`);\n\t\t\t} finally {\n\t\t\t\tsetBusy(null);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tif (error && !turns) {\n\t\treturn <div className=\"tab-stub\">Error loading turns: {error.message}</div>;\n\t}\n\tif (loading && !turns) {\n\t\treturn <div className=\"tab-stub\">Loading turns…</div>;\n\t}\n\tif (!turns || turns.conversations.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">\n\t\t\t\t<h3>Turn-by-turn memory</h3>\n\t\t\t\t<p>\n\t\t\t\t\tNo turns recorded yet. Per-turn tracking starts when{\" \"}\n\t\t\t\t\t<code>MEGACOMPACT_TURNS_DB=1</code> and the session runs through a\n\t\t\t\t\tcompaction. Each turn records its context metrics + the checkpoints\n\t\t\t\t\trecalled into it.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<h3 className=\"font-heading text-lg font-semibold\">\n\t\t\t\tTurn-by-turn memory tracking + recall\n\t\t\t</h3>\n\t\t\t{notice && <Badge variant=\"warning\">{notice}</Badge>}\n\n\t\t\t{intents && intents.intents.length > 0 && (\n\t\t\t\t<Card>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<CardTitle>\n\t\t\t\t\t\t\tPending rewind intents ({intents.intents.length})\n\t\t\t\t\t\t</CardTitle>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<CardContent>\n\t\t\t\t\t\t<ul className=\"list-disc space-y-1 pl-5\">\n\t\t\t\t\t\t\t{intents.intents.map((i) => (\n\t\t\t\t\t\t\t\t<li key={i.id}>\n\t\t\t\t\t\t\t\t\t{fmtTs(i.createdAt)} — rewind{\" \"}\n\t\t\t\t\t\t\t\t\t<code>{i.conversationId}</code> to turn {i.targetTurnIndex}\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t<Card>\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<CardTitle>\n\t\t\t\t\t\tConversations ({turns.conversations.length})\n\t\t\t\t\t</CardTitle>\n\t\t\t\t</CardHeader>\n\t\t\t\t<CardContent>\n\t\t\t\t\t<table className=\"w-full border-collapse text-sm\">\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Conversation</th>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Turns</th>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Recall</th>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Epochs</th>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Avg ctx%</th>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Last turn</th>\n\t\t\t\t\t\t\t\t<th className=\"border-b border-border px-3 py-2\"></th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{turns.conversations.map((c: ConversationSummary) => (\n\t\t\t\t\t\t\t\t<ConversationRow\n\t\t\t\t\t\t\t\t\tkey={c.conversationId}\n\t\t\t\t\t\t\t\t\tc={c}\n\t\t\t\t\t\t\t\t\tactive={turns.activeConversationId === c.conversationId}\n\t\t\t\t\t\t\t\t\texpanded={expanded === c.conversationId}\n\t\t\t\t\t\t\t\t\tonExpand={() => expand(c.conversationId)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\n\t\t\t{expanded && (\n\t\t\t\t<Card>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<CardTitle>\n\t\t\t\t\t\t\tTurns in <code>{expanded}</code>\n\t\t\t\t\t\t</CardTitle>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<CardContent>\n\t\t\t\t\t\t{detailLoading ? (\n\t\t\t\t\t\t\t<div className=\"text-sm text-muted-foreground\">Loading turns…</div>\n\t\t\t\t\t\t) : detail ? (\n\t\t\t\t\t\t\t<TurnDetail\n\t\t\t\t\t\t\t\tdetail={detail}\n\t\t\t\t\t\t\t\tbusy={busy}\n\t\t\t\t\t\t\t\tonFork={onFork}\n\t\t\t\t\t\t\t\tonRewind={onRewind}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"text-sm text-muted-foreground\">No detail.</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ConversationRow({\n\tc,\n\tactive,\n\texpanded,\n\tonExpand,\n}: {\n\tc: ConversationSummary;\n\tactive: boolean;\n\texpanded: boolean;\n\tonExpand: () => void;\n}): React.ReactElement {\n\treturn (\n\t\t<>\n\t\t\t<tr\n\t\t\t\tclassName={`border-b border-border/50 hover:bg-bg-elevated/40 ${\n\t\t\t\t\tactive ? \"bg-primary/10\" : \"\"\n\t\t\t\t}`}\n\t\t\t\tonClick={onExpand}\n\t\t\t\tstyle={{ cursor: \"pointer\" }}\n\t\t\t>\n\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t{expanded ? \"▾\" : \"▸\"} <code>{c.conversationId}</code>\n\t\t\t\t\t{active && <Badge variant=\"accent\" className=\"ml-2\">active</Badge>}\n\t\t\t\t</td>\n\t\t\t\t<td className=\"px-3 py-2 text-right\">{c.turnCount}</td>\n\t\t\t\t<td className=\"px-3 py-2 text-right\">{c.totalRecall}</td>\n\t\t\t\t<td className=\"px-3 py-2 text-right\">{c.epochCount}</td>\n\t\t\t\t<td className=\"px-3 py-2 text-right\">{c.avgCtxPercent.toFixed(0)}%</td>\n\t\t\t\t<td className=\"px-3 py-2\">{fmtTs(c.lastTurnAt)}</td>\n\t\t\t\t<td className=\"px-3 py-2\" />\n\t\t\t</tr>\n\t\t</>\n\t);\n}\n\nfunction TurnDetail({\n\tdetail,\n\tbusy,\n\tonFork,\n\tonRewind,\n}: {\n\tdetail: ConversationTurnsResponse;\n\tbusy: string | null;\n\tonFork: (conversationId: string, turnIndex: number) => void;\n\tonRewind: (conversationId: string, turnIndex: number) => void;\n}): React.ReactElement {\n\treturn (\n\t\t<table className=\"w-full border-collapse text-sm\">\n\t\t\t<thead>\n\t\t\t\t<tr>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">#</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Role</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Ctx</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Band</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Epoch</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Recalled checkpoints (memory recall)</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">HyDE</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Ended</th>\n\t\t\t\t\t<th className=\"border-b border-border px-3 py-2 text-left font-medium text-muted-foreground\">Actions</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t{detail.turns.map((t) => (\n\t\t\t\t\t<tr\n\t\t\t\t\t\tkey={`${t.conversationId}:${t.turnIndex}`}\n\t\t\t\t\t\tclassName=\"border-b border-border/50 hover:bg-bg-elevated/40\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<td className=\"px-3 py-2 text-right\">{t.turnIndex}</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">{t.role}</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t\t\t{t.ctxTokens ?? \"—\"}\n\t\t\t\t\t\t\t{t.ctxPercent != null && (\n\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{\" \"}\n\t\t\t\t\t\t\t\t\t· {t.ctxPercent.toFixed(0)}%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t\t\t<Badge variant={bandVariant(t.pressureBand)}>\n\t\t\t\t\t\t\t\t{t.pressureBand ?? \"—\"}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">{t.epochId ? <code>{t.epochId.slice(0, 8)}</code> : \"—\"}</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t\t\t{t.recall.length === 0 ? (\n\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">—</span>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<ul className=\"space-y-1\">\n\t\t\t\t\t\t\t\t\t{t.recall.map((r) => (\n\t\t\t\t\t\t\t\t\t\t<li key={r.checkpointId}>\n\t\t\t\t\t\t\t\t\t\t\t<code>{r.checkpointId.slice(0, 12)}</code>{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t{sourceLabel(r.source)} · {r.score.toFixed(2)}\n\t\t\t\t\t\t\t\t\t\t\t\t{r.raptorLevel != null ? ` · L${r.raptorLevel}` : \"\"}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2 align-top\">\n\t\t\t\t\t\t\t<HydeDetailPanel\n\t\t\t\t\t\t\t\tconversationId={t.conversationId}\n\t\t\t\t\t\t\t\tturnIndex={t.turnIndex}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">{fmtTs(t.endedAt)}</td>\n\t\t\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tdisabled={busy !== null}\n\t\t\t\t\t\t\t\t\tonClick={() => onFork(t.conversationId, t.turnIndex)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tfork\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tdisabled={busy !== null}\n\t\t\t\t\t\t\t\t\tonClick={() => onRewind(t.conversationId, t.turnIndex)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\trewind\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t))}\n\t\t\t</tbody>\n\t\t</table>\n\t);\n}\n","/**\n * dashboard-client/src/tabs/SessionsTab.tsx — Sessions tab (S39, DASH-0b).\n *\n * DASH-0b: the Sessions surface absorbs the existent TurnsTab as a drill-down.\n * A `SessionsViews` toggle (\"Active Sessions\" / \"Turn Memory\") switches between\n * the existent sessions summary/chart/table body and the turns view (rendered by\n * `SessionsTab/TurnMemoryView.tsx` — the turns body moved VERBATIM from the\n * standalone TurnsTab.tsx, which is left untouched this sprint for flag-off\n * parity).\n *\n * Flag: `MEGACOMPACT_DASH_0B` default ON. The dashboard client is a browser\n * bundle with NO `process` global, so the positive sprint flag cannot be read\n * server-side-style (`process.env`) inside the client. Instead the flag is read\n * from the server-authoritative `/api/rag-settings` state: the server resolves\n * `process.env[\"MEGACOMPACT_DASH_0B\"] ?? default` into the `SettingState.value`\n * boolean. When the flag is OFF (settings confirmed value=false), this surface\n * renders ONLY the existent sessions body — no toggle, no TurnMemoryView branch\n * (byte-identical predecessor). The standalone TurnsTab.tsx top-level surface is\n * untouched and remains reachable for flag-off parity.\n *\n * Data sources: fetchSessions() + fetchSessionTimeseries(minutes). Both poll\n * every 2s for near-real-time updates. useSSE() listens for session_sample\n * events emitted by appendTokenSample (Step 5) so the chart refetches\n * instantly between polls when a new token sample is appended to events.log.\n *\n * Empty state: shows \"No active sessions.\" when the /api/sessions response\n * returns an empty array (e.g. no pi processes are running yet).\n */\n\nimport type React from \"react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useApi } from \"../hooks/useApi\";\nimport { useSSE } from \"../hooks/useSSE\";\nimport { fetchSessions, fetchSessionTimeseries, fetchSettings } from \"../api/client\";\nimport type {\n\tSseEvent,\n\tSseSessionSample,\n\tSessionsResponse,\n\tSessionTimeseriesResponse,\n\tSettingsResponse,\n} from \"@contracts\";\nimport { SessionsMemoryChart } from \"../components/SessionsMemoryChart\";\nimport { ActiveSessionsTable } from \"../components/ActiveSessionsTable\";\nimport { Toggle } from \"../components/ui/toggle\";\nimport { Card, CardContent } from \"../components/ui/card\";\nimport { TurnMemoryView } from \"./SessionsTab/TurnMemoryView\";\n\n/**\n * Shape of the {@link SseSessionSample} SSE event appended to events.log by\n * `appendTokenSample` (src/store/sqlite/global-index.ts). The contract now\n * defines this variant as part of the {@link SseEvent} union (Step 5); the\n * local alias keeps the surface terser in this file.\n */\ntype SessionSampleEvent = SseSessionSample;\n\n/** Type guard: narrows an SSE event to a session_sample event. */\nfunction isSessionSample(\n\te: SseEvent,\n): e is SessionSampleEvent {\n\treturn e.type === \"session_sample\";\n}\n\nconst DASH_0B_KEY = \"MEGACOMPACT_DASH_0B\";\n\n/** Resolve the DASH-0b consolidation flag from the server settings state.\n * Absent/not-yet-loaded => false (flag-off posture), so flag-off users never\n * see a toggle flash; the toggle appears only once settings confirm it is ON. */\nfunction dash0bEnabled(settings: SettingsResponse | null): boolean {\n\tif (!settings) return false;\n\tfor (const cat of settings.categories) {\n\t\tfor (const s of cat.settings) {\n\t\t\tif (s.key === DASH_0B_KEY && s.type === \"boolean\") return s.value === true;\n\t\t}\n\t}\n\treturn false;\n}\n\nconst WINDOWS: ReadonlyArray<{ value: number; label: string }> = [\n\t{ value: 5, label: \"5m\" },\n\t{ value: 15, label: \"15m\" },\n\t{ value: 30, label: \"30m\" },\n\t{ value: 60, label: \"60m\" },\n] as const;\n\ninterface SummaryTilesProps {\n\tsessions: SessionsResponse;\n}\n\nfunction SummaryTiles({ sessions }: SummaryTilesProps): React.ReactElement {\n\tconst active = sessions.sessions.length;\n\tconst combinedTokens = sessions.sessions.reduce(\n\t\t(sum, s) => sum + (s.tokens ?? 0),\n\t\t0,\n\t);\n\tconst maxWindow = sessions.sessions.reduce(\n\t\t(max, s) => Math.max(max, s.ctxWindow),\n\t\t0,\n\t);\n\tconst combinedPct = maxWindow > 0 ? (combinedTokens / maxWindow) * 100 : 0;\n\treturn (\n\t\t<div className=\"grid grid-cols-2 gap-4 md:grid-cols-4\">\n\t\t\t<Card>\n\t\t\t\t<CardContent>\n\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">Active sessions</span>\n\t\t\t\t\t<div className=\"text-xl font-semibold\">{active}</div>\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t\t<Card>\n\t\t\t\t<CardContent>\n\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">Combined tokens</span>\n\t\t\t\t\t<div className=\"text-xl font-semibold\">\n\t\t\t\t\t\t{combinedTokens >= 100_000\n\t\t\t\t\t\t\t? `${(combinedTokens / 1000).toFixed(0)}k`\n\t\t\t\t\t\t\t: combinedTokens.toLocaleString()}\n\t\t\t\t\t</div>\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t\t<Card>\n\t\t\t\t<CardContent>\n\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\tCombined % of max window\n\t\t\t\t\t</span>\n\t\t\t\t\t<div className=\"text-xl font-semibold\">{Math.round(combinedPct)}%</div>\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t\t<Card>\n\t\t\t\t<CardContent>\n\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">Pruned (stale)</span>\n\t\t\t\t\t<div className=\"text-xl font-semibold\">{sessions.pruned}</div>\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t</div>\n\t);\n}\n\ntype SessionsView = \"active\" | \"turns\";\n\nexport default function SessionsTab(): React.ReactElement {\n\tconst [minutes, setMinutes] = useState(30);\n\tconst [view, setView] = useState<SessionsView>(\"active\");\n\n\tconst {\n\t\tdata: settingsData,\n\t} = useApi<SettingsResponse>(\n\t\tuseCallback(() => fetchSettings(), []),\n\t\t{ pollInterval: 0, maxRetries: 0 },\n\t);\n\tconst dash0bOn = dash0bEnabled(settingsData);\n\n\tconst {\n\t\tdata: sessionsData,\n\t\terror: sessionsErr,\n\t\trefetch: refetchSessions,\n\t} = useApi<SessionsResponse>(\n\t\tuseCallback(() => fetchSessions(), []),\n\t\t{ pollInterval: 2_000 },\n\t);\n\n\tconst {\n\t\tdata: timeseriesData,\n\t\terror: timeseriesErr,\n\t\trefetch: refetchTimeseries,\n\t} = useApi<SessionTimeseriesResponse>(\n\t\tuseCallback(() => fetchSessionTimeseries(minutes), [minutes]),\n\t\t{ pollInterval: 2_000 },\n\t);\n\n\tconst { events } = useSSE();\n\n\t// Filter SSE events for session_sample pushes (Step 5) and trigger an\n\t// immediate refetch when a new sample arrives, so the chart updates\n\t// between the 2s polls. The events array grows as new samples arrive; the\n\t// length-based dependency means the effect re-runs when a new sample event\n\t// lands (not on every poll). We debounce via a microtask guard.\n\tconst sampleEvents = useMemo(\n\t\t() => events.filter(isSessionSample),\n\t\t[events],\n\t);\n\n\tconst lastSampleTs = useMemo(() => {\n\t\tif (sampleEvents.length === 0) return null;\n\t\treturn sampleEvents[sampleEvents.length - 1].ts;\n\t}, [sampleEvents]);\n\n\tuseEffect(() => {\n\t\tif (lastSampleTs == null) return;\n\t\trefetchSessions();\n\t\trefetchTimeseries();\n\t}, [lastSampleTs, refetchSessions, refetchTimeseries]);\n\n\tif (dash0bOn && view === \"turns\") {\n\t\treturn <TurnMemoryView />;\n\t}\n\n\tif (sessionsErr && !sessionsData) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">\n\t\t\t\tError loading sessions: {sessionsErr.message}\n\t\t\t</div>\n\t\t);\n\t}\n\tif (timeseriesErr && !timeseriesData) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">\n\t\t\t\tError loading timeseries: {timeseriesErr.message}\n\t\t\t</div>\n\t\t);\n\t}\n\tif (!sessionsData) {\n\t\treturn <div className=\"tab-stub\">Loading sessions…</div>;\n\t}\n\n\tconst sessions = sessionsData.sessions;\n\tconst series = timeseriesData?.series ?? [];\n\tconst totals = timeseriesData?.totals ?? [];\n\tconst windowLabel =\n\t\tWINDOWS.find((w) => w.value === minutes)?.label ?? `${minutes}m`;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<h2 className=\"font-heading text-lg font-semibold\">\n\t\t\t\t\tSession Memory Graph\n\t\t\t\t</h2>\n\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t{WINDOWS.map((w) => (\n\t\t\t\t\t\t<Toggle\n\t\t\t\t\t\t\tkey={w.value}\n\t\t\t\t\t\t\tpressed={minutes === w.value}\n\t\t\t\t\t\t\tonClick={() => setMinutes(w.value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{w.label}\n\t\t\t\t\t\t</Toggle>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{dash0bOn && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"flex items-center gap-2\"\n\t\t\t\t\trole=\"tablist\"\n\t\t\t\t\taria-label=\"Sessions views\"\n\t\t\t\t>\n\t\t\t\t\t<Toggle\n\t\t\t\t\t\tpressed={view === \"active\"}\n\t\t\t\t\t\tonClick={() => setView(\"active\")}\n\t\t\t\t\t>\n\t\t\t\t\t\tActive Sessions\n\t\t\t\t\t</Toggle>\n\t\t\t\t\t<Toggle\n\t\t\t\t\t\tpressed={view === \"turns\"}\n\t\t\t\t\t\tonClick={() => setView(\"turns\")}\n\t\t\t\t\t>\n\t\t\t\t\t\tTurn Memory\n\t\t\t\t\t</Toggle>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{sessions.length === 0 ? (\n\t\t\t\t<div className=\"text-sm text-muted-foreground\">No active sessions.</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<SummaryTiles sessions={sessionsData} />\n\t\t\t\t\t<SessionsMemoryChart series={series} totals={totals} />\n\t\t\t\t\t<h2 className=\"font-heading text-lg font-semibold\">\n\t\t\t\t\t\tActive Sessions\n\t\t\t\t\t</h2>\n\t\t\t\t\t<ActiveSessionsTable sessions={sessions} series={series} />\n\t\t\t\t\t<div className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t{series.length} series · {totals.length} timestamps ·{\" \"}\n\t\t\t\t\t\t{windowLabel} window · updated{\" \"}\n\t\t\t\t\t\t{timeseriesData?.updatedAt ?? sessionsData.updatedAt}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"names":["pivot","series","totals","map","sessionIds","pt","row","sid","t","a","b","fmtTs","ts","fmtTokens","value","n","gradId","sessionId","SessionsMemoryChart","data","useMemo","jsx","Card","CardContent","ResponsiveContainer","jsxs","AreaChart","s","CartesianGrid","XAxis","YAxis","v","Tooltip","Legend","Area","Line","HEADERS","fmtAge","ms","m","pctClass","pct","fmtPct","fmtWindow","tokens","window","Sparkline","points","color","min","range","w","h","stepX","segments","i","x","indexSeries","ActiveSessionsTable","sessions","seriesById","now","srs","sparkPts","d","bandVariant","band","sourceLabel","TurnMemoryView","turns","loading","error","useApi","useCallback","fetchTurns","intents","fetchTurnIntents","expanded","setExpanded","useState","detail","setDetail","detailLoading","setDetailLoading","busy","setBusy","notice","setNotice","expand","conversationId","fetchConversationTurns","onFork","turnIndex","out","postFork","e","onRewind","postTurnIntent","Badge","CardHeader","CardTitle","c","ConversationRow","TurnDetail","active","onExpand","Fragment","r","HydeDetailPanel","Button","isSessionSample","DASH_0B_KEY","dash0bEnabled","settings","cat","WINDOWS","SummaryTiles","combinedTokens","sum","maxWindow","max","combinedPct","SessionsTab","minutes","setMinutes","view","setView","settingsData","fetchSettings","dash0bOn","sessionsData","sessionsErr","refetchSessions","fetchSessions","timeseriesData","timeseriesErr","refetchTimeseries","fetchSessionTimeseries","events","useSSE","sampleEvents","lastSampleTs","useEffect","windowLabel","Toggle"],"mappings":"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"}