@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
@@ -17,7 +17,7 @@ export function SkillInventory(props: { skills: SkillReport[] }) {
17
17
 
18
18
  return (
19
19
  <Card>
20
- <div className="flex items-start justify-between gap-4 border-b border-white/[0.06] px-5 py-4 max-sm:flex-col">
20
+ <div className="flex items-start justify-between gap-4 border-b border-dashboard-border-subtle px-5 py-4 max-sm:flex-col">
21
21
  <SectionIntro
22
22
  description={
23
23
  <>
@@ -28,7 +28,7 @@ export function SkillInventory(props: { skills: SkillReport[] }) {
28
28
  }
29
29
  title="Skills"
30
30
  />
31
- <div className="grid min-w-[12rem] grid-cols-2 overflow-hidden rounded-lg border border-white/[0.07] bg-black/15 max-sm:w-full max-sm:min-w-0">
31
+ <div className="grid min-w-[12rem] grid-cols-2 overflow-hidden rounded-lg border border-dashboard-border bg-dashboard-overlay-soft max-sm:w-full max-sm:min-w-0">
32
32
  <InventoryMetric label="discovered" value={props.skills.length} />
33
33
  <InventoryMetric label="from plugins" value={pluginSkillCount} />
34
34
  </div>
@@ -42,7 +42,7 @@ export function SkillInventory(props: { skills: SkillReport[] }) {
42
42
  />
43
43
  ))
44
44
  ) : (
45
- <div className="rounded-lg border border-dashed border-white/[0.08] px-4 py-8 text-center font-mono text-xs text-dashboard-text-muted">
45
+ <div className="rounded-lg border border-dashed border-dashboard-border px-4 py-8 text-center font-sans text-xs text-dashboard-text-muted">
46
46
  No skills have been discovered yet.
47
47
  </div>
48
48
  )}
@@ -54,10 +54,10 @@ export function SkillInventory(props: { skills: SkillReport[] }) {
54
54
  function SkillGroupCard(props: { group: SkillGroup }) {
55
55
  const label = props.group.pluginProvider ?? "Standalone";
56
56
  return (
57
- <article className="rounded-lg border border-white/[0.065] bg-white/[0.025] p-4">
57
+ <article className="rounded-lg border border-dashboard-border-subtle bg-dashboard-fill-soft p-4">
58
58
  <div className="mb-3 flex items-center justify-between gap-3">
59
59
  <div className="flex min-w-0 items-center gap-2.5">
60
- <div className="grid size-8 shrink-0 place-items-center rounded border border-cyan-300/15 bg-cyan-300/[0.075] text-cyan-200">
60
+ <div className="grid size-8 shrink-0 place-items-center rounded-md border border-dashboard-accent/15 bg-dashboard-accent/[0.075] text-dashboard-accent-text">
61
61
  {props.group.pluginProvider ? (
62
62
  <Boxes aria-hidden="true" size={15} strokeWidth={1.8} />
63
63
  ) : (
@@ -68,7 +68,7 @@ function SkillGroupCard(props: { group: SkillGroup }) {
68
68
  <h3 className="m-0 truncate font-display text-base font-medium text-dashboard-text">
69
69
  {label}
70
70
  </h3>
71
- <div className="mt-0.5 font-mono text-xs uppercase tracking-[0.1em] text-dashboard-text-muted">
71
+ <div className="mt-0.5 font-sans font-medium text-xs text-dashboard-text-muted">
72
72
  {props.group.pluginProvider ? "plugin provider" : "core or local"}
73
73
  </div>
74
74
  </div>
@@ -81,7 +81,7 @@ function SkillGroupCard(props: { group: SkillGroup }) {
81
81
  <div className="flex flex-wrap gap-2">
82
82
  {props.group.skills.map((skill) => (
83
83
  <span
84
- className="rounded border border-white/[0.07] bg-black/20 px-2.5 py-1.5 font-mono text-xs text-dashboard-text-muted"
84
+ className="rounded-md border border-dashboard-border bg-dashboard-overlay-soft px-2.5 py-1.5 font-mono text-xs text-dashboard-text-muted"
85
85
  key={skill.name}
86
86
  >
87
87
  {skill.name}
@@ -94,11 +94,11 @@ function SkillGroupCard(props: { group: SkillGroup }) {
94
94
 
95
95
  function InventoryMetric(props: { label: string; value: number }) {
96
96
  return (
97
- <div className="border-r border-white/[0.06] px-3 py-2.5 text-center last:border-r-0">
97
+ <div className="border-r border-dashboard-border-subtle px-3 py-2.5 text-center last:border-r-0">
98
98
  <div className="font-display text-xl font-light leading-none text-dashboard-text">
99
99
  {formatCompactNumber(props.value)}
100
100
  </div>
101
- <div className="mt-1.5 font-mono text-xs uppercase tracking-[0.1em] text-dashboard-text-muted">
101
+ <div className="mt-1.5 font-sans font-medium text-xs text-dashboard-text-muted">
102
102
  {props.label}
103
103
  </div>
104
104
  </div>
@@ -79,7 +79,7 @@ export function SystemActivity(props: {
79
79
  return (
80
80
  <section aria-label="Runtime telemetry" className="grid gap-4">
81
81
  {props.error ? (
82
- <p className="m-0 font-mono text-xs text-rose-200/65">
82
+ <p className="m-0 font-sans text-xs text-rose-200/65">
83
83
  Metrics refresh failed. Showing cached data.
84
84
  </p>
85
85
  ) : null}
@@ -13,10 +13,7 @@ import { PluginPanels } from "./PluginPanels";
13
13
  import { PluginReports } from "./PluginReports";
14
14
  import { SkillInventory } from "./SkillInventory";
15
15
  import { SystemActivity } from "./SystemActivity";
16
- import {
17
- SystemPageLayout,
18
- SystemRouteLoading,
19
- } from "./SystemPageLayout";
16
+ import { SystemPageLayout, SystemRouteLoading } from "./SystemPageLayout";
20
17
  import {
21
18
  buildSystemPlugins,
22
19
  normalizeSystemPath,
@@ -172,14 +169,14 @@ function PluginReportError(props: { showingReports: boolean }) {
172
169
  return (
173
170
  <Card className="border-amber-300/10 bg-amber-300/[0.025]" padding="sm">
174
171
  <div className="flex items-center gap-3">
175
- <div className="grid size-9 shrink-0 place-items-center rounded border border-amber-300/15 bg-amber-300/[0.055] text-amber-200/70">
172
+ <div className="grid size-9 shrink-0 place-items-center rounded-md border border-amber-300/15 bg-amber-300/[0.055] text-amber-200/70">
176
173
  <TriangleAlert aria-hidden="true" size={15} />
177
174
  </div>
178
175
  <div>
179
176
  <div className="font-display text-sm font-medium text-dashboard-text-muted">
180
177
  Plugin stats failed to load.
181
178
  </div>
182
- <div className="mt-1 font-mono text-xs leading-relaxed text-dashboard-text-muted">
179
+ <div className="mt-1 font-sans text-xs leading-relaxed text-dashboard-text-muted">
183
180
  {props.showingReports
184
181
  ? `Showing the last operational reports ${getDashboardAgentName()} received.`
185
182
  : "Plugin details and capabilities are still available."}
@@ -1,7 +1,4 @@
1
- import type {
2
- StatsReport,
3
- WorkspaceReport,
4
- } from "@sentry/junior/api/schema";
1
+ import type { StatsReport, WorkspaceReport } from "@sentry/junior/api/schema";
5
2
 
6
3
  import { useStatsData } from "../../api";
7
4
  import { EmptyTelemetry } from "../../components/EmptyTelemetry";
@@ -58,7 +55,7 @@ export function WorkspaceDetailsContent(props: {
58
55
  ) : (
59
56
  <div className="grid min-w-0 gap-3">
60
57
  {props.error ? (
61
- <p className="m-0 font-mono text-xs text-rose-200/65">
58
+ <p className="m-0 font-sans text-xs text-rose-200/65">
62
59
  Workspace usage refresh failed. Showing cached data.
63
60
  </p>
64
61
  ) : null}
@@ -114,7 +114,7 @@ export function WorkspaceEditor(props: WorkspaceEditorProps) {
114
114
  <div className="grid gap-3">
115
115
  {props.draft.repos.map((repo, index) => (
116
116
  <div
117
- className="grid gap-3 rounded-lg border border-white/10 bg-black/20 p-3 sm:p-4"
117
+ className="grid gap-3 rounded-lg border border-dashboard-border-strong bg-dashboard-overlay-soft p-3 sm:p-4"
118
118
  key={repo.key}
119
119
  >
120
120
  <div className="grid gap-3 sm:grid-cols-[minmax(0,8.5rem)_minmax(0,1fr)_auto] sm:items-end">
@@ -202,7 +202,7 @@ export function WorkspaceEditor(props: WorkspaceEditorProps) {
202
202
 
203
203
  {props.error ? <InlineError>{props.error}</InlineError> : null}
204
204
 
205
- <div className="flex flex-wrap items-center gap-3 border-t border-white/[0.06] pt-5">
205
+ <div className="flex flex-wrap items-center gap-3 border-t border-dashboard-border-subtle pt-5">
206
206
  <Button disabled={!props.canSave} type="submit">
207
207
  {props.busy
208
208
  ? "Saving…"
@@ -50,7 +50,7 @@ function WorkspaceListItem(props: {
50
50
  const openWorkspace = () =>
51
51
  navigate(`/system/workspaces/${encodeURIComponent(workspace.id)}`);
52
52
  return (
53
- <li className="border-b border-white/[0.055] last:border-b-0">
53
+ <li className="border-b border-dashboard-border-subtle last:border-b-0">
54
54
  <SelectableRow
55
55
  className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-4 py-3.5"
56
56
  onSelect={openWorkspace}
@@ -62,7 +62,7 @@ function WorkspaceListItem(props: {
62
62
  onClick={openWorkspace}
63
63
  type="button"
64
64
  >
65
- <span className="grid size-9 shrink-0 place-items-center rounded border border-white/10 bg-white/[0.03] text-[#beaaff] transition-colors group-hover:border-cyan-300/20 group-hover:bg-cyan-300/[0.06] group-hover:text-cyan-200">
65
+ <span className="grid size-9 shrink-0 place-items-center rounded-md border border-dashboard-border-strong bg-dashboard-fill-soft text-dashboard-accent transition-colors group-hover:border-dashboard-accent/20 group-hover:bg-dashboard-accent/[0.06] group-hover:text-dashboard-accent-text">
66
66
  <FolderGit2 aria-hidden="true" size={16} />
67
67
  </span>
68
68
  <span className="min-w-0 flex-1">
@@ -87,7 +87,7 @@ export function PluginUserPage(props: { page: PluginUserPageLink }) {
87
87
  >
88
88
  {content.metrics.map((metric) => (
89
89
  <Card className="p-4" key={metric.label}>
90
- <div className="font-mono text-xs uppercase tracking-[0.12em] text-dashboard-text-muted">
90
+ <div className="font-sans font-medium text-xs text-dashboard-text-muted">
91
91
  {metric.label}
92
92
  </div>
93
93
  <div className="mt-3 font-display text-2xl font-light text-dashboard-text">
@@ -121,7 +121,7 @@ export function PluginUserPage(props: { page: PluginUserPageLink }) {
121
121
  ) : records.length === 0 ? (
122
122
  <Card padding="md">
123
123
  <div className="flex items-center gap-4">
124
- <div className="grid size-10 shrink-0 place-items-center rounded border border-white/[0.07] bg-white/[0.025] text-dashboard-text-muted">
124
+ <div className="grid size-10 shrink-0 place-items-center rounded-md border border-dashboard-border bg-dashboard-fill-soft text-dashboard-text-muted">
125
125
  <Boxes aria-hidden="true" size={17} />
126
126
  </div>
127
127
  <p className="m-0 text-sm text-dashboard-text-muted">
@@ -180,7 +180,7 @@ export function PluginUserPage(props: { page: PluginUserPageLink }) {
180
180
  <dl className="mt-4 flex flex-wrap gap-x-6 gap-y-2">
181
181
  {record.metadata.map((item) => (
182
182
  <div key={item.label}>
183
- <dt className="font-mono text-xs uppercase tracking-[0.12em] text-dashboard-text-muted">
183
+ <dt className="font-sans font-medium text-xs text-dashboard-text-muted">
184
184
  {item.label}
185
185
  </dt>
186
186
  <dd className="mt-1 ml-0 font-mono text-xs text-dashboard-text-muted">
@@ -7,12 +7,13 @@ export function cn(
7
7
 
8
8
  export const dashboardContainerClass = "mx-auto w-full min-w-0 max-w-screen-xl";
9
9
 
10
+ /** Underline a neutral inline link, such as a channel or record name in prose. */
11
+ export const dashboardInlineLinkClass =
12
+ "text-dashboard-text underline decoration-dashboard-border-heavy underline-offset-2 transition-colors hover:decoration-dashboard-text-muted";
13
+
10
14
  export const dashboardInteractiveTextClass =
11
15
  "text-dashboard-text-muted hover:text-dashboard-text";
12
16
 
13
17
  /** Raised input surface so the chat box reads against the near-black shell. */
14
18
  export const dashboardComposerSurfaceClass =
15
- "rounded-xl border border-dashboard-border-interactive bg-dashboard-surface-active";
16
-
17
- /** Shared shell canvas + grid background class from `tailwind.css`. */
18
- export const dashboardShellBgClass = "dashboard-shell-bg";
19
+ "rounded-xl border border-dashboard-border-emphasis bg-dashboard-surface-raised shadow-[0_8px_32px_rgba(0,0,0,0.35)] transition-colors";
@@ -40,6 +40,8 @@ export type TranscriptViewToolCallPart = {
40
40
  export type TranscriptViewSubagentPart = {
41
41
  agentName?: string;
42
42
  childConversationId: string;
43
+ /** When the child reached its current terminal status. */
44
+ finishedTimestamp?: number;
43
45
  id: string;
44
46
  status: "aborted" | "blocked" | "completed" | "error" | "running";
45
47
  subagentKind: string;
@@ -156,6 +158,7 @@ export type Conversation = {
156
158
  channel?: string;
157
159
  channelName?: string;
158
160
  channelNameRedacted?: boolean;
161
+ childAgentTotals?: ConversationSummaryReport["childAgentTotals"];
159
162
  cumulativeDurationMs: number;
160
163
  cumulativeUsage?: ConversationSummaryReport["cumulativeUsage"];
161
164
  displayTitle: string;
@@ -129,6 +129,8 @@ export const DASHBOARD_QA_CONVERSATION_ID = "internal:dashboard-qa";
129
129
  export const ARCHIVED_CONVERSATION_ID = "internal:archived-restore-qa";
130
130
  const DASHBOARD_QA_PLAN_ID = "junior:internal:dashboard-qa:advisor-plan";
131
131
  const DASHBOARD_QA_REVIEW_ID = "junior:internal:dashboard-qa:advisor-review";
132
+ const DASHBOARD_QA_PLAN_CHECK_ID =
133
+ "junior:internal:dashboard-qa:advisor-plan:claim-check";
132
134
  /** Process-local archive state so mock restore can be exercised in visual QA. */
133
135
  const mockArchivedConversationIds = new Set<string>([ARCHIVED_CONVERSATION_ID]);
134
136
 
@@ -672,7 +674,24 @@ function dashboardQaConversation(nowMs: number): ConversationDetailReport {
672
674
  updatedAt: iso(Date.parse(startedAt), 20_000),
673
675
  },
674
676
  ],
675
- cumulativeDurationMs: 98_000,
677
+ // Totals include all three subagents, like the API.
678
+ childAgentTotals: {
679
+ count: 3,
680
+ cumulativeDurationMs: 88_400,
681
+ cumulativeUsage: {
682
+ inputTokens: 48_700,
683
+ outputTokens: 2_680,
684
+ cachedInputTokens: 21_600,
685
+ cost: { total: 0.172 },
686
+ },
687
+ },
688
+ cumulativeDurationMs: 186_400,
689
+ cumulativeUsage: {
690
+ inputTokens: 100_700,
691
+ outputTokens: 6_080,
692
+ cachedInputTokens: 51_600,
693
+ cost: { total: 0.382 },
694
+ },
676
695
  events: [
677
696
  reportEvent(0, startedAt, {
678
697
  type: "message",
@@ -973,8 +992,9 @@ function advisorConversation(
973
992
  text: string,
974
993
  metrics: Pick<
975
994
  ConversationDetailReport,
976
- "cumulativeDurationMs" | "cumulativeUsage"
995
+ "childAgentTotals" | "cumulativeDurationMs" | "cumulativeUsage"
977
996
  >,
997
+ parentConversationId = DASHBOARD_QA_CONVERSATION_ID,
978
998
  ): MockConversation {
979
999
  const startedAt = iso(nowMs, -10 * 60_000);
980
1000
  const conversation = detail(nowMs, {
@@ -999,10 +1019,7 @@ function advisorConversation(
999
1019
  }),
1000
1020
  ],
1001
1021
  });
1002
- return {
1003
- ...conversation,
1004
- parentConversationId: DASHBOARD_QA_CONVERSATION_ID,
1005
- };
1022
+ return { ...conversation, parentConversationId };
1006
1023
  }
1007
1024
 
1008
1025
  function longConversation(nowMs: number): ConversationDetailReport {
@@ -1404,14 +1421,37 @@ function mockConversations(nowMs: number): MockConversation[] {
1404
1421
  DASHBOARD_QA_PLAN_ID,
1405
1422
  "Review the dashboard plan before editing.",
1406
1423
  {
1407
- cumulativeDurationMs: 72_400,
1424
+ childAgentTotals: {
1425
+ count: 1,
1426
+ cumulativeDurationMs: 6_200,
1427
+ cumulativeUsage: {
1428
+ inputTokens: 4_100,
1429
+ outputTokens: 220,
1430
+ cost: { total: 0.011 },
1431
+ },
1432
+ },
1433
+ cumulativeDurationMs: 78_600,
1408
1434
  cumulativeUsage: {
1409
- inputTokens: 38_400,
1410
- outputTokens: 2_150,
1435
+ inputTokens: 42_500,
1436
+ outputTokens: 2_370,
1411
1437
  cachedInputTokens: 21_600,
1412
- cost: { input: 0.094, output: 0.048, total: 0.142 },
1438
+ cost: { input: 0.1, output: 0.053, total: 0.153 },
1439
+ },
1440
+ },
1441
+ ),
1442
+ advisorConversation(
1443
+ nowMs,
1444
+ DASHBOARD_QA_PLAN_CHECK_ID,
1445
+ "Check one claim in the dashboard plan.",
1446
+ {
1447
+ cumulativeDurationMs: 6_200,
1448
+ cumulativeUsage: {
1449
+ inputTokens: 4_100,
1450
+ outputTokens: 220,
1451
+ cost: { total: 0.011 },
1413
1452
  },
1414
1453
  },
1454
+ DASHBOARD_QA_PLAN_ID,
1415
1455
  ),
1416
1456
  advisorConversation(
1417
1457
  nowMs,
@@ -1855,20 +1895,39 @@ export function readMockConversationChildAgents(
1855
1895
  (candidate) => candidate.conversationId === conversationId,
1856
1896
  );
1857
1897
  if (!conversation) return undefined;
1858
- if (conversationId !== DASHBOARD_QA_CONVERSATION_ID) {
1859
- return { agents: [], conversationId };
1860
- }
1861
1898
  const startedAtMs = NOW_MS - 5 * 60 * 60_000;
1862
- // Match the API: each row has the usage of its own child Conversation.
1899
+ // Match the API: each row has the usage of its child Conversation and of
1900
+ // that child's own subagents.
1863
1901
  const childMetrics = (childConversationId: string) => {
1864
1902
  const child = conversations.find(
1865
1903
  (candidate) => candidate.conversationId === childConversationId,
1866
1904
  )!;
1867
1905
  return {
1906
+ ...(child.childAgentTotals
1907
+ ? { childAgentTotals: child.childAgentTotals }
1908
+ : undefined),
1868
1909
  cumulativeDurationMs: child.cumulativeDurationMs,
1869
1910
  cumulativeUsage: child.cumulativeUsage,
1870
1911
  };
1871
1912
  };
1913
+ if (conversationId === DASHBOARD_QA_PLAN_ID) {
1914
+ return {
1915
+ agents: [
1916
+ {
1917
+ ...childMetrics(DASHBOARD_QA_PLAN_CHECK_ID),
1918
+ conversationId: DASHBOARD_QA_PLAN_CHECK_ID,
1919
+ status: "completed",
1920
+ task: "Check one claim in the dashboard plan.",
1921
+ title: "Check one plan claim",
1922
+ updatedAt: iso(startedAtMs, 16_000),
1923
+ },
1924
+ ],
1925
+ conversationId,
1926
+ };
1927
+ }
1928
+ if (conversationId !== DASHBOARD_QA_CONVERSATION_ID) {
1929
+ return { agents: [], conversationId };
1930
+ }
1872
1931
  return {
1873
1932
  agents: [
1874
1933
  {
package/src/tailwind.css CHANGED
@@ -2,18 +2,24 @@
2
2
  @import "tailwindcss";
3
3
 
4
4
  /*
5
- * Dashboard color tokens.
6
- * Keep structural UI colors here so light/dark themes can share one utility surface.
5
+ * Dashboard design tokens. components/README.md explains each role.
6
+ * Keep structural UI colors here so a second theme can redefine them.
7
7
  * Prefer roles over opacity ladders. Status accents stay as Tailwind palette utilities.
8
8
  */
9
9
  @theme {
10
+ /* Headings, record titles, and large metric values. */
10
11
  --font-display:
11
12
  "Outfit", "Avenir Next", Avenir, "Segoe UI", -apple-system,
12
13
  BlinkMacSystemFont, sans-serif;
13
- /* Primary UI/body face. Prefer Inter over the previous mono-first shell. */
14
+ /* UI face for prose, controls, navigation, labels, and names. */
14
15
  --font-sans:
15
16
  "Inter", -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu,
16
17
  sans-serif;
18
+ /*
19
+ * Machine values only: code, ids, paths, file names, and raw payloads.
20
+ * Use font-sans with tabular-nums for counts, times, and prices. Controls,
21
+ * navigation, and human text use font-sans.
22
+ */
17
23
  --font-mono:
18
24
  ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
19
25
  monospace;
@@ -43,25 +49,39 @@
43
49
  --text-4xl: 2.25rem; /* 36px — large display titles */
44
50
  --text-4xl--line-height: 1.15;
45
51
 
46
- /* Canvas and elevated surfaces */
47
- --color-dashboard-bg: #050507;
48
- --color-dashboard-bg-elevated: #070707;
49
- --color-dashboard-surface-panel: #09090b;
50
- --color-dashboard-surface-active: #1a1a1c;
51
- --color-dashboard-surface-raised: #0b0b0b;
52
- --color-dashboard-surface-hover: #151515;
53
- --color-dashboard-control: #111114;
52
+ /*
53
+ * Canvas and elevated surfaces, darkest to lightest. One cool zinc hue.
54
+ * bg: page canvas. bg-elevated: drawers and sheets. surface-panel: sidebar,
55
+ * cards, and message bubbles. surface-raised: buttons, tooltips, and drawer
56
+ * headers. control: form controls. surface-hover / surface-active: row
57
+ * hover and selected rows.
58
+ */
59
+ --color-dashboard-bg: #060607;
60
+ --color-dashboard-bg-elevated: #09090b;
61
+ --color-dashboard-surface-panel: #0c0c0e;
62
+ --color-dashboard-surface-active: #1c1c20;
63
+ --color-dashboard-surface-raised: #101013;
64
+ --color-dashboard-surface-hover: #17171a;
65
+ --color-dashboard-control: #121215;
54
66
  --color-dashboard-ink: #000000;
55
67
 
56
- /* Text */
68
+ /* Text, brightest to dimmest: solid, text, subtle, muted, faint. */
57
69
  --color-dashboard-text: #f4f4f5;
58
70
  --color-dashboard-text-muted: #a1a1aa;
59
- --color-dashboard-text-subtle: #b8b8b8;
60
- --color-dashboard-text-faint: #888888;
71
+ --color-dashboard-text-subtle: #c4c4cc;
72
+ --color-dashboard-text-faint: #8a8a93;
61
73
  --color-dashboard-text-solid: #ffffff;
62
74
  --color-dashboard-text-inverse: #000000;
63
75
 
64
- /* Brand focus used for rings and avatar chips */
76
+ /*
77
+ * Brand accent (lavender). Use accent for icons, active markers, and tinted
78
+ * fills (with an opacity suffix). Use accent-text for links and accent text
79
+ * on the dark canvas. Focus rings use focus, which is the same hue.
80
+ * Status colors (info, success, warning, error) and categorical chart or
81
+ * event colors stay as Tailwind palette utilities.
82
+ */
83
+ --color-dashboard-accent: #beaaff;
84
+ --color-dashboard-accent-text: #ddd3ff;
65
85
  --color-dashboard-focus: #beaaff;
66
86
 
67
87
  /* Hairline borders (pre-multiplied so themes can flip without white/black literals) */
@@ -82,8 +102,7 @@
82
102
  --color-dashboard-overlay-soft: rgb(0 0 0 / 0.2);
83
103
  --color-dashboard-overlay: rgb(0 0 0 / 0.55);
84
104
 
85
- /* Shell grid + scroll chrome */
86
- --color-dashboard-grid-line: rgb(255 255 255 / 0.04);
105
+ /* Scroll chrome */
87
106
  --color-dashboard-scrollbar-track: rgb(255 255 255 / 0.02);
88
107
  --color-dashboard-scrollbar-thumb: rgb(255 255 255 / 0.1);
89
108
  --color-dashboard-scrollbar-thumb-hover: rgb(255 255 255 / 0.2);
@@ -118,27 +137,6 @@
118
137
  }
119
138
  }
120
139
 
121
- /* Shared shell canvas + grid. Prefer this class over inline background styles. */
122
- .dashboard-shell-bg {
123
- background-color: var(--color-dashboard-bg);
124
- background-image:
125
- radial-gradient(
126
- ellipse at 50% 0%,
127
- transparent 0%,
128
- var(--color-dashboard-bg) 70%
129
- ),
130
- linear-gradient(var(--color-dashboard-grid-line) 1px, transparent 1px),
131
- linear-gradient(
132
- 90deg,
133
- var(--color-dashboard-grid-line) 1px,
134
- transparent 1px
135
- );
136
- background-size:
137
- 100% 100%,
138
- 40px 40px,
139
- 40px 40px;
140
- }
141
-
142
140
  @source "./app.ts";
143
141
  @source "./dashboardLoader.ts";
144
142
  @source "./client.tsx";