@sentry/junior-dashboard 0.263.0 → 0.265.0

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 (197) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +2 -5
  3. package/dist/app.js +119 -35
  4. package/dist/client.js +148 -135
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.js +119 -35
  7. package/dist/tailwind.css +1 -1
  8. package/package.json +9 -4
  9. package/src/api/schema.ts +0 -1
  10. package/src/app.ts +5 -20
  11. package/src/client/App.tsx +29 -31
  12. package/src/client/api.ts +7 -0
  13. package/src/client/components/BottomSheet.tsx +26 -18
  14. package/src/client/components/CopyButton.tsx +83 -0
  15. package/src/client/components/DetailsPanel.tsx +133 -0
  16. package/src/client/components/Drawer.tsx +34 -33
  17. package/src/client/components/FilterBar.tsx +16 -31
  18. package/src/client/components/Metric.tsx +33 -23
  19. package/src/client/components/PageContentSkeleton.tsx +1 -1
  20. package/src/client/components/Pagination.tsx +1 -1
  21. package/src/client/components/ParticipantAvatarStack.tsx +40 -36
  22. package/src/client/components/ProfileMenu.tsx +27 -93
  23. package/src/client/components/README.md +101 -64
  24. package/src/client/components/SegmentedNav.tsx +1 -1
  25. package/src/client/components/ShimmerText.tsx +2 -6
  26. package/src/client/components/ThemeSwitcher.tsx +19 -15
  27. package/src/client/components/charts/ActivityChart.tsx +173 -288
  28. package/src/client/components/charts/CacheWrites.tsx +63 -50
  29. package/src/client/components/charts/InputCacheChart.tsx +137 -131
  30. package/src/client/components/charts/README.md +4 -4
  31. package/src/client/components/charts/SystemMetricCharts.tsx +68 -95
  32. package/src/client/components/charts/WorkspaceUsageChart.tsx +42 -62
  33. package/src/client/components/controls/DirectorySortSelect.tsx +3 -3
  34. package/src/client/components/controls/TimeRangeSelector.tsx +10 -15
  35. package/src/client/components/layout/DashboardHeader.tsx +44 -90
  36. package/src/client/components/layout/SecondaryNavigation.tsx +2 -1
  37. package/src/client/components/layout/VisualViewportShell.tsx +2 -2
  38. package/src/client/components/ui/accordion.tsx +77 -0
  39. package/src/client/components/ui/alert-dialog.tsx +89 -0
  40. package/src/client/components/ui/button.tsx +85 -0
  41. package/src/client/components/ui/chart.tsx +74 -0
  42. package/src/client/components/ui/checkbox.tsx +26 -0
  43. package/src/client/components/ui/collapsible.tsx +22 -0
  44. package/src/client/components/ui/field.tsx +49 -0
  45. package/src/client/components/ui/input.tsx +35 -0
  46. package/src/client/components/ui/native-select.tsx +57 -0
  47. package/src/client/components/ui/popover.tsx +67 -0
  48. package/src/client/components/ui/radio-group.tsx +32 -0
  49. package/src/client/components/ui/sheet.tsx +151 -0
  50. package/src/client/components/ui/skeleton.tsx +19 -0
  51. package/src/client/components/ui/table.tsx +80 -0
  52. package/src/client/components/ui/tabs.tsx +75 -0
  53. package/src/client/components/ui/textarea.tsx +17 -0
  54. package/src/client/components/ui/toast.tsx +215 -0
  55. package/src/client/components/ui/toggle-group.tsx +36 -0
  56. package/src/client/components/ui/toggle.tsx +37 -0
  57. package/src/client/components/ui/tooltip.tsx +168 -0
  58. package/src/client/components/ui/trace.tsx +96 -0
  59. package/src/client/components/ui/useSheet.ts +74 -0
  60. package/src/client/conversations/ChatLayout.tsx +7 -3
  61. package/src/client/conversations/ConversationBrief.tsx +17 -6
  62. package/src/client/conversations/ConversationChildAgents.tsx +87 -58
  63. package/src/client/conversations/ConversationComposer.tsx +26 -12
  64. package/src/client/conversations/ConversationDetails.tsx +198 -95
  65. package/src/client/conversations/ConversationEventDetails.tsx +141 -0
  66. package/src/client/conversations/ConversationEventLog.tsx +150 -129
  67. package/src/client/conversations/ConversationHeader.tsx +8 -3
  68. package/src/client/conversations/ConversationHeaderActions.tsx +90 -82
  69. package/src/client/conversations/ConversationHomeList.tsx +1 -1
  70. package/src/client/conversations/ConversationLinkedWork.tsx +118 -0
  71. package/src/client/conversations/ConversationMeta.tsx +111 -92
  72. package/src/client/conversations/ConversationPage.tsx +241 -110
  73. package/src/client/conversations/ConversationSidebar.tsx +48 -29
  74. package/src/client/conversations/ConversationUsageBreakdown.tsx +16 -3
  75. package/src/client/conversations/ConversationWatches.tsx +165 -0
  76. package/src/client/conversations/ConversationWorkspace.tsx +12 -22
  77. package/src/client/conversations/ConversationWorkspaceLoading.tsx +1 -1
  78. package/src/client/conversations/DetailsList.tsx +124 -0
  79. package/src/client/conversations/EventDetails.tsx +42 -8
  80. package/src/client/conversations/ForkConversationButton.tsx +27 -16
  81. package/src/client/conversations/ObjectCard.tsx +20 -8
  82. package/src/client/conversations/PendingMailboxStack.tsx +52 -33
  83. package/src/client/conversations/README.md +93 -19
  84. package/src/client/conversations/ShareConversationButton.tsx +28 -3
  85. package/src/client/conversations/SubagentTranscriptDrawer.tsx +21 -15
  86. package/src/client/conversations/ToolFrame.tsx +36 -52
  87. package/src/client/conversations/TranscriptActivityGroup.tsx +13 -4
  88. package/src/client/conversations/TranscriptAutomationTriggerView.tsx +5 -4
  89. package/src/client/conversations/TranscriptContextEventView.tsx +25 -11
  90. package/src/client/conversations/TranscriptHeadingRow.tsx +7 -7
  91. package/src/client/conversations/TranscriptLoading.tsx +1 -1
  92. package/src/client/conversations/TranscriptMarkdown.tsx +25 -20
  93. package/src/client/conversations/TranscriptMessageContextView.tsx +8 -2
  94. package/src/client/conversations/TranscriptMessageView.tsx +6 -1
  95. package/src/client/conversations/TranscriptReasoningView.tsx +54 -68
  96. package/src/client/conversations/TranscriptSubagentView.tsx +3 -3
  97. package/src/client/conversations/TranscriptTimestamp.tsx +9 -7
  98. package/src/client/conversations/TranscriptToolView.tsx +1 -1
  99. package/src/client/conversations/TranscriptTurnContextView.tsx +99 -27
  100. package/src/client/conversations/TranscriptView.tsx +63 -27
  101. package/src/client/conversations/eventLog.ts +57 -0
  102. package/src/client/conversations/eventTime.ts +60 -0
  103. package/src/client/conversations/queries.ts +29 -0
  104. package/src/client/conversations/transcriptBottomPinning.ts +34 -0
  105. package/src/client/format.ts +5 -0
  106. package/src/client/lib/utils.ts +1 -0
  107. package/src/client/pages/ConnectionsPage.tsx +2 -2
  108. package/src/client/pages/PersonalTokensPage.tsx +4 -4
  109. package/src/client/pages/SettingsPage.tsx +9 -10
  110. package/src/client/pages/admin/ServiceAccountsSection.tsx +2 -2
  111. package/src/client/pages/automations/AutomationCostChart.tsx +50 -71
  112. package/src/client/pages/automations/AutomationDeleteDialog.tsx +87 -0
  113. package/src/client/pages/automations/AutomationDetails.tsx +193 -0
  114. package/src/client/pages/automations/AutomationEditPage.tsx +7 -8
  115. package/src/client/pages/automations/AutomationEditor.tsx +41 -29
  116. package/src/client/pages/automations/AutomationEditorLoading.tsx +1 -1
  117. package/src/client/pages/automations/AutomationEventFields.tsx +202 -119
  118. package/src/client/pages/automations/AutomationExecutionChart.tsx +51 -64
  119. package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +47 -70
  120. package/src/client/pages/automations/AutomationExecutionsPage.tsx +150 -126
  121. package/src/client/pages/automations/AutomationFilters.tsx +189 -74
  122. package/src/client/pages/automations/AutomationLifecycle.tsx +109 -78
  123. package/src/client/pages/automations/AutomationOutcomeFields.tsx +26 -24
  124. package/src/client/pages/automations/AutomationRecentRuns.tsx +143 -0
  125. package/src/client/pages/automations/AutomationRow.tsx +12 -138
  126. package/src/client/pages/automations/AutomationRunDetails.tsx +307 -0
  127. package/src/client/pages/automations/AutomationRunsPage.tsx +119 -94
  128. package/src/client/pages/automations/AutomationScheduleFields.tsx +51 -51
  129. package/src/client/pages/automations/AutomationStatus.tsx +201 -0
  130. package/src/client/pages/automations/AutomationVersionsPage.tsx +65 -28
  131. package/src/client/pages/automations/AutomationsPage.tsx +80 -68
  132. package/src/client/pages/automations/AutomationsPageLayout.tsx +46 -14
  133. package/src/client/pages/automations/README.md +57 -0
  134. package/src/client/pages/automations/TriggerFilters.tsx +22 -0
  135. package/src/client/pages/automations/automationFormat.ts +37 -23
  136. package/src/client/pages/code/CodeActivityChart.tsx +59 -101
  137. package/src/client/pages/code/CodePage.tsx +52 -55
  138. package/src/client/pages/code/RepositoryPage.tsx +6 -8
  139. package/src/client/pages/locations/LocationActivityChart.tsx +53 -70
  140. package/src/client/pages/locations/LocationDirectoryActivityChart.tsx +60 -80
  141. package/src/client/pages/memory/MemoryCostChart.tsx +79 -103
  142. package/src/client/pages/memory/MemoryDetails.tsx +218 -0
  143. package/src/client/pages/memory/MemoryPage.tsx +168 -112
  144. package/src/client/pages/memory/MemoryPageLayout.tsx +33 -9
  145. package/src/client/pages/memory/MemoryTimeline.tsx +46 -69
  146. package/src/client/pages/memory/memoryRecord.ts +1 -1
  147. package/src/client/pages/people/ContributionGrid.tsx +23 -16
  148. package/src/client/pages/people/PeopleActivityChart.tsx +68 -107
  149. package/src/client/pages/people/ProfileCodeChanges.tsx +5 -5
  150. package/src/client/pages/system/BaseSandboxCard.tsx +1 -1
  151. package/src/client/pages/system/ConversationActivityChart.tsx +49 -67
  152. package/src/client/pages/system/GuardianActivity.tsx +1 -2
  153. package/src/client/pages/system/PluginBarChart.tsx +106 -87
  154. package/src/client/pages/system/PluginReportRecordSet.tsx +25 -24
  155. package/src/client/pages/system/README.md +23 -0
  156. package/src/client/pages/system/SystemNavigation.tsx +5 -1
  157. package/src/client/pages/system/WorkspaceDeleteDialog.tsx +111 -0
  158. package/src/client/pages/system/WorkspaceDetails.tsx +200 -43
  159. package/src/client/pages/system/WorkspaceEditor.tsx +59 -61
  160. package/src/client/pages/system/WorkspaceFormPage.tsx +23 -47
  161. package/src/client/pages/system/WorkspaceList.tsx +20 -30
  162. package/src/client/pages/system/WorkspacesPage.tsx +117 -119
  163. package/src/client/pages/system/sandboxSize.ts +8 -0
  164. package/src/client/pages/system/workspaceQueries.ts +53 -0
  165. package/src/client/pages/user/PluginUserPage.tsx +51 -2
  166. package/src/client/pages/user/pluginUserPageData.ts +1 -6
  167. package/src/client/styles.ts +4 -0
  168. package/src/client.tsx +7 -1
  169. package/src/mock-reporting/automation-collection.ts +4 -2
  170. package/src/mock-reporting/fixtures.ts +23 -7
  171. package/src/mock-reporting/routes.ts +12 -0
  172. package/src/mock-reporting/watches.ts +94 -0
  173. package/src/shell.ts +4 -9
  174. package/src/tailwind.css +77 -10
  175. package/src/client/components/Button.tsx +0 -118
  176. package/src/client/components/Field.tsx +0 -53
  177. package/src/client/components/SegmentedTabs.tsx +0 -119
  178. package/src/client/components/Select.tsx +0 -52
  179. package/src/client/components/Sheet.LICENSE +0 -21
  180. package/src/client/components/Sheet.tsx +0 -141
  181. package/src/client/components/Skeleton.tsx +0 -17
  182. package/src/client/components/TextInput.tsx +0 -58
  183. package/src/client/components/Tooltip.tsx +0 -216
  184. package/src/client/components/charts/useChartLayout.ts +0 -27
  185. package/src/client/conversations/ConversationDetailsFrame.tsx +0 -91
  186. package/src/client/conversations/CopyMarkdownButton.tsx +0 -65
  187. package/src/client/pages/automations/AutomationDetailsDrawer.tsx +0 -219
  188. package/src/client/pages/dev/ChartFixtures.tsx +0 -325
  189. package/src/client/pages/dev/ComponentsPage.tsx +0 -899
  190. package/src/client/pages/dev/ConversationFixture.tsx +0 -231
  191. package/src/client/pages/dev/ObjectFixtures.tsx +0 -138
  192. package/src/client/pages/dev/SegmentedFixtures.tsx +0 -59
  193. package/src/client/pages/dev/SelectFixtures.tsx +0 -62
  194. package/src/client/pages/dev/TranscriptActivityFixtures.tsx +0 -206
  195. package/src/client/pages/memory/MemoryDetailsDrawer.tsx +0 -167
  196. package/src/client/pages/system/SandboxSizeSummary.tsx +0 -47
  197. package/src/client/pages/system/SnapshotSummary.tsx +0 -78
@@ -1,8 +1,15 @@
1
1
  import type { ConversationMetricDay } from "@sentry/junior/api/schema";
2
+ import { ChevronRight } from "lucide-react";
2
3
  import { formatCompactNumber } from "../../format";
3
4
  import type { TimeRangeBucketUnit } from "../controls/TimeRangeSelector";
4
5
  import { formatActivityTooltipDate } from "./ActivityChart";
5
6
  import { cacheInputTotal, formatCacheShare } from "./cache-input";
7
+ import {
8
+ Collapsible,
9
+ CollapsibleContent,
10
+ CollapsibleTrigger,
11
+ } from "../ui/collapsible";
12
+ import { dashboardDisclosureChevronClass } from "../../styles";
6
13
 
7
14
  /** Identify the largest cache writes within the page's selected time window. */
8
15
  export function CacheWrites(props: {
@@ -20,58 +27,64 @@ export function CacheWrites(props: {
20
27
  if (!ranked.length) return null;
21
28
  const unit = props.bucketUnit === "6hour" ? "6 hours" : props.bucketUnit;
22
29
  return (
23
- <details className="border-t border-dashboard-border-subtle px-4 py-3 sm:px-5">
24
- <summary className="cursor-pointer font-sans tabular-nums text-xs text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus">
30
+ <Collapsible className="border-t border-dashboard-border-subtle px-4 py-3 sm:px-5">
31
+ <CollapsibleTrigger className="group flex cursor-pointer items-center gap-1 font-sans tabular-nums text-xs text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus">
32
+ <ChevronRight
33
+ aria-hidden="true"
34
+ className={dashboardDisclosureChevronClass}
35
+ />
25
36
  Largest cache writes
26
- </summary>
27
- <p className="mb-2 mt-3 font-sans tabular-nums text-xs leading-relaxed text-dashboard-text-muted">
28
- Top three by tokens written per {unit}, within the selected time window.
29
- Large writes alone do not mean a cache problem.
30
- </p>
31
- <div className="overflow-x-auto">
32
- <table
33
- aria-label="Largest cache writes"
34
- className="w-full min-w-80 table-fixed border-collapse font-sans text-xs tabular-nums"
35
- >
36
- <thead className="text-dashboard-text-muted">
37
- <tr>
38
- <th scope="col" className="py-2 text-left font-normal">
39
- {props.bucketUnit === "day" ? "Day" : "Starting at"}
40
- </th>
41
- <th scope="col" className="w-24 py-2 text-right font-normal">
42
- Written
43
- </th>
44
- <th scope="col" className="w-24 py-2 text-right font-normal">
45
- From cache
46
- </th>
47
- </tr>
48
- </thead>
49
- <tbody>
50
- {ranked.map((day) => (
51
- <tr
52
- key={day.date}
53
- className="border-t border-dashboard-border-subtle"
54
- >
55
- <th
56
- scope="row"
57
- className="py-2 text-left font-normal text-dashboard-text-muted"
58
- >
59
- {formatActivityTooltipDate(day.date)}
37
+ </CollapsibleTrigger>
38
+ <CollapsibleContent hiddenUntilFound>
39
+ <p className="mb-2 mt-3 font-sans tabular-nums text-xs leading-relaxed text-dashboard-text-muted">
40
+ Top three by tokens written per {unit}, within the selected time
41
+ window. Large writes alone do not mean a cache problem.
42
+ </p>
43
+ <div className="overflow-x-auto">
44
+ <table
45
+ aria-label="Largest cache writes"
46
+ className="w-full min-w-80 table-fixed border-collapse font-sans text-xs tabular-nums"
47
+ >
48
+ <thead className="text-dashboard-text-muted">
49
+ <tr>
50
+ <th scope="col" className="py-2 text-left font-normal">
51
+ {props.bucketUnit === "day" ? "Day" : "Starting at"}
52
+ </th>
53
+ <th scope="col" className="w-24 py-2 text-right font-normal">
54
+ Written
55
+ </th>
56
+ <th scope="col" className="w-24 py-2 text-right font-normal">
57
+ From cache
60
58
  </th>
61
- <td className="py-2 text-right text-dashboard-text">
62
- {formatCompactNumber(day.cacheCreationTokens)}
63
- </td>
64
- <td className="py-2 text-right text-dashboard-text">
65
- {formatCacheShare(
66
- day.cachedInputTokens,
67
- cacheInputTotal(day),
68
- )}
69
- </td>
70
59
  </tr>
71
- ))}
72
- </tbody>
73
- </table>
74
- </div>
75
- </details>
60
+ </thead>
61
+ <tbody>
62
+ {ranked.map((day) => (
63
+ <tr
64
+ key={day.date}
65
+ className="border-t border-dashboard-border-subtle"
66
+ >
67
+ <th
68
+ scope="row"
69
+ className="py-2 text-left font-normal text-dashboard-text-muted"
70
+ >
71
+ {formatActivityTooltipDate(day.date)}
72
+ </th>
73
+ <td className="py-2 text-right text-dashboard-text">
74
+ {formatCompactNumber(day.cacheCreationTokens)}
75
+ </td>
76
+ <td className="py-2 text-right text-dashboard-text">
77
+ {formatCacheShare(
78
+ day.cachedInputTokens,
79
+ cacheInputTotal(day),
80
+ )}
81
+ </td>
82
+ </tr>
83
+ ))}
84
+ </tbody>
85
+ </table>
86
+ </div>
87
+ </CollapsibleContent>
88
+ </Collapsible>
76
89
  );
77
90
  }
@@ -1,23 +1,30 @@
1
+ import { ChevronRight } from "lucide-react";
1
2
  import { useState } from "react";
2
3
  import type { ConversationMetricDay } from "@sentry/junior/api/schema";
3
4
 
4
- import { ToggleButton } from "../Button";
5
5
  import { Card } from "../layout/Card";
6
+ import {
7
+ Collapsible,
8
+ CollapsibleContent,
9
+ CollapsibleTrigger,
10
+ } from "../ui/collapsible";
11
+ import { dashboardDisclosureChevronClass } from "../../styles";
12
+ import { ToggleGroup, ToggleGroupItem } from "../ui/toggle-group";
6
13
  import { formatCompactNumber } from "../../format";
7
14
  import {
8
15
  type TimeRangeBucketUnit,
9
16
  timeRangeBucketPerLabel,
10
17
  } from "../controls/TimeRangeSelector";
18
+ import { Bar, BarChart, CartesianGrid, XAxis } from "recharts";
19
+ import { ChartContainer, ChartTooltip } from "../ui/chart";
11
20
  import {
12
- ActivityChartDateLabels,
13
- ActivityChartGrid,
14
- ActivityChartTooltip,
15
- ActivityTooltipRows,
16
- ChartSvg,
21
+ activityChartMargin,
22
+ ActivityChartTooltipContent,
23
+ ActivityChartXAxis,
24
+ ActivityChartYAxis,
17
25
  } from "./ActivityChart";
18
26
  import { ChartHeader } from "./ChartHeader";
19
27
  import { CacheWrites } from "./CacheWrites";
20
- import { useChartLayout } from "./useChartLayout";
21
28
  import {
22
29
  CACHE_INPUT_SERIES,
23
30
  cacheInputTotal,
@@ -26,6 +33,13 @@ import {
26
33
  summarizeCacheInput,
27
34
  } from "./cache-input";
28
35
 
36
+ const chartConfig = {
37
+ ...Object.fromEntries(
38
+ CACHE_INPUT_SERIES.map(({ color, key, label }) => [key, { color, label }]),
39
+ ),
40
+ missing: { color: "var(--color-slate-400)", label: "Missing data" },
41
+ };
42
+
29
43
  /** Show cache reuse and write volume without treating missing counters as zero. */
30
44
  export function InputCacheChart(props: {
31
45
  bucketUnit: TimeRangeBucketUnit;
@@ -33,40 +47,53 @@ export function InputCacheChart(props: {
33
47
  }) {
34
48
  const [mode, setMode] = useState<"share" | "tokens">("share");
35
49
  const summary = summarizeCacheInput(props.days);
36
- const { ref, layout } = useChartLayout(160);
37
- const reportedTotals = props.days.map((day) =>
38
- CACHE_INPUT_SERIES.reduce((sum, { key }) => sum + (day[key] ?? 0), 0),
39
- );
40
- const maximum = mode === "share" ? 100 : Math.max(1, ...reportedTotals);
41
- const step = layout.plotWidth / Math.max(1, props.days.length);
42
- const barWidth = Math.min(32, step * 0.7);
43
- const x = (index: number) => layout.left + step * (index + 0.5);
50
+ const data = props.days.map((day) => {
51
+ const total = cacheInputTotal(day);
52
+ const plotted = Object.fromEntries(
53
+ CACHE_INPUT_SERIES.map(({ key }) => {
54
+ const value = day[key] ?? 0;
55
+ return [
56
+ key,
57
+ mode === "share" ? (total ? (value / total) * 100 : 0) : value,
58
+ ];
59
+ }),
60
+ );
61
+ return {
62
+ ...plotted,
63
+ date: day.date,
64
+ day,
65
+ // A zero-height bar that `minPointSize` draws as a gray mark.
66
+ missing: total === undefined && hasCacheActivity(day) ? 0 : undefined,
67
+ };
68
+ });
69
+ const maximum =
70
+ mode === "share"
71
+ ? 100
72
+ : Math.max(
73
+ 1,
74
+ ...props.days.map((day) =>
75
+ CACHE_INPUT_SERIES.reduce(
76
+ (sum, { key }) => sum + (day[key] ?? 0),
77
+ 0,
78
+ ),
79
+ ),
80
+ );
44
81
 
45
82
  return (
46
83
  <Card>
47
84
  <ChartHeader
48
85
  title="Input cache"
49
86
  trailing={
50
- <div
87
+ <ToggleGroup
51
88
  aria-label="Cache chart display"
52
- className="flex gap-1"
53
- role="group"
89
+ onValueChange={([next]) => {
90
+ if (next) setMode(next);
91
+ }}
92
+ value={[mode]}
54
93
  >
55
- <ToggleButton
56
- pressed={mode === "share"}
57
- variant="segment"
58
- onClick={() => setMode("share")}
59
- >
60
- Percent
61
- </ToggleButton>
62
- <ToggleButton
63
- pressed={mode === "tokens"}
64
- variant="segment"
65
- onClick={() => setMode("tokens")}
66
- >
67
- Tokens
68
- </ToggleButton>
69
- </div>
94
+ <ToggleGroupItem value="share">Percent</ToggleGroupItem>
95
+ <ToggleGroupItem value="tokens">Tokens</ToggleGroupItem>
96
+ </ToggleGroup>
70
97
  }
71
98
  />
72
99
  <dl className="m-0 flex flex-wrap gap-x-5 gap-y-2 px-4 py-3 font-sans tabular-nums text-xs sm:px-5">
@@ -97,112 +124,91 @@ export function InputCacheChart(props: {
97
124
  reported values.
98
125
  </p>
99
126
  ) : null}
100
- <div className="px-2 pb-2" ref={ref}>
101
- <ChartSvg
102
- aria-label={`Input cache ${mode} per ${timeRangeBucketPerLabel(props.bucketUnit)}`}
103
- layout={layout}
127
+ <div className="px-2 pb-2">
128
+ <ChartContainer
129
+ className="aspect-auto h-40 w-full"
130
+ config={chartConfig}
104
131
  >
105
- <ActivityChartGrid
106
- format={
107
- mode === "share" ? (value) => `${value}%` : formatCompactNumber
108
- }
109
- layout={layout}
110
- maximum={maximum}
111
- />
112
- {props.days.map((day, index) => {
113
- const total = cacheInputTotal(day);
114
- const incomplete = total === undefined && hasCacheActivity(day);
115
- let offset = 0;
116
- const bars = CACHE_INPUT_SERIES.map(({ key, color }) => {
117
- const value = day[key] ?? 0;
118
- const plotted =
119
- mode === "share" ? (total ? (value / total) * 100 : 0) : value;
120
- const height = (plotted / maximum) * layout.plotHeight;
121
- offset += height;
122
- return (
123
- <rect
124
- key={key}
125
- fill={color}
126
- opacity={0.85}
127
- height={height}
128
- width={barWidth}
129
- x={x(index) - barWidth / 2}
130
- y={layout.top + layout.plotHeight - offset}
131
- />
132
- );
133
- });
134
- return (
135
- <ActivityChartTooltip
136
- key={day.date}
137
- date={day.date}
138
- summary={
139
- incomplete
140
- ? "Missing cache data"
141
- : total === undefined
142
- ? "No input reported"
143
- : `${formatCacheShare(day.cachedInputTokens, total)} cached · ${formatCompactNumber(total)} input tokens`
144
- }
145
- content={
146
- <ActivityTooltipRows
147
- rows={CACHE_INPUT_SERIES.map(({ key, label }) => [
132
+ <BarChart
133
+ aria-label={`Input cache ${mode} per ${timeRangeBucketPerLabel(props.bucketUnit)}`}
134
+ data={data}
135
+ margin={activityChartMargin}
136
+ role="img"
137
+ >
138
+ <CartesianGrid strokeDasharray="3 5" vertical={false} />
139
+ <ActivityChartYAxis
140
+ format={
141
+ mode === "share" ? (value) => `${value}%` : formatCompactNumber
142
+ }
143
+ maximum={maximum}
144
+ />
145
+ <ActivityChartXAxis keys={data.map((day) => day.date)} />
146
+ {/* A hidden second axis lets the missing mark overlay the stack. */}
147
+ <XAxis dataKey="date" hide xAxisId="missing" />
148
+ <ChartTooltip
149
+ content={
150
+ <ActivityChartTooltipContent
151
+ rows={({ day }: (typeof data)[number]) => {
152
+ const total = cacheInputTotal(day);
153
+ return CACHE_INPUT_SERIES.map(({ key, label }) => [
148
154
  label,
149
155
  day[key] === undefined
150
156
  ? "Not reported"
151
157
  : `${formatCompactNumber(day[key])} · ${formatCacheShare(day[key], total)}`,
152
- ])}
153
- />
154
- }
155
- >
156
- <g tabIndex={0}>
157
- <rect
158
- fill="transparent"
159
- x={x(index) - step / 2}
160
- y={layout.top}
161
- width={step}
162
- height={layout.plotHeight}
163
- />
164
- {bars}
165
- {incomplete ? (
166
- <rect
167
- fill="var(--color-slate-400)"
168
- x={x(index) - barWidth / 2}
169
- y={layout.top + layout.plotHeight - 3}
170
- width={barWidth}
171
- height={3}
172
- />
173
- ) : null}
174
- </g>
175
- </ActivityChartTooltip>
176
- );
177
- })}
178
- <ActivityChartDateLabels
179
- dates={props.days.map((day) => day.date)}
180
- layout={layout}
181
- xPosition={x}
182
- />
183
- </ChartSvg>
158
+ ]);
159
+ }}
160
+ />
161
+ }
162
+ />
163
+ {CACHE_INPUT_SERIES.map(({ key }) => (
164
+ <Bar
165
+ dataKey={key}
166
+ fill={`var(--color-${key})`}
167
+ fillOpacity={0.85}
168
+ isAnimationActive={false}
169
+ key={key}
170
+ maxBarSize={32}
171
+ stackId="input"
172
+ />
173
+ ))}
174
+ <Bar
175
+ dataKey="missing"
176
+ fill="var(--color-missing)"
177
+ isAnimationActive={false}
178
+ maxBarSize={32}
179
+ minPointSize={3}
180
+ xAxisId="missing"
181
+ />
182
+ </BarChart>
183
+ </ChartContainer>
184
184
  </div>
185
185
  <CacheWrites days={props.days} bucketUnit={props.bucketUnit} />
186
- <details className="border-t border-dashboard-border-subtle px-4 py-3 font-sans tabular-nums text-xs text-dashboard-text-muted sm:px-5">
187
- <summary className="cursor-pointer text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus">
186
+ <Collapsible className="border-t border-dashboard-border-subtle px-4 py-3 font-sans tabular-nums text-xs text-dashboard-text-muted sm:px-5">
187
+ <CollapsibleTrigger className="group flex cursor-pointer items-center gap-1 text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-dashboard-focus">
188
+ <ChevronRight
189
+ aria-hidden="true"
190
+ className={dashboardDisclosureChevronClass}
191
+ />
188
192
  How to read this
189
- </summary>
190
- <div className="mt-3 grid gap-2 leading-relaxed">
191
- <p className="m-0">
192
- From cache is input reused. Written to cache is input saved for
193
- reuse. Uncached is the remaining input.
194
- </p>
195
- <p className="m-0">
196
- Percentages use total input tokens, not call counts. Gray marks and
197
- — mean missing data; zero means a reported zero. The latest interval
198
- may be incomplete.
199
- </p>
200
- <p className="m-0">
201
- These totals can show when reuse changes, but not why. They do not
202
- show individual calls or prove that every call reported cache use.
203
- </p>
204
- </div>
205
- </details>
193
+ </CollapsibleTrigger>
194
+ <CollapsibleContent hiddenUntilFound>
195
+ <div className="mt-3 grid gap-2 leading-relaxed">
196
+ <p className="m-0">
197
+ From cache is input reused. Written to cache is input saved for
198
+ reuse. Uncached is the remaining input.
199
+ </p>
200
+ <p className="m-0">
201
+ Percentages use total input tokens, not call counts. Gray marks
202
+ and — mean missing data; zero means a reported zero. The latest
203
+ interval may be incomplete.
204
+ </p>
205
+ <p className="m-0">
206
+ These totals can show when reuse changes, but not why. They do not
207
+ show individual calls or prove that every call reported cache use.
208
+ </p>
209
+ </div>
210
+ </CollapsibleContent>
211
+ </Collapsible>
206
212
  </Card>
207
213
  );
208
214
  }
@@ -27,12 +27,12 @@ or a cache failure rate.
27
27
  The list and chart consume the same selected buckets. There is no local time
28
28
  selector or comparison window. The list is collapsed until needed.
29
29
 
30
- `useChartLayout` measures the available width. Charts keep a fixed, compact
31
- height rather than growing taller on wide screens.
30
+ The chart fills the available width. It keeps a fixed, compact height rather
31
+ than growing taller on wide screens.
32
32
 
33
33
  This report has no per-call model, release, environment, trace, or write-cost
34
34
  fields. Add a reporting contract before adding those filters or drilldowns.
35
35
  A large write alone cannot identify cache expiry, a cold start, or prefix loss.
36
36
 
37
- The chart gallery includes a reuse drop and a missing counter. The System
38
- browser scenario covers display modes and verifies that the page time control also filters the list.
37
+ The System browser scenario covers display modes and verifies that the page
38
+ time control also filters the list.