@sentry/junior-dashboard 0.247.0 → 0.249.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/dist/app.js +69 -15
  2. package/dist/client.js +51 -50
  3. package/dist/index.js +69 -15
  4. package/dist/tailwind.css +1 -1
  5. package/package.json +3 -3
  6. package/src/client/App.tsx +1 -5
  7. package/src/client/components/ActorAvatar.tsx +7 -4
  8. package/src/client/components/AutomationCard.tsx +2 -2
  9. package/src/client/components/Button.tsx +12 -11
  10. package/src/client/components/ConversationList.tsx +3 -3
  11. package/src/client/components/ConversationSummary.tsx +2 -1
  12. package/src/client/components/DetailList.tsx +3 -3
  13. package/src/client/components/Drawer.tsx +2 -2
  14. package/src/client/components/EmptyTelemetry.tsx +1 -1
  15. package/src/client/components/Field.tsx +1 -2
  16. package/src/client/components/FilterBar.tsx +6 -6
  17. package/src/client/components/Metric.tsx +11 -16
  18. package/src/client/components/Notice.tsx +7 -7
  19. package/src/client/components/PageContentSkeleton.tsx +2 -2
  20. package/src/client/components/Pagination.tsx +2 -2
  21. package/src/client/components/ParticipantAvatarStack.tsx +4 -4
  22. package/src/client/components/ProfileMenu.tsx +5 -7
  23. package/src/client/components/README.md +122 -58
  24. package/src/client/components/SearchInput.tsx +4 -3
  25. package/src/client/components/SegmentedNav.tsx +10 -17
  26. package/src/client/components/SegmentedTabs.tsx +3 -3
  27. package/src/client/components/Select.tsx +1 -1
  28. package/src/client/components/SelectableRow.tsx +2 -2
  29. package/src/client/components/Skeleton.tsx +1 -1
  30. package/src/client/components/StatusChip.tsx +1 -1
  31. package/src/client/components/StatusDot.tsx +1 -1
  32. package/src/client/components/TextInput.tsx +1 -1
  33. package/src/client/components/Tooltip.tsx +2 -2
  34. package/src/client/components/VersionDriftBanner.tsx +2 -2
  35. package/src/client/components/charts/ActivityChart.tsx +5 -6
  36. package/src/client/components/charts/CacheWrites.tsx +3 -3
  37. package/src/client/components/charts/ChartHeader.tsx +4 -4
  38. package/src/client/components/charts/ChartLegend.tsx +1 -1
  39. package/src/client/components/charts/InputCacheChart.tsx +5 -5
  40. package/src/client/components/charts/WorkspaceUsageChart.tsx +4 -11
  41. package/src/client/components/controls/DirectorySortSelect.tsx +2 -2
  42. package/src/client/components/directory/DirectoryMetric.tsx +2 -2
  43. package/src/client/components/directory/DirectoryRowsSkeleton.tsx +5 -5
  44. package/src/client/components/directory/DirectoryTable.tsx +3 -3
  45. package/src/client/components/layout/CardHeader.tsx +4 -4
  46. package/src/client/components/layout/DashboardChrome.tsx +9 -3
  47. package/src/client/components/layout/DashboardHeader.tsx +7 -7
  48. package/src/client/components/layout/PageHeader.tsx +2 -2
  49. package/src/client/components/layout/SecondaryNavigation.tsx +7 -14
  50. package/src/client/components/layout/SectionIntro.tsx +1 -1
  51. package/src/client/components/layout/SectionTitle.tsx +1 -1
  52. package/src/client/components/metrics/StatCard.tsx +2 -2
  53. package/src/client/conversations/ConversationArchiveNotices.tsx +1 -1
  54. package/src/client/conversations/ConversationBrief.tsx +4 -4
  55. package/src/client/conversations/ConversationChildAgents.tsx +13 -4
  56. package/src/client/conversations/ConversationComposer.tsx +8 -7
  57. package/src/client/conversations/ConversationHeader.tsx +5 -5
  58. package/src/client/conversations/ConversationHeaderActions.tsx +9 -9
  59. package/src/client/conversations/ConversationHomeList.tsx +3 -3
  60. package/src/client/conversations/ConversationListStatusIcon.tsx +1 -1
  61. package/src/client/conversations/ConversationMemories.tsx +4 -4
  62. package/src/client/conversations/ConversationMeta.tsx +30 -11
  63. package/src/client/conversations/ConversationPage.tsx +13 -5
  64. package/src/client/conversations/ConversationSidebar.tsx +6 -6
  65. package/src/client/conversations/ConversationUsageBreakdown.tsx +278 -0
  66. package/src/client/conversations/ConversationWorkspace.tsx +1 -1
  67. package/src/client/conversations/ConversationWorkspaceLoading.tsx +4 -4
  68. package/src/client/conversations/CopyMarkdownButton.tsx +1 -1
  69. package/src/client/conversations/EventUsage.tsx +2 -2
  70. package/src/client/conversations/PendingMailboxStack.tsx +5 -5
  71. package/src/client/conversations/README.md +9 -0
  72. package/src/client/conversations/SubagentTranscriptDrawer.tsx +39 -23
  73. package/src/client/conversations/TelemetryMetrics.tsx +327 -180
  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 +172 -0
  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/format.ts +1 -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/ComponentsPage.tsx +40 -146
  112. package/src/client/pages/dev/TranscriptActivityFixtures.tsx +206 -0
  113. package/src/client/pages/locations/LocationDetailPage.tsx +4 -4
  114. package/src/client/pages/locations/LocationDirectory.tsx +1 -1
  115. package/src/client/pages/locations/PrivateActivityCard.tsx +3 -3
  116. package/src/client/pages/memory/MemoryCostChart.tsx +3 -5
  117. package/src/client/pages/memory/MemoryDetailsDrawer.tsx +5 -5
  118. package/src/client/pages/memory/MemoryPage.tsx +15 -15
  119. package/src/client/pages/memory/MemoryTimeline.tsx +3 -5
  120. package/src/client/pages/people/ContributionGrid.tsx +8 -5
  121. package/src/client/pages/people/PersonProfilePage.tsx +3 -6
  122. package/src/client/pages/people/ProfilePluginReports.tsx +2 -2
  123. package/src/client/pages/system/GuardianActivity.tsx +9 -9
  124. package/src/client/pages/system/PluginBarChart.tsx +4 -6
  125. package/src/client/pages/system/PluginDetails.tsx +11 -7
  126. package/src/client/pages/system/PluginPanels.tsx +8 -8
  127. package/src/client/pages/system/PluginReportRecordSet.tsx +14 -14
  128. package/src/client/pages/system/PluginReports.tsx +7 -11
  129. package/src/client/pages/system/SkillInventory.tsx +9 -9
  130. package/src/client/pages/system/SystemActivity.tsx +1 -1
  131. package/src/client/pages/system/SystemPage.tsx +3 -6
  132. package/src/client/pages/system/WorkspaceDetails.tsx +2 -5
  133. package/src/client/pages/system/WorkspaceEditor.tsx +2 -2
  134. package/src/client/pages/system/WorkspaceList.tsx +2 -2
  135. package/src/client/pages/user/PluginUserPage.tsx +3 -3
  136. package/src/client/styles.ts +5 -4
  137. package/src/client/types.ts +3 -0
  138. package/src/mock-reporting/fixtures.ts +73 -14
  139. package/src/tailwind.css +36 -38
@@ -40,7 +40,10 @@ export function CodeActivityChart(props: {
40
40
  const gap = Math.max(1, barWidth * 0.2);
41
41
  const groupWidth = barWidth * 3 + gap * 2;
42
42
  const totals = days.map((day) => day.created + day.merged + day.closed);
43
- const maximum = Math.max(1, ...days.flatMap((day) => [day.created, day.merged, day.closed]));
43
+ const maximum = Math.max(
44
+ 1,
45
+ ...days.flatMap((day) => [day.created, day.merged, day.closed]),
46
+ );
44
47
  const average = activityChartAverage(days.map((day) => day.created));
45
48
  const hasActivity = totals.some((total) => total > 0);
46
49
 
@@ -51,7 +54,7 @@ export function CodeActivityChart(props: {
51
54
  <h2 className="m-0 font-display text-xl font-medium text-dashboard-text">
52
55
  Changes over time
53
56
  </h2>
54
- <p className="mt-1 mb-0 font-mono text-xs leading-relaxed text-dashboard-text-muted">
57
+ <p className="mt-1 mb-0 font-sans text-xs leading-relaxed text-dashboard-text-muted">
55
58
  Code changes created, merged, and closed each day.
56
59
  </p>
57
60
  </div>
@@ -106,9 +109,7 @@ export function CodeActivityChart(props: {
106
109
  date={day.date}
107
110
  summary={`${day.created} created, ${day.merged} merged, ${day.closed} closed`}
108
111
  >
109
- <g
110
- tabIndex={0}
111
- >
112
+ <g tabIndex={0}>
112
113
  {series.map((entry, seriesIndex) => {
113
114
  const height = (entry.value / maximum) * layout.plotHeight;
114
115
  const x = groupX + seriesIndex * (barWidth + gap);
@@ -151,7 +152,7 @@ export function CodeActivityChart(props: {
151
152
  />
152
153
  </ChartSvg>
153
154
  {!hasActivity ? (
154
- <div className="pointer-events-none absolute inset-0 grid place-items-center pt-12 font-mono text-xs text-dashboard-text-muted">
155
+ <div className="pointer-events-none absolute inset-0 grid place-items-center pt-12 font-sans text-xs text-dashboard-text-muted">
155
156
  No code changes in this period.
156
157
  </div>
157
158
  ) : null}
@@ -18,7 +18,7 @@ export function CodeChangeRow(props: { change: CodeChangeSummaryReport }) {
18
18
  <div className="truncate font-display text-sm text-dashboard-text">
19
19
  {change.url ? (
20
20
  <a
21
- className="text-inherit no-underline hover:text-cyan-100"
21
+ className="text-inherit no-underline hover:text-dashboard-accent-text"
22
22
  href={change.url}
23
23
  rel="noreferrer"
24
24
  target="_blank"
@@ -96,7 +96,7 @@ function CodeOverview(props: {
96
96
  <col className="w-28" />
97
97
  <col className="w-28" />
98
98
  </colgroup>
99
- <thead className="font-mono text-xs uppercase tracking-[0.1em] text-dashboard-text-muted">
99
+ <thead className="font-sans font-medium text-xs text-dashboard-text-muted">
100
100
  <tr className="border-b border-dashboard-border-subtle">
101
101
  <th className="px-4 py-2.5 font-medium">Repository</th>
102
102
  <th className="px-4 py-2.5 text-right font-medium whitespace-nowrap">
@@ -119,7 +119,7 @@ function CodeOverview(props: {
119
119
  <td className="min-w-0 px-4 py-3">
120
120
  <div className="truncate font-display text-sm text-dashboard-text">
121
121
  <Link
122
- className="text-inherit no-underline hover:text-cyan-100"
122
+ className="text-inherit no-underline hover:text-dashboard-accent-text"
123
123
  to={codeRepositoryPath(repository.id)}
124
124
  >
125
125
  {repository.name}
@@ -129,13 +129,13 @@ function CodeOverview(props: {
129
129
  {repository.provider}
130
130
  </div>
131
131
  </td>
132
- <td className="px-4 py-3 text-right font-mono text-sm whitespace-nowrap text-dashboard-text">
132
+ <td className="px-4 py-3 text-right font-sans text-sm tabular-nums whitespace-nowrap text-dashboard-text">
133
133
  {repository.created}
134
134
  </td>
135
- <td className="px-4 py-3 text-right font-mono text-sm whitespace-nowrap text-dashboard-text">
135
+ <td className="px-4 py-3 text-right font-sans text-sm tabular-nums whitespace-nowrap text-dashboard-text">
136
136
  {formatMergeRate(repository.mergeRate)}
137
137
  </td>
138
- <td className="px-4 py-3 text-right font-mono text-sm whitespace-nowrap text-dashboard-text">
138
+ <td className="px-4 py-3 text-right font-sans text-sm tabular-nums whitespace-nowrap text-dashboard-text">
139
139
  {formatCodeCost(repository.medianCostUsd)}
140
140
  </td>
141
141
  </tr>
@@ -35,13 +35,13 @@ import {
35
35
  RepositoryChangesTab,
36
36
  RepositoryConversationsTab,
37
37
  } from "./RepositoryTabs";
38
+ import { cn, dashboardInlineLinkClass } from "../../styles";
38
39
 
39
40
  const RECENT_ROWS = 5;
40
41
  const DESCRIPTION = "Conversations and code changes from Junior.";
41
42
 
42
43
  /** Inline link style used by `ConversationSummary` location links. */
43
- const inlineLinkClass =
44
- "font-semibold text-dashboard-text underline decoration-white/20 underline-offset-2 transition-colors hover:decoration-white/60";
44
+ const inlineLinkClass = cn("font-semibold", dashboardInlineLinkClass);
45
45
 
46
46
  /** Render one repository tab under the shared header and tab bar. */
47
47
  export function RepositoryPage(props: { tab: CodeRepositoryTab }) {
@@ -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">
@@ -0,0 +1,206 @@
1
+ import { TranscriptSubagentView } from "../../conversations/TranscriptSubagentView";
2
+ import { TranscriptToolView } from "../../conversations/TranscriptToolView";
3
+ import type {
4
+ TranscriptViewSubagentPart,
5
+ TranscriptViewToolCallPart,
6
+ } from "../../types";
7
+
8
+ type ToolCallFixture = {
9
+ description: string;
10
+ part: TranscriptViewToolCallPart;
11
+ timestamp: number;
12
+ };
13
+
14
+ const TOOL_CALL_TIMESTAMP = Date.UTC(2026, 4, 1, 16);
15
+
16
+ const TOOL_CALL_FIXTURES = [
17
+ {
18
+ description: "Default completed tool with normalized arguments",
19
+ part: {
20
+ id: "gallery-search",
21
+ input: {
22
+ query: "release regression",
23
+ limit: 25,
24
+ options: { includeArchived: false },
25
+ },
26
+ name: "searchIssues",
27
+ output: { matches: 3 },
28
+ resultTimestamp: TOOL_CALL_TIMESTAMP + 1_842,
29
+ status: "completed",
30
+ type: "tool_call",
31
+ },
32
+ timestamp: TOOL_CALL_TIMESTAMP,
33
+ },
34
+ {
35
+ description: "Running webSearch with name-only shimmer",
36
+ part: {
37
+ id: "gallery-running",
38
+ input: {
39
+ query: "service:checkout status:error",
40
+ max_results: 50,
41
+ },
42
+ name: "webSearch",
43
+ status: "running",
44
+ type: "tool_call",
45
+ },
46
+ timestamp: TOOL_CALL_TIMESTAMP + 3_000,
47
+ },
48
+ {
49
+ description: "Failed tool",
50
+ part: {
51
+ id: "gallery-error",
52
+ input: {
53
+ command: "jr-rpc config get github.repo",
54
+ timeout_ms: 10_000,
55
+ },
56
+ name: "bash",
57
+ output: { error: "configuration unavailable" },
58
+ resultTimestamp: TOOL_CALL_TIMESTAMP + 6_416,
59
+ status: "error",
60
+ type: "tool_call",
61
+ },
62
+ timestamp: TOOL_CALL_TIMESTAMP + 6_000,
63
+ },
64
+ {
65
+ description: "Known loadSkill signature",
66
+ part: {
67
+ id: "gallery-load-skill",
68
+ input: { skill_name: "junior-qa" },
69
+ name: "loadSkill",
70
+ output: { skill_name: "junior-qa" },
71
+ resultTimestamp: TOOL_CALL_TIMESTAMP + 8_105,
72
+ status: "completed",
73
+ type: "tool_call",
74
+ },
75
+ timestamp: TOOL_CALL_TIMESTAMP + 8_000,
76
+ },
77
+ {
78
+ description: "Known executeTool signature with nested arguments",
79
+ part: {
80
+ id: "gallery-execute-tool",
81
+ input: {
82
+ tool_name: "github_search",
83
+ arguments: { query: "is:pr is:open", limit: 25 },
84
+ },
85
+ name: "executeTool",
86
+ output: { matches: 3 },
87
+ resultTimestamp: TOOL_CALL_TIMESTAMP + 10_723,
88
+ status: "completed",
89
+ type: "tool_call",
90
+ },
91
+ timestamp: TOOL_CALL_TIMESTAMP + 10_000,
92
+ },
93
+ {
94
+ description: "Long generic arguments exercise both truncation limits",
95
+ part: {
96
+ id: "gallery-long",
97
+ input: {
98
+ project: "payments-checkout-platform",
99
+ query:
100
+ "Find every regression associated with the most recent production deployment and include the complete evidence trail",
101
+ environment: "production",
102
+ includeResolved: false,
103
+ ignoredAfterFourEntries: "not shown in the collapsed preview",
104
+ },
105
+ name: "investigateDeploy",
106
+ output: { channel_id: "C123" },
107
+ resultTimestamp: TOOL_CALL_TIMESTAMP + 13_250,
108
+ status: "completed",
109
+ type: "tool_call",
110
+ },
111
+ timestamp: TOOL_CALL_TIMESTAMP + 12_000,
112
+ },
113
+ {
114
+ description: "Completed tool without argument or result payloads",
115
+ part: {
116
+ id: "gallery-empty",
117
+ name: "systemTime",
118
+ status: "completed",
119
+ type: "tool_call",
120
+ },
121
+ timestamp: TOOL_CALL_TIMESTAMP + 15_000,
122
+ },
123
+ ] as const satisfies readonly ToolCallFixture[];
124
+
125
+ const SUBAGENT_STARTED = Date.UTC(2026, 4, 1, 16);
126
+
127
+ const SUBAGENT_FIXTURES: readonly TranscriptViewSubagentPart[] = [
128
+ {
129
+ agentName: "planner",
130
+ childConversationId: "gallery-planner",
131
+ id: "gallery-planner",
132
+ status: "running",
133
+ subagentKind: "agent",
134
+ type: "subagent",
135
+ title: "Review the dashboard plan",
136
+ },
137
+ {
138
+ agentName: "reviewer",
139
+ childConversationId: "gallery-reviewer",
140
+ finishedTimestamp: SUBAGENT_STARTED + 16_000,
141
+ id: "gallery-reviewer",
142
+ status: "completed",
143
+ subagentKind: "agent",
144
+ type: "subagent",
145
+ title: "Check the pull request against the repository rules",
146
+ },
147
+ {
148
+ agentName: "github",
149
+ childConversationId: "gallery-github",
150
+ finishedTimestamp: SUBAGENT_STARTED + 4_000,
151
+ id: "gallery-github",
152
+ status: "blocked",
153
+ subagentKind: "agent",
154
+ type: "subagent",
155
+ },
156
+ {
157
+ agentName: "deploy",
158
+ childConversationId: "gallery-deploy",
159
+ finishedTimestamp: SUBAGENT_STARTED + 92_000,
160
+ id: "gallery-deploy",
161
+ status: "error",
162
+ subagentKind: "agent",
163
+ type: "subagent",
164
+ task: "Roll back payments-v42 in us-west1 and confirm the canary error rate.",
165
+ },
166
+ ];
167
+
168
+ /** Render typed transcript tool states for visual regression and interaction checks. */
169
+ export function ToolCallGallery() {
170
+ return (
171
+ <div className="min-w-0 overflow-hidden rounded-lg border border-dashboard-border bg-dashboard-fill-faint">
172
+ <div className="border-b border-dashboard-border-subtle px-2.5 py-1.5 font-sans text-xs text-dashboard-text-muted">
173
+ Activity lane · click a row for arguments and result
174
+ </div>
175
+ <div className="grid min-w-0 gap-1 px-2 py-1.5">
176
+ {TOOL_CALL_FIXTURES.map((fixture) => (
177
+ <div className="grid min-w-0 gap-1" key={fixture.part.id}>
178
+ <div className="font-sans font-medium text-2xs text-dashboard-text-muted">
179
+ {fixture.description}
180
+ </div>
181
+ <TranscriptToolView
182
+ part={fixture.part}
183
+ timestamp={fixture.timestamp}
184
+ />
185
+ </div>
186
+ ))}
187
+ </div>
188
+ </div>
189
+ );
190
+ }
191
+
192
+ /** Show subagent cards in each lifecycle status, with and without a title. */
193
+ export function SubagentCardFixture() {
194
+ return (
195
+ <div className="grid min-w-0 gap-2">
196
+ {SUBAGENT_FIXTURES.map((part) => (
197
+ <TranscriptSubagentView
198
+ key={part.id}
199
+ onOpenTranscript={() => undefined}
200
+ part={part}
201
+ timestamp={SUBAGENT_STARTED}
202
+ />
203
+ ))}
204
+ </div>
205
+ );
206
+ }
@@ -92,12 +92,12 @@ function LocationDetail(props: { detail: LocationDetailReport }) {
92
92
  <LocationActivityChart days={detail.activityDays} />
93
93
 
94
94
  <Card>
95
- <div className="flex items-center gap-3 border-b border-white/[0.06] px-4 py-4">
96
- <span className="grid size-9 place-items-center rounded border border-cyan-400/15 bg-cyan-400/[0.06] text-cyan-300">
95
+ <div className="flex items-center gap-3 border-b border-dashboard-border-subtle px-4 py-4">
96
+ <span className="grid size-9 place-items-center rounded-md border border-dashboard-accent/15 bg-dashboard-accent/[0.06] text-dashboard-accent">
97
97
  <MapPin aria-hidden="true" size={16} />
98
98
  </span>
99
99
  <div>
100
- <h3 className="m-0 font-mono text-xs font-medium uppercase tracking-[0.14em] text-dashboard-text-muted">
100
+ <h3 className="m-0 font-sans text-xs font-medium text-dashboard-text-muted">
101
101
  People seen here
102
102
  </h3>
103
103
  <p className="mt-1 mb-0 font-mono text-xs text-dashboard-text-muted">
@@ -127,7 +127,7 @@ function LocationDetail(props: { detail: LocationDetailReport }) {
127
127
  </>
128
128
  );
129
129
  const className =
130
- "min-w-0 border-b border-r border-white/[0.055] px-4 py-3.5 transition-colors hover:bg-white/[0.03]";
130
+ "min-w-0 border-b border-r border-dashboard-border-subtle px-4 py-3.5 transition-colors hover:bg-dashboard-fill-soft";
131
131
  return item.actor.email ? (
132
132
  <Link
133
133
  className={`${className} text-inherit no-underline`}
@@ -76,7 +76,7 @@ export function LocationDirectory(props: {
76
76
  <>Last active {formatRelativeTime(location.lastSeenAt)}</>
77
77
  }
78
78
  icon={<Hash aria-hidden="true" size={16} strokeWidth={1.8} />}
79
- iconClassName="bg-cyan-400/[0.06] text-cyan-300 group-hover:border-cyan-400/25"
79
+ iconClassName="bg-dashboard-accent/[0.06] text-dashboard-accent group-hover:border-dashboard-accent/25"
80
80
  title={location.label}
81
81
  />
82
82
  <DirectoryMetric
@@ -9,14 +9,14 @@ export function PrivateActivityCard(props: { item: ConversationStatsItem }) {
9
9
  return (
10
10
  <Card className="opacity-80" padding="sm">
11
11
  <div className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 max-sm:grid-cols-[auto_minmax(0,1fr)]">
12
- <span className="grid size-9 shrink-0 place-items-center rounded border border-white/[0.08] bg-white/[0.025] text-dashboard-text-muted">
12
+ <span className="grid size-9 shrink-0 place-items-center rounded-md border border-dashboard-border bg-dashboard-fill-soft text-dashboard-text-muted">
13
13
  <LockKeyhole aria-hidden="true" size={15} />
14
14
  </span>
15
15
  <div className="min-w-0">
16
16
  <div className="font-display text-base font-medium text-dashboard-text">
17
17
  Private activity
18
18
  </div>
19
- <div className="mt-1 font-mono text-xs leading-relaxed text-dashboard-text-muted">
19
+ <div className="mt-1 font-sans text-xs leading-relaxed text-dashboard-text-muted">
20
20
  DMs, private channels, and unknown visibility stay combined and
21
21
  unlinked.
22
22
  </div>
@@ -25,7 +25,7 @@ export function PrivateActivityCard(props: { item: ConversationStatsItem }) {
25
25
  <div className="font-display text-2xl font-light text-dashboard-text">
26
26
  {formatCompactNumber(props.item.conversations)}
27
27
  </div>
28
- <div className="font-mono text-xs uppercase tracking-[0.1em] text-dashboard-text-muted">
28
+ <div className="font-sans font-medium text-xs text-dashboard-text-muted">
29
29
  conversations
30
30
  </div>
31
31
  </div>
@@ -66,7 +66,7 @@ export function MemoryCostChart(props: {
66
66
  <h2 className="m-0 font-display text-xl font-medium text-dashboard-text">
67
67
  {formatCostSummary({ total })}
68
68
  </h2>
69
- <p className="mt-1 mb-0 font-mono text-xs leading-relaxed text-dashboard-text-muted">
69
+ <p className="mt-1 mb-0 font-sans text-xs leading-relaxed text-dashboard-text-muted">
70
70
  System-wide estimate across {formatRunCount(runs)} spanning extraction
71
71
  and recall.
72
72
  </p>
@@ -128,9 +128,7 @@ export function MemoryCostChart(props: {
128
128
  date={day.date}
129
129
  summary={`extraction ${formatCostSummary({ total: day.extraction.costUsd })}, ${formatRunCount(day.extraction.events)}; recall ${formatCostSummary({ total: day.recall.costUsd })}, ${formatRunCount(day.recall.events)}`}
130
130
  >
131
- <g
132
- tabIndex={0}
133
- >
131
+ <g tabIndex={0}>
134
132
  <rect
135
133
  fill="#67e8f9"
136
134
  height={extractionHeight}
@@ -180,7 +178,7 @@ export function MemoryCostChart(props: {
180
178
  />
181
179
  </ChartSvg>
182
180
  {runs === 0 ? (
183
- <div className="pointer-events-none absolute inset-0 grid place-items-center pt-12 font-mono text-xs text-dashboard-text-muted">
181
+ <div className="pointer-events-none absolute inset-0 grid place-items-center pt-12 font-sans text-xs text-dashboard-text-muted">
184
182
  No memory extraction or recall ran in this period.
185
183
  </div>
186
184
  ) : null}