pi-mega-compact 0.13.4 → 0.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +50 -0
- package/dist/extensions/dashboard-server/api-contracts/rag-metrics.js +1 -0
- package/dist/extensions/dashboard-server/api-contracts/rag-settings.js +3 -3
- package/dist/extensions/dashboard-server/api-contracts/wiki.js +1 -0
- package/dist/extensions/dashboard-server/routes-rag-metrics.js +60 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +167 -0
- package/dist/extensions/dashboard-server/routes-rag-settings.js +136 -77
- package/dist/extensions/dashboard-server/routes-wiki-helpers.js +97 -0
- package/dist/extensions/dashboard-server/routes-wiki.js +330 -0
- package/dist/extensions/dashboard-server/routes.js +2 -0
- package/dist/extensions/dashboard-server/server.js +17 -3
- package/dist/extensions/mega-events/context-handler/afterCompact.js +35 -2
- package/dist/extensions/mega-pipeline/recall.js +31 -0
- package/dist/extensions/mega-turn-store.js +2 -1
- package/dist/src/config/turns.js +10 -0
- package/dist/src/config.js +2 -0
- package/dist/src/recall/async.js +10 -1
- package/dist/src/recall/format.js +10 -1
- package/dist/src/recall/hydeTelemetry.js +22 -0
- package/dist/src/recall/sync.js +28 -2
- package/dist/src/store/turns/hydeStore.js +32 -0
- package/dist/src/store/turns/index.js +1 -0
- package/dist/src/store/turns/schema.js +102 -1
- package/dist/src/store/turns/sqlite-store/rows.js +23 -0
- package/dist/src/store/turns/sqlite-store/write.js +7 -3
- package/dist/src/topics/durability.js +187 -0
- package/dist/src/topics/index.js +2 -1
- package/dist/src/topics/store.js +28 -9
- package/dist/src/wiki/curation-helpers.js +71 -0
- package/dist/src/wiki/curation.js +147 -0
- package/dist/src/wiki/incremental.js +126 -0
- package/dist/src/wiki/index.js +5 -0
- package/extensions/dashboard-client/dist/assets/AreaChart-KAmp_6bL.js +70 -0
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C30AwyoF.js.map → AreaChart-KAmp_6bL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-Bk-gm-R0.js +2 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-Bk-gm-R0.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-Cyylo0of.js +2 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-Cyylo0of.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-D-IzmV29.js +2 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-D-IzmV29.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-CrlkCFVj.js +2 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-CrlkCFVj.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DHUdZ7RR.js +2 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DHUdZ7RR.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-B7I4HWVg.js +2 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-B7I4HWVg.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-K6j4ZI7u.js +2 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-K6j4ZI7u.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-BSRWhn56.js +2 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-BSRWhn56.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/SessionsTab-BXdizHN1.js +2 -0
- package/extensions/dashboard-client/dist/assets/SessionsTab-BXdizHN1.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CAgyfqY3.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CAgyfqY3.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-DwgCzPD9.js +2 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-DwgCzPD9.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TurnsTab-CVKcStBp.js +5 -0
- package/extensions/dashboard-client/dist/assets/TurnsTab-CVKcStBp.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-BNohxTbs.js +2 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-BNohxTbs.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/button-B4A-_dCA.js +2 -0
- package/extensions/dashboard-client/dist/assets/button-B4A-_dCA.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/card-Cjn7Ifoe.js +2 -0
- package/extensions/dashboard-client/dist/assets/card-Cjn7Ifoe.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-CQjCLvv7.js +137 -0
- package/extensions/dashboard-client/dist/assets/index-CQjCLvv7.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +1 -0
- package/extensions/dashboard-client/dist/assets/switch-CcdXX0Zm.js +2 -0
- package/extensions/dashboard-client/dist/assets/switch-CcdXX0Zm.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/toggle-KdBnFLu3.js +2 -0
- package/extensions/dashboard-client/dist/assets/toggle-KdBnFLu3.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js → useSSE-B6t44vzc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-p1pOI_-P.js.map → useSSE-B6t44vzc.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/package-lock.json +1995 -191
- package/extensions/dashboard-client/package.json +12 -1
- package/extensions/dashboard-client/postcss.config.js +6 -0
- package/extensions/dashboard-client/src/App.tsx +127 -88
- package/extensions/dashboard-client/src/api/client.ts +109 -10
- package/extensions/dashboard-client/src/components/ActiveReposTable.tsx +15 -7
- package/extensions/dashboard-client/src/components/ActiveSessionsTable.tsx +67 -55
- package/extensions/dashboard-client/src/components/CacheHitRateTrendCard.tsx +17 -13
- package/extensions/dashboard-client/src/components/CacheHitsCard.tsx +35 -30
- package/extensions/dashboard-client/src/components/CacheStatusPerModel.tsx +33 -28
- package/extensions/dashboard-client/src/components/EventCategoryFilter.tsx +5 -6
- package/extensions/dashboard-client/src/components/EventStream.tsx +17 -13
- package/extensions/dashboard-client/src/components/HydeDetailPanel.tsx +173 -0
- package/extensions/dashboard-client/src/components/LegendCard.tsx +16 -9
- package/extensions/dashboard-client/src/components/PerfCards.tsx +28 -20
- package/extensions/dashboard-client/src/components/PerfChart.tsx +9 -6
- package/extensions/dashboard-client/src/components/ProviderCacheCard.tsx +15 -7
- package/extensions/dashboard-client/src/components/RagDashboard.tsx +253 -0
- package/extensions/dashboard-client/src/components/RepoAllSessionsCard.tsx +15 -10
- package/extensions/dashboard-client/src/components/RepoContextStack.tsx +24 -16
- package/extensions/dashboard-client/src/components/RepoDetailModal.tsx +52 -49
- package/extensions/dashboard-client/src/components/RepoTable.tsx +26 -17
- package/extensions/dashboard-client/src/components/SessionContextGauges.tsx +11 -14
- package/extensions/dashboard-client/src/components/SessionInfo.tsx +20 -15
- package/extensions/dashboard-client/src/components/SessionsMemoryChart.tsx +8 -5
- package/extensions/dashboard-client/src/components/SummaryTiles.tsx +26 -17
- package/extensions/dashboard-client/src/components/TabBar.tsx +1 -3
- package/extensions/dashboard-client/src/components/layout/AppShell.tsx +42 -0
- package/extensions/dashboard-client/src/components/layout/BottomBar.tsx +88 -0
- package/extensions/dashboard-client/src/components/layout/Sidebar.tsx +83 -0
- package/extensions/dashboard-client/src/components/ui/badge.tsx +30 -0
- package/extensions/dashboard-client/src/components/ui/button.tsx +44 -0
- package/extensions/dashboard-client/src/components/ui/card.tsx +32 -0
- package/extensions/dashboard-client/src/components/ui/select.tsx +64 -0
- package/extensions/dashboard-client/src/components/ui/switch.tsx +26 -0
- package/extensions/dashboard-client/src/components/ui/tabs.tsx +36 -0
- package/extensions/dashboard-client/src/components/ui/toggle.tsx +28 -0
- package/extensions/dashboard-client/src/components/ui/tooltip.tsx +27 -0
- package/extensions/dashboard-client/src/config.ts +10 -0
- package/extensions/dashboard-client/src/main.tsx +2 -2
- package/extensions/dashboard-client/src/memory-map-layout.ts +1 -2
- package/extensions/dashboard-client/src/styles/index.css +79 -0
- package/extensions/dashboard-client/src/tabs/CacheTab.tsx +33 -26
- package/extensions/dashboard-client/src/tabs/EventsTab.tsx +22 -7
- package/extensions/dashboard-client/src/tabs/HealthTab.tsx +77 -46
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/ActionsCard.tsx +60 -50
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/DbStatsCard.tsx +61 -35
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/DebugBundleCard.tsx +34 -23
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/HealthMitigationCard.tsx +62 -43
- package/extensions/dashboard-client/src/tabs/MaintenanceTab/SchemaHealthCard.tsx +53 -32
- package/extensions/dashboard-client/src/tabs/MaintenanceTab.tsx +2 -2
- package/extensions/dashboard-client/src/tabs/MemoryMapTab/MemoryMapView.tsx +29 -46
- package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +10 -34
- package/extensions/dashboard-client/src/tabs/MemoryMapTab.tsx +14 -34
- package/extensions/dashboard-client/src/tabs/MetricsTab.tsx +5 -2
- package/extensions/dashboard-client/src/tabs/OverviewTab.tsx +11 -5
- package/extensions/dashboard-client/src/tabs/ReposTab.tsx +5 -5
- package/extensions/dashboard-client/src/tabs/SessionsTab.tsx +47 -33
- package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetup.tsx +6 -2
- package/extensions/dashboard-client/src/tabs/SetupTab/RagHealthCard.tsx +78 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/SettingsPanel.tsx +198 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/SettingsSection.tsx +50 -0
- package/extensions/dashboard-client/src/tabs/SetupTab.tsx +21 -59
- package/extensions/dashboard-client/src/tabs/TopicsTab.tsx +75 -40
- package/extensions/dashboard-client/src/tabs/TurnsTab.tsx +150 -112
- package/extensions/dashboard-client/src/tabs/WikiTab/TopicEvolutionGraph.tsx +274 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/TopicEvolutionView.tsx +71 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/TopicTimeline.tsx +103 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/WikiPage.tsx +213 -0
- package/extensions/dashboard-client/src/tabs/WikiTab/WikiPageControls.tsx +188 -0
- package/extensions/dashboard-client/src/tabs/WikiTab.tsx +222 -0
- package/extensions/dashboard-client/src/tabs/registry.ts +57 -0
- package/extensions/dashboard-client/src/utils/cn.ts +7 -0
- package/extensions/dashboard-client/tailwind.config.js +46 -0
- package/extensions/dashboard-server/api-contracts/core.ts +59 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +79 -0
- package/extensions/dashboard-server/api-contracts/index.ts +48 -2
- package/extensions/dashboard-server/api-contracts/rag-metrics.ts +22 -0
- package/extensions/dashboard-server/api-contracts/rag-settings.ts +30 -20
- package/extensions/dashboard-server/api-contracts/wiki.ts +138 -0
- package/extensions/dashboard-server/routes-rag-metrics.ts +82 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +314 -0
- package/extensions/dashboard-server/routes-rag-settings.ts +147 -97
- package/extensions/dashboard-server/routes-wiki-helpers.ts +126 -0
- package/extensions/dashboard-server/routes-wiki.ts +376 -0
- package/extensions/dashboard-server/routes.ts +2 -0
- package/extensions/dashboard-server/server.ts +18 -2
- package/extensions/mega-events/context-handler/afterCompact.ts +44 -1
- package/extensions/mega-pipeline/recall.ts +31 -0
- package/extensions/mega-turn-store.ts +13 -0
- package/package.json +1 -1
- package/src/config/turns.ts +17 -0
- package/src/config.ts +3 -0
- package/src/recall/async.ts +10 -1
- package/src/recall/format.ts +15 -2
- package/src/recall/hydeTelemetry.ts +44 -0
- package/src/recall/sync.ts +34 -2
- package/src/recall/types.ts +36 -0
- package/src/store/turns/hydeStore.ts +82 -0
- package/src/store/turns/index.ts +4 -0
- package/src/store/turns/schema.ts +126 -1
- package/src/store/turns/sqlite-store/rows.ts +25 -0
- package/src/store/turns/sqlite-store/write.ts +20 -2
- package/src/store/turns/types.ts +33 -0
- package/src/topics/durability.ts +231 -0
- package/src/topics/index.ts +7 -1
- package/src/topics/store.ts +35 -9
- package/src/wiki/curation-helpers.ts +140 -0
- package/src/wiki/curation.ts +217 -0
- package/src/wiki/incremental.ts +164 -0
- package/src/wiki/index.ts +13 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-Cqnc7lMg.js +0 -2
- package/extensions/dashboard-client/dist/assets/CacheTab-Cqnc7lMg.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/EventsTab-tYk3VFAp.js +0 -2
- package/extensions/dashboard-client/dist/assets/EventsTab-tYk3VFAp.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/HealthTab-D2_kjgxw.js +0 -2
- package/extensions/dashboard-client/dist/assets/HealthTab-D2_kjgxw.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js +0 -2
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-Bc-uPYrz.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js +0 -2
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-D1V9g_NC.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-DT_XfL96.js +0 -2
- package/extensions/dashboard-client/dist/assets/MetricsTab-DT_XfL96.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/OverviewTab-BY6KZCme.js +0 -2
- package/extensions/dashboard-client/dist/assets/OverviewTab-BY6KZCme.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/ReposTab-CeS-tpDM.js +0 -2
- package/extensions/dashboard-client/dist/assets/ReposTab-CeS-tpDM.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/SessionsTab-C30AwyoF.js +0 -70
- package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-BJUHOVK2.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-p55K1tFP.js +0 -2
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-p55K1tFP.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TopicsTab-D8FqyAbK.js +0 -2
- package/extensions/dashboard-client/dist/assets/TopicsTab-D8FqyAbK.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TurnsTab-ju-nXDys.js +0 -2
- package/extensions/dashboard-client/dist/assets/TurnsTab-ju-nXDys.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js +0 -42
- package/extensions/dashboard-client/dist/assets/index-BEj1Zahy.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-CUNn22iV.css +0 -1
- package/extensions/dashboard-client/src/styles/metrics-extra.css +0 -69
- package/extensions/dashboard-client/src/styles/turns.css +0 -142
- package/extensions/dashboard-client/src/tabs/SetupTab/RagSettingsCard.tsx +0 -160
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
3
|
+
import { Check } from "lucide-react";
|
|
4
|
+
import { cn } from "../../utils/cn";
|
|
5
|
+
|
|
6
|
+
const Select = SelectPrimitive.Root;
|
|
7
|
+
const SelectValue = SelectPrimitive.Value;
|
|
8
|
+
|
|
9
|
+
const SelectTrigger = React.forwardRef<
|
|
10
|
+
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
11
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
12
|
+
>(({ className, children, ...props }, ref) => (
|
|
13
|
+
<SelectPrimitive.Trigger
|
|
14
|
+
ref={ref}
|
|
15
|
+
className={cn(
|
|
16
|
+
"flex h-9 w-full items-center justify-between rounded-md border border-border bg-bg-elevated px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary/60",
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</SelectPrimitive.Trigger>
|
|
23
|
+
));
|
|
24
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
25
|
+
|
|
26
|
+
const SelectContent = React.forwardRef<
|
|
27
|
+
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
28
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
29
|
+
>(({ className, children, ...props }, ref) => (
|
|
30
|
+
<SelectPrimitive.Portal>
|
|
31
|
+
<SelectPrimitive.Content
|
|
32
|
+
ref={ref}
|
|
33
|
+
className={cn("z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-bg-elevated text-foreground shadow-panel", className)}
|
|
34
|
+
{...props}
|
|
35
|
+
>
|
|
36
|
+
<SelectPrimitive.Viewport className="p-1">{children}</SelectPrimitive.Viewport>
|
|
37
|
+
</SelectPrimitive.Content>
|
|
38
|
+
</SelectPrimitive.Portal>
|
|
39
|
+
));
|
|
40
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
41
|
+
|
|
42
|
+
const SelectItem = React.forwardRef<
|
|
43
|
+
React.ElementRef<typeof SelectPrimitive.Item>,
|
|
44
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
45
|
+
>(({ className, children, ...props }, ref) => (
|
|
46
|
+
<SelectPrimitive.Item
|
|
47
|
+
ref={ref}
|
|
48
|
+
className={cn(
|
|
49
|
+
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm text-foreground focus:bg-primary/15 focus:text-neon data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
>
|
|
54
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
55
|
+
<SelectPrimitive.ItemIndicator>
|
|
56
|
+
<Check className="h-4 w-4" />
|
|
57
|
+
</SelectPrimitive.ItemIndicator>
|
|
58
|
+
</span>
|
|
59
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
60
|
+
</SelectPrimitive.Item>
|
|
61
|
+
));
|
|
62
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
63
|
+
|
|
64
|
+
export { Select, SelectValue, SelectTrigger, SelectContent, SelectItem };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
|
3
|
+
import { cn } from "../../utils/cn";
|
|
4
|
+
|
|
5
|
+
const Switch = React.forwardRef<
|
|
6
|
+
React.ElementRef<typeof SwitchPrimitives.Root>,
|
|
7
|
+
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
|
8
|
+
>(({ className, ...props }, ref) => (
|
|
9
|
+
<SwitchPrimitives.Root
|
|
10
|
+
ref={ref}
|
|
11
|
+
className={cn(
|
|
12
|
+
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-border transition-colors data-[state=checked]:bg-primary data-[state=unchecked]:bg-bg-elevated focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
className,
|
|
14
|
+
)}
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
<SwitchPrimitives.Thumb
|
|
18
|
+
className={cn(
|
|
19
|
+
"pointer-events-none block h-4 w-4 rounded-full bg-foreground shadow-lg transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0.5",
|
|
20
|
+
)}
|
|
21
|
+
/>
|
|
22
|
+
</SwitchPrimitives.Root>
|
|
23
|
+
));
|
|
24
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
25
|
+
|
|
26
|
+
export { Switch };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
3
|
+
import { cn } from "../../utils/cn";
|
|
4
|
+
|
|
5
|
+
const Tabs = TabsPrimitive.Root;
|
|
6
|
+
|
|
7
|
+
const TabsList = React.forwardRef<
|
|
8
|
+
React.ElementRef<typeof TabsPrimitive.List>,
|
|
9
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
10
|
+
>(({ className, ...props }, ref) => (
|
|
11
|
+
<TabsPrimitive.List
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn("inline-flex items-center gap-1 rounded-lg bg-bg-elevated p-1", className)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
));
|
|
17
|
+
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
18
|
+
|
|
19
|
+
const TabsTrigger = React.forwardRef<
|
|
20
|
+
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
21
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
22
|
+
>(({ className, ...props }, ref) => (
|
|
23
|
+
<TabsPrimitive.Trigger
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn(
|
|
26
|
+
"inline-flex items-center justify-center gap-2 rounded-md px-3 py-1.5 text-sm font-medium text-muted transition-all hover:text-foreground data-[state=active]:bg-primary/15 data-[state=active]:text-neon",
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
33
|
+
|
|
34
|
+
const TabsContent = TabsPrimitive.Content;
|
|
35
|
+
|
|
36
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "../../utils/cn";
|
|
3
|
+
|
|
4
|
+
export interface ToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
pressed?: boolean;
|
|
6
|
+
onPressedChange?: (pressed: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Toggle({ pressed, onPressedChange, className, onClick, ...props }: ToggleProps) {
|
|
10
|
+
return (
|
|
11
|
+
<button
|
|
12
|
+
type="button"
|
|
13
|
+
aria-pressed={pressed}
|
|
14
|
+
onClick={(e) => {
|
|
15
|
+
onClick?.(e);
|
|
16
|
+
onPressedChange?.(!pressed);
|
|
17
|
+
}}
|
|
18
|
+
className={cn(
|
|
19
|
+
"inline-flex items-center justify-center rounded-md border px-3 py-1.5 text-sm font-medium transition-all",
|
|
20
|
+
pressed
|
|
21
|
+
? "border-primary/50 bg-primary/15 text-neon glow-primary"
|
|
22
|
+
: "border-border bg-transparent text-muted hover:text-foreground",
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
+
import { cn } from "../../utils/cn";
|
|
4
|
+
|
|
5
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
6
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
7
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
8
|
+
|
|
9
|
+
const TooltipContent = React.forwardRef<
|
|
10
|
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
11
|
+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
|
12
|
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
13
|
+
<TooltipPrimitive.Portal>
|
|
14
|
+
<TooltipPrimitive.Content
|
|
15
|
+
ref={ref}
|
|
16
|
+
sideOffset={sideOffset}
|
|
17
|
+
className={cn(
|
|
18
|
+
"z-50 overflow-hidden rounded-md border border-border bg-bg-elevated px-3 py-1.5 text-xs text-foreground shadow-panel",
|
|
19
|
+
className,
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
</TooltipPrimitive.Portal>
|
|
24
|
+
));
|
|
25
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
26
|
+
|
|
27
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
@@ -7,18 +7,18 @@
|
|
|
7
7
|
import { StrictMode } from "react";
|
|
8
8
|
import { createRoot } from "react-dom/client";
|
|
9
9
|
import App from "./App";
|
|
10
|
+
// Tailwind + design tokens (Spec 1)
|
|
11
|
+
import "./styles/index.css";
|
|
10
12
|
import "./styles/base.css";
|
|
11
13
|
import "./styles/overview-events.css";
|
|
12
14
|
import "./styles/repos-metrics.css";
|
|
13
15
|
import "./styles/repos-extra.css";
|
|
14
16
|
import "./styles/overview-extra.css";
|
|
15
17
|
import "./styles/config.css";
|
|
16
|
-
import "./styles/metrics-extra.css";
|
|
17
18
|
import "./styles/game-achievements.css";
|
|
18
19
|
import "./styles/sessions.css";
|
|
19
20
|
import "./styles/repostack.css";
|
|
20
21
|
import "./styles/session-gauges.css";
|
|
21
|
-
import "./styles/turns.css";
|
|
22
22
|
import "./styles/maintenance.css";
|
|
23
23
|
import "./styles/cache.css";
|
|
24
24
|
|
|
@@ -48,7 +48,7 @@ export interface LayoutEdge {
|
|
|
48
48
|
source: number;
|
|
49
49
|
target: number;
|
|
50
50
|
weight: number;
|
|
51
|
-
type:
|
|
51
|
+
type: GraphEdgeMin["type"];
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export interface Layout {
|
|
@@ -135,7 +135,6 @@ export function applyForces(layout: Layout): void {
|
|
|
135
135
|
else continue;
|
|
136
136
|
const dx = nodes[other].pos.x - nodes[i].pos.x;
|
|
137
137
|
const dy = nodes[other].pos.y - nodes[i].pos.y;
|
|
138
|
-
const dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
139
138
|
fx += dx * ATTRACTION * e.weight;
|
|
140
139
|
fy += dy * ATTRACTION * e.weight;
|
|
141
140
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer base {
|
|
6
|
+
:root {
|
|
7
|
+
--bg: 222 47% 5%;
|
|
8
|
+
--bg-card: 222 32% 8%;
|
|
9
|
+
--bg-elevated: 222 28% 12%;
|
|
10
|
+
--border: 217 33% 17%;
|
|
11
|
+
--foreground: 210 40% 98%;
|
|
12
|
+
--muted: 215 20% 65%;
|
|
13
|
+
--primary: 217 91% 60%;
|
|
14
|
+
--primary-glow: 217 91% 60%;
|
|
15
|
+
--success: 142 71% 45%;
|
|
16
|
+
--warning: 38 92% 50%;
|
|
17
|
+
--danger: 0 84% 60%;
|
|
18
|
+
--accent: 280 100% 70%;
|
|
19
|
+
--radius: 0.75rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
* {
|
|
23
|
+
@apply border-border;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
html {
|
|
27
|
+
@apply bg-background text-foreground antialiased;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
body {
|
|
31
|
+
@apply bg-background text-foreground font-sans;
|
|
32
|
+
margin: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h1, h2, h3, h4, h5, h6 {
|
|
36
|
+
font-family: theme("fontFamily.heading");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:where(button, [role="tab"], a):focus-visible {
|
|
40
|
+
outline: 2px solid hsl(var(--primary) / 0.6);
|
|
41
|
+
outline-offset: 2px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@layer components {
|
|
46
|
+
.glass-panel {
|
|
47
|
+
@apply relative rounded-lg border border-border bg-bg-card/70 backdrop-blur-md;
|
|
48
|
+
box-shadow:
|
|
49
|
+
inset 0 1px 0 0 hsl(var(--border) / 0.5),
|
|
50
|
+
var(--tw-shadow, 0 8px 30px -12px hsl(var(--bg) / 0.6));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.electric-hover {
|
|
54
|
+
@apply transition-all duration-200 hover:-translate-y-0.5;
|
|
55
|
+
}
|
|
56
|
+
.electric-hover:hover {
|
|
57
|
+
border-color: hsl(var(--primary) / 0.7);
|
|
58
|
+
box-shadow: 0 0 20px -4px hsl(var(--primary-glow) / 0.45);
|
|
59
|
+
}
|
|
60
|
+
.electric-hover:focus-visible {
|
|
61
|
+
outline: 2px solid hsl(var(--primary) / 0.6);
|
|
62
|
+
outline-offset: 2px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.glow-primary {
|
|
66
|
+
box-shadow: 0 0 20px -4px hsl(var(--primary-glow) / 0.5);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.text-neon {
|
|
70
|
+
color: hsl(var(--primary));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.gradient-text {
|
|
74
|
+
background: linear-gradient(120deg, hsl(var(--primary)), hsl(var(--accent)));
|
|
75
|
+
-webkit-background-clip: text;
|
|
76
|
+
background-clip: text;
|
|
77
|
+
color: transparent;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -30,6 +30,8 @@ import { TimeSavedCard } from "../components/TimeSavedCard";
|
|
|
30
30
|
import { ProviderCacheCard } from "../components/ProviderCacheCard";
|
|
31
31
|
import { StripeDistributionCard } from "../components/StripeDistributionCard";
|
|
32
32
|
import { CacheHitRateTrendCard } from "../components/CacheHitRateTrendCard";
|
|
33
|
+
import { Button } from "../components/ui/button";
|
|
34
|
+
import { Card, CardContent, CardHeader, CardTitle } from "../components/ui/card";
|
|
33
35
|
|
|
34
36
|
export default function CacheTab(): React.ReactElement {
|
|
35
37
|
const [infoExpanded, setInfoExpanded] = useState(false);
|
|
@@ -74,38 +76,43 @@ export default function CacheTab(): React.ReactElement {
|
|
|
74
76
|
);
|
|
75
77
|
|
|
76
78
|
return (
|
|
77
|
-
<div className="
|
|
78
|
-
<div
|
|
79
|
-
<
|
|
79
|
+
<div className="flex flex-col gap-4">
|
|
80
|
+
<div>
|
|
81
|
+
<Button
|
|
80
82
|
type="button"
|
|
81
|
-
|
|
83
|
+
variant="outline"
|
|
82
84
|
onClick={() => setInfoExpanded(!infoExpanded)}
|
|
83
85
|
>
|
|
84
86
|
{infoExpanded ? "Hide Guidance" : "Show Cache-Friendly Prompt Ordering Guidance"}
|
|
85
|
-
</
|
|
87
|
+
</Button>
|
|
86
88
|
{infoExpanded && (
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
<Card className="mt-3">
|
|
90
|
+
<CardHeader>
|
|
91
|
+
<CardTitle>Cache-Friendly Prompt Ordering</CardTitle>
|
|
92
|
+
</CardHeader>
|
|
93
|
+
<CardContent>
|
|
94
|
+
<ul className="list-disc space-y-1 pl-5">
|
|
95
|
+
<li>Keep system prompts and stable context at the top of your conversation — the provider caches the leading prefix.</li>
|
|
96
|
+
<li>Tool results and volatile content are automatically moved to the tail by message separation (<code>MEGACOMPACT_MESSAGE_SEPARATION</code>) so they don't invalidate the cache prefix.</li>
|
|
97
|
+
<li>Cache striping (<code>MEGACOMPACT_CACHE_STRIPING</code>) further orders stable context by a stability score so the most durable chunks lead.</li>
|
|
98
|
+
<li>Avoid inserting new instructions mid-conversation — prepend them instead.</li>
|
|
99
|
+
</ul>
|
|
100
|
+
{snapshot && (
|
|
101
|
+
<div className="mt-2 text-sm">
|
|
102
|
+
<strong>Status:</strong>{" "}
|
|
103
|
+
{snapshot.config.auto ? "Auto-compaction Enabled" : "Auto-compaction Disabled"} |{" "}
|
|
104
|
+
fast-gate {snapshot.config.fastGatePct}% / threshold{" "}
|
|
105
|
+
{snapshot.config.thresholdTokens.toLocaleString()} tokens
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
</CardContent>
|
|
109
|
+
</Card>
|
|
103
110
|
)}
|
|
104
111
|
</div>
|
|
105
112
|
{/* ==============================================================
|
|
106
113
|
Section 1 -- Provider Prompt Cache
|
|
107
114
|
============================================================== */}
|
|
108
|
-
<h2>Provider Prompt Cache</h2>
|
|
115
|
+
<h2 className="font-heading text-lg font-semibold">Provider Prompt Cache</h2>
|
|
109
116
|
{pcLoading ? (
|
|
110
117
|
<p className="tab-stub">Loading...</p>
|
|
111
118
|
) : pcError ? (
|
|
@@ -132,7 +139,7 @@ export default function CacheTab(): React.ReactElement {
|
|
|
132
139
|
{/* ==============================================================
|
|
133
140
|
Section 2 -- Cache Stripe Distribution
|
|
134
141
|
============================================================== */}
|
|
135
|
-
<h2>Cache Stripe Distribution</h2>
|
|
142
|
+
<h2 className="font-heading text-lg font-semibold">Cache Stripe Distribution</h2>
|
|
136
143
|
{stripesLoading ? (
|
|
137
144
|
<p className="tab-stub">Loading...</p>
|
|
138
145
|
) : stripesError ? (
|
|
@@ -146,7 +153,7 @@ export default function CacheTab(): React.ReactElement {
|
|
|
146
153
|
{/* ==============================================================
|
|
147
154
|
Section 3 -- Cache Hit-Rate Trend
|
|
148
155
|
============================================================== */}
|
|
149
|
-
<h2>Cache Hit-Rate Trend</h2>
|
|
156
|
+
<h2 className="font-heading text-lg font-semibold">Cache Hit-Rate Trend</h2>
|
|
150
157
|
{perfLoading ? (
|
|
151
158
|
<p className="tab-stub">Loading...</p>
|
|
152
159
|
) : perfError ? (
|
|
@@ -160,7 +167,7 @@ export default function CacheTab(): React.ReactElement {
|
|
|
160
167
|
{/* ==============================================================
|
|
161
168
|
Section 4 -- Mega-Compact Dedup Cache
|
|
162
169
|
============================================================== */}
|
|
163
|
-
<h2>Mega-Compact Dedup Cache</h2>
|
|
170
|
+
<h2 className="font-heading text-lg font-semibold">Mega-Compact Dedup Cache</h2>
|
|
164
171
|
{snapLoading ? (
|
|
165
172
|
<p className="tab-stub">Loading...</p>
|
|
166
173
|
) : snapError ? (
|
|
@@ -170,7 +177,7 @@ export default function CacheTab(): React.ReactElement {
|
|
|
170
177
|
(() => {
|
|
171
178
|
const { cacheHits, compacts, timeSaved } = snapshot;
|
|
172
179
|
return (
|
|
173
|
-
<div className="
|
|
180
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
174
181
|
<CacheHitsCard
|
|
175
182
|
cacheHitsSession={cacheHits.session}
|
|
176
183
|
cacheHitsTotal={cacheHits.total}
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
EventCategoryFilter,
|
|
16
16
|
type EventCategory,
|
|
17
17
|
} from "../components/EventCategoryFilter";
|
|
18
|
+
import { Badge } from "../components/ui/badge";
|
|
18
19
|
|
|
19
20
|
const COMPACT_TYPES = new Set([
|
|
20
21
|
"compact_start",
|
|
@@ -31,6 +32,11 @@ const CONFIG_TYPES = new Set([
|
|
|
31
32
|
"anchors_updated",
|
|
32
33
|
"checkpoint_persisted",
|
|
33
34
|
]);
|
|
35
|
+
const RECALL_TYPES = new Set([
|
|
36
|
+
"recall_inject",
|
|
37
|
+
"hyde_executed",
|
|
38
|
+
"recall_metrics",
|
|
39
|
+
]);
|
|
34
40
|
const CREW_TYPES = new Set([
|
|
35
41
|
"crew_presence_changed",
|
|
36
42
|
"crew_turn_changed",
|
|
@@ -48,7 +54,7 @@ function matchesCategory(ev: SseEvent, cat: EventCategory): boolean {
|
|
|
48
54
|
if (cat === "all") return true;
|
|
49
55
|
const t = ev.type;
|
|
50
56
|
if (cat === "compact") return COMPACT_TYPES.has(t);
|
|
51
|
-
if (cat === "recall") return t
|
|
57
|
+
if (cat === "recall") return RECALL_TYPES.has(t);
|
|
52
58
|
if (cat === "config") return CONFIG_TYPES.has(t);
|
|
53
59
|
if (cat === "crew") return CREW_TYPES.has(t);
|
|
54
60
|
return GAME_TYPES.has(t); // cat === "game"
|
|
@@ -63,7 +69,14 @@ export default function EventsTab(): React.ReactElement {
|
|
|
63
69
|
[events, category],
|
|
64
70
|
);
|
|
65
71
|
|
|
66
|
-
const
|
|
72
|
+
const statusVariant =
|
|
73
|
+
status === "connected"
|
|
74
|
+
? ("success" as const)
|
|
75
|
+
: status === "error"
|
|
76
|
+
? ("danger" as const)
|
|
77
|
+
: status === "connecting"
|
|
78
|
+
? ("warning" as const)
|
|
79
|
+
: ("outline" as const);
|
|
67
80
|
const statusLabel =
|
|
68
81
|
status === "connected"
|
|
69
82
|
? "connected"
|
|
@@ -74,13 +87,15 @@ export default function EventsTab(): React.ReactElement {
|
|
|
74
87
|
: "disconnected";
|
|
75
88
|
|
|
76
89
|
return (
|
|
77
|
-
<div className="
|
|
78
|
-
<div className="
|
|
79
|
-
<
|
|
80
|
-
<span className="
|
|
90
|
+
<div className="flex flex-col gap-4">
|
|
91
|
+
<div className="flex items-center justify-between">
|
|
92
|
+
<Badge variant={statusVariant} role="status">
|
|
93
|
+
<span className="mr-1 inline-block h-1.5 w-1.5 rounded-full bg-current" aria-hidden="true" />
|
|
81
94
|
{statusLabel}
|
|
95
|
+
</Badge>
|
|
96
|
+
<span className="text-xs text-muted-foreground">
|
|
97
|
+
{eventCount} events received
|
|
82
98
|
</span>
|
|
83
|
-
<span className="event-count">{eventCount} events received</span>
|
|
84
99
|
</div>
|
|
85
100
|
<EventCategoryFilter active={category} onFilter={setCategory} />
|
|
86
101
|
<EventStream events={filtered} />
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import { useState, useEffect, useCallback } from "react";
|
|
8
8
|
import { fetchContextHealth, type ContextHealthResponse } from "../api/health";
|
|
9
|
+
import { Card, CardContent, CardHeader, CardTitle } from "../components/ui/card";
|
|
10
|
+
import { Badge } from "../components/ui/badge";
|
|
9
11
|
|
|
10
12
|
function healthColor(score: number): string {
|
|
11
13
|
if (score > 0.8) return "#4ade80";
|
|
@@ -105,60 +107,89 @@ export default function HealthTab(): React.ReactElement {
|
|
|
105
107
|
const composite = latest?.composite ?? 0;
|
|
106
108
|
|
|
107
109
|
return (
|
|
108
|
-
<div className="
|
|
109
|
-
<div className="
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
<div className="flex flex-col gap-4">
|
|
111
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
112
|
+
<Card>
|
|
113
|
+
<CardContent className="flex justify-center">
|
|
114
|
+
<HealthGauge score={composite} />
|
|
115
|
+
</CardContent>
|
|
116
|
+
</Card>
|
|
117
|
+
<Card>
|
|
118
|
+
<CardHeader>
|
|
119
|
+
<CardTitle>Sub-Scores</CardTitle>
|
|
120
|
+
</CardHeader>
|
|
121
|
+
<CardContent>
|
|
122
|
+
<SubScoreBar label="Drift" value={latest?.driftScore ?? 0} />
|
|
123
|
+
<SubScoreBar label="Output Quality" value={latest?.outputQuality ?? 0} />
|
|
124
|
+
<SubScoreBar label="Error Rate" value={latest?.errorScore ?? 0} />
|
|
125
|
+
<SubScoreBar label="Cache Health" value={latest?.cacheHealth ?? 0} />
|
|
126
|
+
<SubScoreBar label="Cache Poison" value={latest?.cachePoison ?? 0} />
|
|
127
|
+
</CardContent>
|
|
128
|
+
</Card>
|
|
119
129
|
</div>
|
|
120
130
|
|
|
121
|
-
<
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
131
|
+
<Card>
|
|
132
|
+
<CardHeader>
|
|
133
|
+
<CardTitle>Health Trend (last {data.trend.length} turns)</CardTitle>
|
|
134
|
+
</CardHeader>
|
|
135
|
+
<CardContent>
|
|
136
|
+
<HealthSparkline trend={data.trend} />
|
|
137
|
+
</CardContent>
|
|
138
|
+
</Card>
|
|
125
139
|
|
|
126
140
|
{data.alerts.length > 0 && (
|
|
127
|
-
<
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
<
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
<Card>
|
|
142
|
+
<CardHeader>
|
|
143
|
+
<CardTitle>Recent Alerts ({data.alerts.length})</CardTitle>
|
|
144
|
+
</CardHeader>
|
|
145
|
+
<CardContent>
|
|
146
|
+
<div className="flex flex-col gap-1">
|
|
147
|
+
{data.alerts.slice(-10).map((a) => (
|
|
148
|
+
<div
|
|
149
|
+
key={`${a.ts}-${a.turnIndex}`}
|
|
150
|
+
className="flex items-center gap-3 border-b border-border/50 py-1 text-sm"
|
|
151
|
+
>
|
|
152
|
+
<span className="text-xs text-muted-foreground">{new Date(a.ts).toLocaleTimeString()}</span>
|
|
153
|
+
<span className="text-muted-foreground">{a.modelId ?? "(unknown)"}</span>
|
|
154
|
+
<span style={{ color: healthColor(a.composite) }}>
|
|
155
|
+
{(a.composite * 100).toFixed(0)}
|
|
156
|
+
</span>
|
|
157
|
+
{a.cachePoison < 0.3 && <Badge variant="danger">CACHE POISON</Badge>}
|
|
158
|
+
</div>
|
|
159
|
+
))}
|
|
160
|
+
</div>
|
|
161
|
+
</CardContent>
|
|
162
|
+
</Card>
|
|
142
163
|
)}
|
|
143
164
|
|
|
144
165
|
{data.perModel.length > 0 && (
|
|
145
|
-
<
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
</
|
|
156
|
-
<td>{m.sampleCount}</td>
|
|
166
|
+
<Card>
|
|
167
|
+
<CardHeader>
|
|
168
|
+
<CardTitle>Health by Model</CardTitle>
|
|
169
|
+
</CardHeader>
|
|
170
|
+
<CardContent>
|
|
171
|
+
<table className="w-full border-collapse text-sm">
|
|
172
|
+
<thead>
|
|
173
|
+
<tr>
|
|
174
|
+
<th className="border-b border-border px-3 py-2 text-left font-medium text-muted-foreground">Model</th>
|
|
175
|
+
<th className="border-b border-border px-3 py-2 text-left font-medium text-muted-foreground">Avg Health</th>
|
|
176
|
+
<th className="border-b border-border px-3 py-2 text-left font-medium text-muted-foreground">Samples</th>
|
|
157
177
|
</tr>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
178
|
+
</thead>
|
|
179
|
+
<tbody>
|
|
180
|
+
{data.perModel.map((m) => (
|
|
181
|
+
<tr key={m.modelId} className="border-b border-border/50">
|
|
182
|
+
<td className="px-3 py-2">{m.modelId}</td>
|
|
183
|
+
<td className="px-3 py-2" style={{ color: healthColor(m.avgComposite) }}>
|
|
184
|
+
{(m.avgComposite * 100).toFixed(0)}%
|
|
185
|
+
</td>
|
|
186
|
+
<td className="px-3 py-2">{m.sampleCount}</td>
|
|
187
|
+
</tr>
|
|
188
|
+
))}
|
|
189
|
+
</tbody>
|
|
190
|
+
</table>
|
|
191
|
+
</CardContent>
|
|
192
|
+
</Card>
|
|
162
193
|
)}
|
|
163
194
|
</div>
|
|
164
195
|
);
|