@sentry/junior-dashboard 0.248.0 → 0.250.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 (139) hide show
  1. package/README.md +3 -0
  2. package/dist/app.js +2 -2
  3. package/dist/client.js +40 -38
  4. package/dist/index.js +2 -2
  5. package/dist/tailwind.css +1 -1
  6. package/package.json +3 -3
  7. package/src/client/App.tsx +19 -5
  8. package/src/client/components/ActorAvatar.tsx +7 -4
  9. package/src/client/components/AutomationCard.tsx +2 -2
  10. package/src/client/components/Button.tsx +12 -11
  11. package/src/client/components/ConversationList.tsx +3 -3
  12. package/src/client/components/ConversationSummary.tsx +2 -1
  13. package/src/client/components/DetailList.tsx +3 -3
  14. package/src/client/components/Drawer.tsx +2 -2
  15. package/src/client/components/EmptyTelemetry.tsx +1 -1
  16. package/src/client/components/Field.tsx +1 -2
  17. package/src/client/components/FilterBar.tsx +6 -6
  18. package/src/client/components/Metric.tsx +4 -4
  19. package/src/client/components/Notice.tsx +7 -7
  20. package/src/client/components/PageContentSkeleton.tsx +2 -2
  21. package/src/client/components/Pagination.tsx +2 -2
  22. package/src/client/components/ParticipantAvatarStack.tsx +4 -4
  23. package/src/client/components/ProfileMenu.tsx +17 -7
  24. package/src/client/components/README.md +122 -58
  25. package/src/client/components/SearchInput.tsx +4 -3
  26. package/src/client/components/SegmentedNav.tsx +10 -17
  27. package/src/client/components/SegmentedTabs.tsx +3 -3
  28. package/src/client/components/Select.tsx +1 -1
  29. package/src/client/components/SelectableRow.tsx +2 -2
  30. package/src/client/components/Skeleton.tsx +1 -1
  31. package/src/client/components/StatusChip.tsx +1 -1
  32. package/src/client/components/StatusDot.tsx +1 -1
  33. package/src/client/components/TextInput.tsx +1 -1
  34. package/src/client/components/Tooltip.tsx +2 -2
  35. package/src/client/components/VersionDriftBanner.tsx +2 -2
  36. package/src/client/components/charts/ActivityChart.tsx +5 -6
  37. package/src/client/components/charts/CacheWrites.tsx +3 -3
  38. package/src/client/components/charts/ChartHeader.tsx +4 -4
  39. package/src/client/components/charts/ChartLegend.tsx +1 -1
  40. package/src/client/components/charts/InputCacheChart.tsx +5 -5
  41. package/src/client/components/charts/WorkspaceUsageChart.tsx +4 -11
  42. package/src/client/components/controls/DirectorySortSelect.tsx +2 -2
  43. package/src/client/components/directory/DirectoryMetric.tsx +2 -2
  44. package/src/client/components/directory/DirectoryRowsSkeleton.tsx +5 -5
  45. package/src/client/components/directory/DirectoryTable.tsx +3 -3
  46. package/src/client/components/layout/CardHeader.tsx +4 -4
  47. package/src/client/components/layout/DashboardChrome.tsx +9 -3
  48. package/src/client/components/layout/DashboardHeader.tsx +7 -7
  49. package/src/client/components/layout/PageHeader.tsx +2 -2
  50. package/src/client/components/layout/SecondaryNavigation.tsx +7 -14
  51. package/src/client/components/layout/SectionIntro.tsx +1 -1
  52. package/src/client/components/layout/SectionTitle.tsx +1 -1
  53. package/src/client/components/metrics/StatCard.tsx +2 -2
  54. package/src/client/conversations/ConversationArchiveNotices.tsx +1 -1
  55. package/src/client/conversations/ConversationBrief.tsx +4 -4
  56. package/src/client/conversations/ConversationChildAgents.tsx +7 -4
  57. package/src/client/conversations/ConversationComposer.tsx +8 -7
  58. package/src/client/conversations/ConversationHeader.tsx +5 -5
  59. package/src/client/conversations/ConversationHeaderActions.tsx +9 -9
  60. package/src/client/conversations/ConversationHomeList.tsx +3 -3
  61. package/src/client/conversations/ConversationListStatusIcon.tsx +1 -1
  62. package/src/client/conversations/ConversationMemories.tsx +4 -4
  63. package/src/client/conversations/ConversationMeta.tsx +10 -10
  64. package/src/client/conversations/ConversationPage.tsx +2 -1
  65. package/src/client/conversations/ConversationSidebar.tsx +6 -6
  66. package/src/client/conversations/ConversationUsageBreakdown.tsx +4 -4
  67. package/src/client/conversations/ConversationWorkspace.tsx +1 -1
  68. package/src/client/conversations/ConversationWorkspaceLoading.tsx +4 -4
  69. package/src/client/conversations/CopyMarkdownButton.tsx +1 -1
  70. package/src/client/conversations/EventUsage.tsx +2 -2
  71. package/src/client/conversations/PendingMailboxStack.tsx +5 -5
  72. package/src/client/conversations/README.md +9 -0
  73. package/src/client/conversations/SubagentTranscriptDrawer.tsx +39 -23
  74. package/src/client/conversations/ToolFrame.tsx +36 -14
  75. package/src/client/conversations/TranscriptActivityGroup.tsx +10 -3
  76. package/src/client/conversations/TranscriptAttachmentsDeliveredView.tsx +4 -6
  77. package/src/client/conversations/TranscriptContextEventView.tsx +2 -2
  78. package/src/client/conversations/TranscriptEventView.tsx +1 -1
  79. package/src/client/conversations/TranscriptMarkdown.tsx +3 -3
  80. package/src/client/conversations/TranscriptMessageContextView.tsx +7 -7
  81. package/src/client/conversations/TranscriptMessageView.tsx +2 -6
  82. package/src/client/conversations/TranscriptRailEvent.tsx +20 -8
  83. package/src/client/conversations/TranscriptReasoningView.tsx +12 -12
  84. package/src/client/conversations/TranscriptStructuredEventView.tsx +16 -11
  85. package/src/client/conversations/TranscriptSubagentView.tsx +64 -39
  86. package/src/client/conversations/TranscriptText.tsx +5 -4
  87. package/src/client/conversations/TranscriptToolView.tsx +9 -11
  88. package/src/client/conversations/TranscriptTurnContextView.tsx +3 -3
  89. package/src/client/conversations/TranscriptView.tsx +3 -3
  90. package/src/client/conversations/UsageCard.tsx +1 -1
  91. package/src/client/conversations/eventTranscript.ts +7 -0
  92. package/src/client/conversations/transcriptMarkdownLinks.ts +2 -4
  93. package/src/client/conversations/transcriptStyles.ts +1 -1
  94. package/src/client/pages/ConnectionsPage.tsx +207 -0
  95. package/src/client/pages/PersonalTokensPage.tsx +4 -4
  96. package/src/client/pages/admin/AdminPage.tsx +2 -2
  97. package/src/client/pages/automations/AutomationCostChart.tsx +2 -2
  98. package/src/client/pages/automations/AutomationDetailsDrawer.tsx +5 -10
  99. package/src/client/pages/automations/AutomationEditor.tsx +1 -1
  100. package/src/client/pages/automations/AutomationExecutionChart.tsx +2 -2
  101. package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +2 -2
  102. package/src/client/pages/automations/AutomationExecutionsPage.tsx +4 -4
  103. package/src/client/pages/automations/AutomationRow.tsx +4 -4
  104. package/src/client/pages/automations/AutomationRunsPage.tsx +3 -3
  105. package/src/client/pages/automations/AutomationScheduleFields.tsx +1 -1
  106. package/src/client/pages/automations/AutomationVersionsPage.tsx +1 -1
  107. package/src/client/pages/code/CodeActivityChart.tsx +7 -6
  108. package/src/client/pages/code/CodeChangeRow.tsx +1 -1
  109. package/src/client/pages/code/CodePage.tsx +5 -5
  110. package/src/client/pages/code/RepositoryPage.tsx +2 -2
  111. package/src/client/pages/dev/ChartFixtures.tsx +265 -21
  112. package/src/client/pages/dev/ComponentsPage.tsx +40 -146
  113. package/src/client/pages/dev/TranscriptActivityFixtures.tsx +206 -0
  114. package/src/client/pages/locations/LocationDetailPage.tsx +4 -4
  115. package/src/client/pages/locations/LocationDirectory.tsx +1 -1
  116. package/src/client/pages/locations/PrivateActivityCard.tsx +3 -3
  117. package/src/client/pages/memory/MemoryCostChart.tsx +3 -5
  118. package/src/client/pages/memory/MemoryDetailsDrawer.tsx +5 -5
  119. package/src/client/pages/memory/MemoryPage.tsx +15 -15
  120. package/src/client/pages/memory/MemoryTimeline.tsx +3 -5
  121. package/src/client/pages/people/ContributionGrid.tsx +8 -5
  122. package/src/client/pages/people/PersonProfilePage.tsx +3 -6
  123. package/src/client/pages/people/ProfilePluginReports.tsx +2 -2
  124. package/src/client/pages/system/GuardianActivity.tsx +9 -9
  125. package/src/client/pages/system/PluginBarChart.tsx +4 -6
  126. package/src/client/pages/system/PluginDetails.tsx +11 -7
  127. package/src/client/pages/system/PluginPanels.tsx +8 -8
  128. package/src/client/pages/system/PluginReportRecordSet.tsx +14 -14
  129. package/src/client/pages/system/PluginReports.tsx +7 -11
  130. package/src/client/pages/system/SkillInventory.tsx +9 -9
  131. package/src/client/pages/system/SystemActivity.tsx +1 -1
  132. package/src/client/pages/system/SystemPage.tsx +3 -6
  133. package/src/client/pages/system/WorkspaceDetails.tsx +2 -5
  134. package/src/client/pages/system/WorkspaceEditor.tsx +2 -2
  135. package/src/client/pages/system/WorkspaceList.tsx +2 -2
  136. package/src/client/pages/user/PluginUserPage.tsx +3 -3
  137. package/src/client/styles.ts +5 -4
  138. package/src/client/types.ts +2 -0
  139. package/src/tailwind.css +36 -38
@@ -1,17 +1,62 @@
1
+ import type { ReactNode } from "react";
1
2
  import type {
3
+ AutomationExecutionDay,
4
+ AutomationExecutionStatusDay,
5
+ CodeActivityDay,
2
6
  ConversationMetricDay,
7
+ DailyConversationActivity,
8
+ GuardianMetricDay,
3
9
  LocationActivityDayReport,
4
10
  PeopleActivityDayReport,
11
+ PluginOperationalReport,
5
12
  } from "@sentry/junior/api/schema";
6
13
  import { InputCacheChart } from "../../components/charts/InputCacheChart";
7
14
  import { SystemMetricCharts } from "../../components/charts/SystemMetricCharts";
15
+ import { WorkspaceUsageChart } from "../../components/charts/WorkspaceUsageChart";
16
+ import { AutomationCostChart } from "../automations/AutomationCostChart";
17
+ import { AutomationExecutionChart } from "../automations/AutomationExecutionChart";
18
+ import { AutomationExecutionStatusChart } from "../automations/AutomationExecutionStatusChart";
19
+ import { CodeActivityChart } from "../code/CodeActivityChart";
20
+ import { LocationActivityChart } from "../locations/LocationActivityChart";
8
21
  import { LocationDirectoryActivityChart } from "../locations/LocationDirectoryActivityChart";
22
+ import { MemoryCostChart } from "../memory/MemoryCostChart";
23
+ import { MemoryTimeline } from "../memory/MemoryTimeline";
24
+ import type { MemoryCostDay, MemoryDay } from "../memory/memoryDashboard";
9
25
  import { ContributionGrid } from "../people/ContributionGrid";
10
26
  import { PeopleActivityChart } from "../people/PeopleActivityChart";
11
27
  import { ConversationActivityChart } from "../system/ConversationActivityChart";
28
+ import { GuardianActivity } from "../system/GuardianActivity";
29
+ import { PluginBarChart } from "../system/PluginBarChart";
12
30
  import { Card } from "../../components/layout/Card";
13
31
  import { CardHeader } from "../../components/layout/CardHeader";
14
32
 
33
+ type PluginWidget = NonNullable<PluginOperationalReport["widgets"]>[number];
34
+
35
+ // The gallery browser scenario saves one image for each id.
36
+ const CHART_FIXTURE_IDS = [
37
+ "conversation-activity",
38
+ "conversation-activity-hourly",
39
+ "input-cache",
40
+ "system-metrics",
41
+ "people-activity",
42
+ "location-directory-activity",
43
+ "location-activity",
44
+ "code-activity",
45
+ "code-activity-dense",
46
+ "code-activity-empty",
47
+ "workspace-usage",
48
+ "automation-executions",
49
+ "automation-execution-status",
50
+ "automation-cost",
51
+ "memory-timeline",
52
+ "memory-cost",
53
+ "guardian-activity",
54
+ "plugin-bar-chart",
55
+ "contribution-grid",
56
+ ] as const;
57
+
58
+ type ChartFixtureId = (typeof CHART_FIXTURE_IDS)[number];
59
+
15
60
  const METRIC_DAYS: ConversationMetricDay[] = fixtureDates(14).map(
16
61
  (date, index) => ({
17
62
  conversations: 4 + ((index * 5) % 17),
@@ -22,6 +67,16 @@ const METRIC_DAYS: ConversationMetricDay[] = fixtureDates(14).map(
22
67
  }),
23
68
  );
24
69
 
70
+ const HOURLY_METRIC_DAYS: ConversationMetricDay[] = fixtureHours(24).map(
71
+ (date, index) => ({
72
+ conversations: index % 5 === 0 ? 0 : 1 + ((index * 7) % 9),
73
+ costUsd: 0.05 + ((index * 3) % 7) * 0.04,
74
+ date,
75
+ durationMs: 30_000 + ((index * 11) % 7) * 9_000,
76
+ tokens: 2_000 + ((index * 13) % 11) * 400,
77
+ }),
78
+ );
79
+
25
80
  const PEOPLE_DAYS: PeopleActivityDayReport[] = fixtureDates(30).map(
26
81
  (date, index) => ({
27
82
  activePeople: 4 + ((index * 7) % 13),
@@ -38,44 +93,233 @@ const LOCATION_DAYS: LocationActivityDayReport[] = fixtureDates(30).map(
38
93
  }),
39
94
  );
40
95
 
96
+ const LOCATION_DETAIL_DAYS: DailyConversationActivity[] = fixtureDates(90).map(
97
+ (date, index) => {
98
+ const conversations = index % 11 === 0 ? 0 : 2 + ((index * 7) % 15);
99
+ return {
100
+ active: Math.min(conversations, index % 4),
101
+ conversations,
102
+ date,
103
+ durationMs: conversations * 60_000,
104
+ failed: index % 13 === 0 ? 1 : 0,
105
+ };
106
+ },
107
+ );
108
+
109
+ const CODE_DAYS: CodeActivityDay[] = codeDays(30);
110
+
111
+ const DENSE_CODE_DAYS: CodeActivityDay[] = codeDays(90);
112
+
113
+ const EMPTY_CODE_DAYS: CodeActivityDay[] = fixtureDates(30).map((date) => ({
114
+ closed: 0,
115
+ created: 0,
116
+ date,
117
+ merged: 0,
118
+ }));
119
+
120
+ const WORKSPACE_USAGE_DAYS = fixtureDates(30).map((date, index) => ({
121
+ count: index % 6 === 0 ? 0 : 1 + ((index * 5) % 9),
122
+ date,
123
+ }));
124
+
125
+ const AUTOMATION_DAYS: AutomationExecutionDay[] = fixtureDates(30).map(
126
+ (date, index) => ({
127
+ costUsd: index % 7 === 0 ? 0 : 0.04 + ((index * 5) % 9) * 0.11,
128
+ date,
129
+ event: (index * 3) % 5,
130
+ scheduled: index % 7 === 0 ? 0 : 1 + ((index * 7) % 6),
131
+ }),
132
+ );
133
+
134
+ const AUTOMATION_STATUS_DAYS: AutomationExecutionStatusDay[] = fixtureDates(
135
+ 30,
136
+ ).map((date, index) => ({
137
+ blocked: index % 9 === 0 ? 1 : 0,
138
+ completed: index % 7 === 0 ? 0 : 1 + ((index * 5) % 4),
139
+ date,
140
+ failed: index % 5 === 0 ? 1 : 0,
141
+ }));
142
+
143
+ const MEMORY_DAYS: MemoryDay[] = fixtureDates(30).map((date, index) => ({
144
+ date,
145
+ personal: index % 8 === 0 ? 0 : (index * 3) % 7,
146
+ public: (index * 5) % 4,
147
+ }));
148
+
149
+ const MEMORY_EXTRACTION_DAYS: MemoryCostDay[] = fixtureDates(30).map(
150
+ (date, index) => ({
151
+ costUsd: index % 8 === 0 ? 0 : 0.02 + ((index * 7) % 9) * 0.015,
152
+ date,
153
+ events: index % 8 === 0 ? 0 : 1 + ((index * 3) % 6),
154
+ }),
155
+ );
156
+
157
+ const MEMORY_RECALL_DAYS: MemoryCostDay[] = fixtureDates(30).map(
158
+ (date, index) => ({
159
+ costUsd: 0.01 + ((index * 5) % 7) * 0.008,
160
+ date,
161
+ events: 2 + ((index * 5) % 9),
162
+ }),
163
+ );
164
+
165
+ const GUARDIAN_DAYS: GuardianMetricDay[] = fixtureDates(30).map(
166
+ (date, index) => {
167
+ const allow = 6 + ((index * 7) % 19);
168
+ const ask = (index * 3) % 5;
169
+ const deny = index % 6 === 0 ? 2 : 0;
170
+ return {
171
+ allow,
172
+ ask,
173
+ costUsd: (allow + ask + deny) * 0.0021,
174
+ date,
175
+ deny,
176
+ requests: allow + ask + deny,
177
+ };
178
+ },
179
+ );
180
+
181
+ const PLUGIN_WIDGET: PluginWidget = {
182
+ categories: fixtureDates(14).map((date, index) => ({
183
+ id: date,
184
+ label: date,
185
+ values: {
186
+ failed: index % 4 === 0 ? 2 : 0,
187
+ succeeded: 3 + ((index * 5) % 11),
188
+ },
189
+ })),
190
+ description: "Deliveries reported by the plugin.",
191
+ id: "deliveries",
192
+ series: [
193
+ { key: "succeeded", label: "Succeeded", tone: "good" },
194
+ { key: "failed", label: "Failed", tone: "danger" },
195
+ ],
196
+ title: "Deliveries",
197
+ type: "bar_chart",
198
+ };
199
+
41
200
  const CONTRIBUTION_DAYS = fixtureDates(70).map((date, index) => ({
42
201
  conversations: index % 9 === 0 ? 0 : 1 + ((index * 7) % 18),
43
202
  date,
44
203
  durationMs: index % 9 === 0 ? 0 : 45_000 + ((index * 13) % 20) * 18_000,
45
204
  }));
46
205
 
47
- /** Render chart examples with cache drops and missing counters for visual review. */
206
+ /** Render every dashboard chart with fixed data for visual review. */
48
207
  export function ChartFixtures() {
49
208
  return (
50
209
  <>
51
- <ConversationActivityChart days={METRIC_DAYS} />
52
- <InputCacheChart
53
- bucketUnit="day"
54
- days={METRIC_DAYS.map((day, index) => ({
55
- ...day,
56
- inputTokens: 2_000,
57
- cachedInputTokens: index === 9 ? 8_000 : 180_000,
58
- cacheCreationTokens:
59
- index === 5 ? undefined : index === 9 ? 190_000 : 10_000,
60
- }))}
61
- />
62
- <SystemMetricCharts days={METRIC_DAYS} />
63
- <PeopleActivityChart days={PEOPLE_DAYS} />
64
- <LocationDirectoryActivityChart days={LOCATION_DAYS} />
65
- <Card>
66
- <CardHeader
67
- description="Daily conversation intensity over ten weeks."
68
- title="Contribution activity"
210
+ <ChartFixture id="conversation-activity">
211
+ <ConversationActivityChart days={METRIC_DAYS} />
212
+ </ChartFixture>
213
+ <ChartFixture id="conversation-activity-hourly">
214
+ <ConversationActivityChart
215
+ bucketUnit="hour"
216
+ days={HOURLY_METRIC_DAYS}
69
217
  />
70
- <ContributionGrid days={CONTRIBUTION_DAYS} />
71
- </Card>
218
+ </ChartFixture>
219
+ <ChartFixture id="input-cache">
220
+ <InputCacheChart
221
+ bucketUnit="day"
222
+ days={METRIC_DAYS.map((day, index) => ({
223
+ ...day,
224
+ inputTokens: 2_000,
225
+ cachedInputTokens: index === 9 ? 8_000 : 180_000,
226
+ cacheCreationTokens:
227
+ index === 5 ? undefined : index === 9 ? 190_000 : 10_000,
228
+ }))}
229
+ />
230
+ </ChartFixture>
231
+ <ChartFixture id="system-metrics">
232
+ <SystemMetricCharts days={METRIC_DAYS} />
233
+ </ChartFixture>
234
+ <ChartFixture id="people-activity">
235
+ <PeopleActivityChart days={PEOPLE_DAYS} />
236
+ </ChartFixture>
237
+ <ChartFixture id="location-directory-activity">
238
+ <LocationDirectoryActivityChart days={LOCATION_DAYS} />
239
+ </ChartFixture>
240
+ <ChartFixture id="location-activity">
241
+ <LocationActivityChart days={LOCATION_DETAIL_DAYS} />
242
+ </ChartFixture>
243
+ <ChartFixture id="code-activity">
244
+ <CodeActivityChart days={CODE_DAYS} range={30} />
245
+ </ChartFixture>
246
+ <ChartFixture id="code-activity-dense">
247
+ <CodeActivityChart days={DENSE_CODE_DAYS} range={90} />
248
+ </ChartFixture>
249
+ <ChartFixture id="code-activity-empty">
250
+ <CodeActivityChart days={EMPTY_CODE_DAYS} range={30} />
251
+ </ChartFixture>
252
+ <ChartFixture id="workspace-usage">
253
+ <WorkspaceUsageChart
254
+ days={WORKSPACE_USAGE_DAYS}
255
+ range={30}
256
+ workspaceName="junior"
257
+ />
258
+ </ChartFixture>
259
+ <ChartFixture id="automation-executions">
260
+ <AutomationExecutionChart days={AUTOMATION_DAYS} range={30} />
261
+ </ChartFixture>
262
+ <ChartFixture id="automation-execution-status">
263
+ <AutomationExecutionStatusChart
264
+ days={AUTOMATION_STATUS_DAYS}
265
+ range={30}
266
+ />
267
+ </ChartFixture>
268
+ <ChartFixture id="automation-cost">
269
+ <AutomationCostChart days={AUTOMATION_DAYS} range={30} />
270
+ </ChartFixture>
271
+ <ChartFixture id="memory-timeline">
272
+ <MemoryTimeline days={MEMORY_DAYS} range={30} />
273
+ </ChartFixture>
274
+ <ChartFixture id="memory-cost">
275
+ <MemoryCostChart
276
+ extractionDays={MEMORY_EXTRACTION_DAYS}
277
+ range={30}
278
+ recallDays={MEMORY_RECALL_DAYS}
279
+ />
280
+ </ChartFixture>
281
+ <ChartFixture id="guardian-activity">
282
+ <GuardianActivity days={GUARDIAN_DAYS} />
283
+ </ChartFixture>
284
+ <ChartFixture id="plugin-bar-chart">
285
+ <PluginBarChart widget={PLUGIN_WIDGET} />
286
+ </ChartFixture>
287
+ <ChartFixture id="contribution-grid">
288
+ <Card>
289
+ <CardHeader
290
+ description="Daily conversation intensity over ten weeks."
291
+ title="Contribution activity"
292
+ />
293
+ <ContributionGrid days={CONTRIBUTION_DAYS} />
294
+ </Card>
295
+ </ChartFixture>
72
296
  </>
73
297
  );
74
298
  }
75
299
 
300
+ function ChartFixture(props: { children: ReactNode; id: ChartFixtureId }) {
301
+ return <div data-gallery-chart={props.id}>{props.children}</div>;
302
+ }
303
+
304
+ function codeDays(count: number): CodeActivityDay[] {
305
+ return fixtureDates(count).map((date, index) => ({
306
+ closed: index % 9 === 0 ? 1 : 0,
307
+ created: index % 4 === 0 ? 0 : 1 + ((index * 5) % 3),
308
+ date,
309
+ merged: index % 3 === 0 ? 1 + (index % 2) : 0,
310
+ }));
311
+ }
312
+
76
313
  function fixtureDates(count: number): string[] {
77
314
  const start = Date.UTC(2026, 4, 1);
78
315
  return Array.from({ length: count }, (_, index) =>
79
316
  new Date(start + index * 86_400_000).toISOString().slice(0, 10),
80
317
  );
81
318
  }
319
+
320
+ function fixtureHours(count: number): string[] {
321
+ const start = Date.UTC(2026, 4, 1);
322
+ return Array.from({ length: count }, (_, index) =>
323
+ new Date(start + index * 3_600_000).toISOString().slice(0, 13),
324
+ );
325
+ }
@@ -7,12 +7,18 @@ import {
7
7
  ConversationFixture,
8
8
  MessageAttachmentsFixture,
9
9
  } from "./ConversationFixture";
10
+ import {
11
+ SubagentCardFixture,
12
+ ToolCallGallery,
13
+ } from "./TranscriptActivityFixtures";
10
14
  import { ObjectCard } from "../../conversations/ObjectCard";
11
15
  import { AutomationCard } from "../../components/AutomationCard";
12
16
  import {
13
17
  Activity,
18
+ ArchiveRestore,
14
19
  Bot,
15
20
  ChevronRight,
21
+ CircleAlert,
16
22
  Copy,
17
23
  MessageSquare,
18
24
  Timer,
@@ -35,6 +41,7 @@ import { DashboardChromeProvider } from "../../components/layout/DashboardChrome
35
41
  import { DashboardHeader } from "../../components/layout/DashboardHeader";
36
42
  import { PageHeader } from "../../components/layout/PageHeader";
37
43
  import { MetricList, MetricValue } from "../../components/Metric";
44
+ import { Notice, NoticeAction } from "../../components/Notice";
38
45
  import { PageContentSkeleton } from "../../components/PageContentSkeleton";
39
46
  import { ActorAvatar } from "../../components/ActorAvatar";
40
47
  import { ParticipantAvatarStack } from "../../components/ParticipantAvatarStack";
@@ -45,9 +52,7 @@ import { TextArea, TextInput } from "../../components/TextInput";
45
52
  import { TranscriptMarkdown } from "../../conversations/TranscriptMarkdown";
46
53
  import { TranscriptText } from "../../conversations/TranscriptText";
47
54
  import { TranscriptMessageShell } from "../../conversations/TranscriptMessageShell";
48
- import { TranscriptToolView } from "../../conversations/TranscriptToolView";
49
55
  import { cn, dashboardContainerClass } from "../../styles";
50
- import type { TranscriptViewToolCallPart } from "../../types";
51
56
 
52
57
  export type GallerySectionId = "foundations" | "charts" | "transcripts";
53
58
 
@@ -134,123 +139,6 @@ Findings:
134
139
 
135
140
  See https://docs.sentry.io for product docs.`;
136
141
 
137
- type ToolCallFixture = {
138
- description: string;
139
- part: TranscriptViewToolCallPart;
140
- timestamp: number;
141
- };
142
-
143
- const TOOL_CALL_TIMESTAMP = Date.UTC(2026, 4, 1, 16);
144
-
145
- const TOOL_CALL_FIXTURES = [
146
- {
147
- description: "Default completed tool with normalized arguments",
148
- part: {
149
- id: "gallery-search",
150
- input: {
151
- query: "release regression",
152
- limit: 25,
153
- options: { includeArchived: false },
154
- },
155
- name: "searchIssues",
156
- output: { matches: 3 },
157
- resultTimestamp: TOOL_CALL_TIMESTAMP + 1_842,
158
- status: "completed",
159
- type: "tool_call",
160
- },
161
- timestamp: TOOL_CALL_TIMESTAMP,
162
- },
163
- {
164
- description: "Running webSearch with name-only shimmer",
165
- part: {
166
- id: "gallery-running",
167
- input: {
168
- query: "service:checkout status:error",
169
- max_results: 50,
170
- },
171
- name: "webSearch",
172
- status: "running",
173
- type: "tool_call",
174
- },
175
- timestamp: TOOL_CALL_TIMESTAMP + 3_000,
176
- },
177
- {
178
- description: "Failed tool",
179
- part: {
180
- id: "gallery-error",
181
- input: {
182
- command: "jr-rpc config get github.repo",
183
- timeout_ms: 10_000,
184
- },
185
- name: "bash",
186
- output: { error: "configuration unavailable" },
187
- resultTimestamp: TOOL_CALL_TIMESTAMP + 6_416,
188
- status: "error",
189
- type: "tool_call",
190
- },
191
- timestamp: TOOL_CALL_TIMESTAMP + 6_000,
192
- },
193
- {
194
- description: "Known loadSkill signature",
195
- part: {
196
- id: "gallery-load-skill",
197
- input: { skill_name: "junior-qa" },
198
- name: "loadSkill",
199
- output: { skill_name: "junior-qa" },
200
- resultTimestamp: TOOL_CALL_TIMESTAMP + 8_105,
201
- status: "completed",
202
- type: "tool_call",
203
- },
204
- timestamp: TOOL_CALL_TIMESTAMP + 8_000,
205
- },
206
- {
207
- description: "Known executeTool signature with nested arguments",
208
- part: {
209
- id: "gallery-execute-tool",
210
- input: {
211
- tool_name: "github_search",
212
- arguments: { query: "is:pr is:open", limit: 25 },
213
- },
214
- name: "executeTool",
215
- output: { matches: 3 },
216
- resultTimestamp: TOOL_CALL_TIMESTAMP + 10_723,
217
- status: "completed",
218
- type: "tool_call",
219
- },
220
- timestamp: TOOL_CALL_TIMESTAMP + 10_000,
221
- },
222
- {
223
- description: "Long generic arguments exercise both truncation limits",
224
- part: {
225
- id: "gallery-long",
226
- input: {
227
- project: "payments-checkout-platform",
228
- query:
229
- "Find every regression associated with the most recent production deployment and include the complete evidence trail",
230
- environment: "production",
231
- includeResolved: false,
232
- ignoredAfterFourEntries: "not shown in the collapsed preview",
233
- },
234
- name: "investigateDeploy",
235
- output: { channel_id: "C123" },
236
- resultTimestamp: TOOL_CALL_TIMESTAMP + 13_250,
237
- status: "completed",
238
- type: "tool_call",
239
- },
240
- timestamp: TOOL_CALL_TIMESTAMP + 12_000,
241
- },
242
- {
243
- description: "Completed tool without argument or result payloads",
244
- part: {
245
- id: "gallery-empty",
246
- name: "systemTime",
247
- status: "completed",
248
- type: "tool_call",
249
- },
250
- timestamp: TOOL_CALL_TIMESTAMP + 15_000,
251
- },
252
- ] as const satisfies readonly ToolCallFixture[];
253
-
254
142
  /** Config-gated component gallery with one page per category. */
255
143
  export function ComponentsPage() {
256
144
  return (
@@ -433,6 +321,14 @@ function FoundationsGalleryPage() {
433
321
  { className: "bg-dashboard-text-muted", label: "muted" },
434
322
  { className: "bg-dashboard-text-subtle", label: "subtle" },
435
323
  { className: "bg-dashboard-text-faint", label: "faint" },
324
+ ]}
325
+ />
326
+ <TokenSwatchRow
327
+ label="Accent"
328
+ swatches={[
329
+ { className: "bg-dashboard-accent", label: "accent" },
330
+ { className: "bg-dashboard-accent-text", label: "accent text" },
331
+ { className: "bg-dashboard-accent/10", label: "accent / 10" },
436
332
  { className: "bg-dashboard-focus", label: "focus" },
437
333
  ]}
438
334
  />
@@ -590,6 +486,23 @@ function FoundationsGalleryPage() {
590
486
  </StatusChip>
591
487
  </div>
592
488
  </Fixture>
489
+ <Fixture title="Notices">
490
+ <div className="grid max-w-md gap-2">
491
+ <Notice
492
+ action={<NoticeAction>Undo</NoticeAction>}
493
+ detail="Investigate checkout latency"
494
+ icon={ArchiveRestore}
495
+ title="Conversation archived"
496
+ />
497
+ <Notice
498
+ action={<NoticeAction tone="error">Dismiss</NoticeAction>}
499
+ detail="Investigate checkout latency"
500
+ icon={CircleAlert}
501
+ title="Could not archive"
502
+ tone="error"
503
+ />
504
+ </div>
505
+ </Fixture>
593
506
  <Fixture title="Actor avatars">
594
507
  <div className="flex items-center gap-4">
595
508
  <ActorAvatar
@@ -808,7 +721,9 @@ function TranscriptsGalleryPage() {
808
721
  <Fixture title="Automation in a reply">
809
722
  <div className="max-w-[52.5rem]">
810
723
  <TranscriptMessageShell actor="Junior" role="assistant">
811
- <span className="text-sm font-semibold text-cyan-100">Junior</span>
724
+ <span className="text-sm font-semibold text-dashboard-accent-text">
725
+ Junior
726
+ </span>
812
727
  <TranscriptText
813
728
  role="assistant"
814
729
  text={
@@ -878,34 +793,13 @@ function TranscriptsGalleryPage() {
878
793
  <Fixture title="Tool calls">
879
794
  <ToolCallGallery />
880
795
  </Fixture>
796
+ <Fixture title="Subagent cards">
797
+ <SubagentCardFixture />
798
+ </Fixture>
881
799
  </GalleryShell>
882
800
  );
883
801
  }
884
802
 
885
- /** Render typed transcript tool states for visual regression and interaction checks. */
886
- export function ToolCallGallery() {
887
- return (
888
- <div className="min-w-0 overflow-hidden rounded-lg border border-dashboard-border bg-dashboard-fill-faint">
889
- <div className="border-b border-dashboard-border-subtle px-2.5 py-1.5 font-mono text-xs text-dashboard-text-muted">
890
- Activity lane · click a row for arguments and result
891
- </div>
892
- <div className="grid min-w-0 gap-1 px-2 py-1.5">
893
- {TOOL_CALL_FIXTURES.map((fixture) => (
894
- <div className="grid min-w-0 gap-1" key={fixture.part.id}>
895
- <div className="font-mono text-2xs uppercase tracking-[0.08em] text-dashboard-text-muted">
896
- {fixture.description}
897
- </div>
898
- <TranscriptToolView
899
- part={fixture.part}
900
- timestamp={fixture.timestamp}
901
- />
902
- </div>
903
- ))}
904
- </div>
905
- </div>
906
- );
907
- }
908
-
909
803
  function GalleryShell(props: {
910
804
  children: ReactNode;
911
805
  description: string;
@@ -938,7 +832,7 @@ function GalleryShell(props: {
938
832
  function Fixture(props: { children: ReactNode; title: string }) {
939
833
  return (
940
834
  <Card className="grid min-w-0 gap-3 p-4 sm:p-5" padding="none">
941
- <div className="border-b border-dashboard-border-subtle pb-3 font-mono text-xs font-medium uppercase tracking-[0.14em] text-dashboard-text-muted">
835
+ <div className="border-b border-dashboard-border-subtle pb-3 font-sans text-xs font-medium text-dashboard-text-muted">
942
836
  {props.title}
943
837
  </div>
944
838
  <div className="min-w-0">{props.children}</div>
@@ -952,7 +846,7 @@ function TokenSwatchRow(props: {
952
846
  }) {
953
847
  return (
954
848
  <div className="grid gap-2">
955
- <div className="font-mono text-xs uppercase tracking-[0.12em] text-dashboard-text-muted">
849
+ <div className="font-sans font-medium text-xs text-dashboard-text-muted">
956
850
  {props.label}
957
851
  </div>
958
852
  <div className="flex flex-wrap gap-3">