@sentry/junior-dashboard 0.264.0 → 0.266.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.
- package/LICENSE +201 -0
- package/README.md +2 -5
- package/dist/app.js +119 -35
- package/dist/client.js +145 -136
- package/dist/index.d.ts +0 -1
- package/dist/index.js +119 -35
- package/dist/tailwind.css +1 -1
- package/package.json +5 -4
- package/src/api/schema.ts +0 -1
- package/src/app.ts +5 -20
- package/src/client/App.tsx +29 -31
- package/src/client/api.ts +7 -0
- package/src/client/components/ActorAvatar.tsx +10 -22
- package/src/client/components/BottomSheet.tsx +12 -2
- package/src/client/components/ConnectionBanner.tsx +4 -3
- package/src/client/components/CopyButton.tsx +82 -0
- package/src/client/components/DetailsPanel.tsx +133 -0
- package/src/client/components/Drawer.tsx +15 -24
- package/src/client/components/EmptyTelemetry.tsx +5 -3
- package/src/client/components/FilterBar.tsx +16 -31
- package/src/client/components/ImageAttachment.tsx +49 -63
- package/src/client/components/InlineError.tsx +8 -4
- package/src/client/components/Metric.tsx +33 -23
- package/src/client/components/Notice.tsx +19 -26
- package/src/client/components/PageContentSkeleton.tsx +1 -1
- package/src/client/components/Pagination.tsx +27 -27
- package/src/client/components/ParticipantAvatarStack.tsx +43 -39
- package/src/client/components/ProfileMenu.tsx +27 -93
- package/src/client/components/README.md +103 -78
- package/src/client/components/SearchInput.tsx +51 -41
- package/src/client/components/SegmentedNav.tsx +1 -1
- package/src/client/components/ShimmerText.tsx +2 -6
- package/src/client/components/ThemeSwitcher.tsx +19 -15
- package/src/client/components/VersionDriftBanner.tsx +9 -7
- package/src/client/components/charts/ActivityChart.tsx +173 -288
- package/src/client/components/charts/CacheWrites.tsx +59 -37
- package/src/client/components/charts/InputCacheChart.tsx +137 -131
- package/src/client/components/charts/README.md +4 -4
- package/src/client/components/charts/SystemMetricCharts.tsx +68 -95
- package/src/client/components/charts/WorkspaceUsageChart.tsx +42 -62
- package/src/client/components/controls/DirectorySortSelect.tsx +3 -3
- package/src/client/components/controls/TimeRangeSelector.tsx +10 -15
- package/src/client/components/layout/DashboardHeader.tsx +44 -90
- package/src/client/components/layout/SecondaryNavigation.tsx +2 -1
- package/src/client/components/layout/VisualViewportShell.tsx +2 -2
- package/src/client/components/ui/accordion.tsx +77 -0
- package/src/client/components/ui/alert-dialog.tsx +89 -0
- package/src/client/components/ui/alert.tsx +64 -0
- package/src/client/components/ui/avatar.tsx +53 -0
- package/src/client/components/ui/button.tsx +86 -0
- package/src/client/components/ui/chart.tsx +74 -0
- package/src/client/components/ui/checkbox.tsx +26 -0
- package/src/client/components/ui/collapsible.tsx +22 -0
- package/src/client/components/ui/dialog.tsx +66 -0
- package/src/client/components/ui/empty.tsx +32 -0
- package/src/client/components/ui/field.tsx +49 -0
- package/src/client/components/ui/input-group.tsx +96 -0
- package/src/client/components/ui/input.tsx +35 -0
- package/src/client/components/ui/native-select.tsx +57 -0
- package/src/client/components/ui/pagination.tsx +60 -0
- package/src/client/components/ui/popover.tsx +67 -0
- package/src/client/components/ui/radio-group.tsx +32 -0
- package/src/client/components/ui/sheet.tsx +13 -3
- package/src/client/components/ui/skeleton.tsx +19 -0
- package/src/client/components/ui/spinner.tsx +21 -0
- package/src/client/components/ui/table.tsx +101 -0
- package/src/client/components/ui/tabs.tsx +75 -0
- package/src/client/components/ui/textarea.tsx +17 -0
- package/src/client/components/ui/toast.tsx +215 -0
- package/src/client/components/ui/toggle-group.tsx +36 -0
- package/src/client/components/ui/toggle.tsx +37 -0
- package/src/client/components/ui/tooltip.tsx +168 -0
- package/src/client/components/ui/trace.tsx +96 -0
- package/src/client/conversations/ChatLayout.tsx +7 -3
- package/src/client/conversations/ConversationBrief.tsx +17 -6
- package/src/client/conversations/ConversationChildAgents.tsx +5 -5
- package/src/client/conversations/ConversationComposer.tsx +26 -12
- package/src/client/conversations/ConversationDetails.tsx +147 -62
- package/src/client/conversations/ConversationEventDetails.tsx +141 -0
- package/src/client/conversations/ConversationEventLog.tsx +150 -129
- package/src/client/conversations/ConversationHeader.tsx +13 -7
- package/src/client/conversations/ConversationHeaderActions.tsx +97 -93
- package/src/client/conversations/ConversationHomeList.tsx +1 -1
- package/src/client/conversations/ConversationLinkedWork.tsx +118 -0
- package/src/client/conversations/ConversationMeta.tsx +55 -88
- package/src/client/conversations/ConversationPage.tsx +220 -101
- package/src/client/conversations/ConversationSidebar.tsx +49 -29
- package/src/client/conversations/ConversationUsageBreakdown.tsx +108 -65
- package/src/client/conversations/ConversationWatches.tsx +173 -0
- package/src/client/conversations/ConversationWorkspace.tsx +12 -22
- package/src/client/conversations/ConversationWorkspaceLoading.tsx +1 -1
- package/src/client/conversations/DetailsList.tsx +139 -0
- package/src/client/conversations/EventDetails.tsx +42 -8
- package/src/client/conversations/EventUsage.tsx +99 -74
- package/src/client/conversations/ForkConversationButton.tsx +27 -16
- package/src/client/conversations/ObjectCard.tsx +20 -8
- package/src/client/conversations/PendingMailboxStack.tsx +52 -38
- package/src/client/conversations/README.md +89 -13
- package/src/client/conversations/ShareConversationButton.tsx +28 -17
- package/src/client/conversations/SubagentTranscriptDrawer.tsx +21 -15
- package/src/client/conversations/ToolFrame.tsx +36 -52
- package/src/client/conversations/TranscriptActivityGroup.tsx +13 -4
- package/src/client/conversations/TranscriptAutomationTriggerView.tsx +5 -4
- package/src/client/conversations/TranscriptContextEventView.tsx +25 -11
- package/src/client/conversations/TranscriptEventView.tsx +35 -16
- package/src/client/conversations/TranscriptHeadingRow.tsx +7 -7
- package/src/client/conversations/TranscriptLoading.tsx +1 -1
- package/src/client/conversations/TranscriptMarkdown.tsx +25 -20
- package/src/client/conversations/TranscriptMessageContextView.tsx +35 -18
- package/src/client/conversations/TranscriptMessageView.tsx +6 -1
- package/src/client/conversations/TranscriptReasoningView.tsx +54 -68
- package/src/client/conversations/TranscriptStructuredEventView.tsx +25 -15
- package/src/client/conversations/TranscriptSummary.tsx +34 -2
- package/src/client/conversations/TranscriptTimestamp.tsx +9 -7
- package/src/client/conversations/TranscriptToolView.tsx +1 -1
- package/src/client/conversations/TranscriptTurnContextView.tsx +144 -65
- package/src/client/conversations/TranscriptView.tsx +63 -27
- package/src/client/conversations/eventLog.ts +58 -0
- package/src/client/conversations/eventTime.ts +60 -0
- package/src/client/conversations/queries.ts +29 -0
- package/src/client/conversations/transcriptBottomPinning.ts +34 -0
- package/src/client/conversations/transcriptMentions.tsx +18 -5
- package/src/client/format.ts +5 -0
- package/src/client/pages/ConnectionsPage.tsx +2 -2
- package/src/client/pages/PersonalTokensPage.tsx +4 -4
- package/src/client/pages/SettingsPage.tsx +9 -10
- package/src/client/pages/admin/ServiceAccountsSection.tsx +2 -2
- package/src/client/pages/automations/AutomationCostChart.tsx +50 -71
- package/src/client/pages/automations/AutomationDeleteDialog.tsx +87 -0
- package/src/client/pages/automations/AutomationDetails.tsx +193 -0
- package/src/client/pages/automations/AutomationEditPage.tsx +7 -8
- package/src/client/pages/automations/AutomationEditor.tsx +41 -29
- package/src/client/pages/automations/AutomationEditorLoading.tsx +1 -1
- package/src/client/pages/automations/AutomationEventFields.tsx +202 -119
- package/src/client/pages/automations/AutomationExecutionChart.tsx +51 -64
- package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +47 -70
- package/src/client/pages/automations/AutomationExecutionsPage.tsx +150 -126
- package/src/client/pages/automations/AutomationFilters.tsx +189 -74
- package/src/client/pages/automations/AutomationLifecycle.tsx +109 -78
- package/src/client/pages/automations/AutomationOutcomeFields.tsx +26 -24
- package/src/client/pages/automations/AutomationRecentRuns.tsx +143 -0
- package/src/client/pages/automations/AutomationRow.tsx +12 -138
- package/src/client/pages/automations/AutomationRunDetails.tsx +307 -0
- package/src/client/pages/automations/AutomationRunsPage.tsx +119 -94
- package/src/client/pages/automations/AutomationScheduleFields.tsx +51 -51
- package/src/client/pages/automations/AutomationStatus.tsx +201 -0
- package/src/client/pages/automations/AutomationVersionsPage.tsx +65 -28
- package/src/client/pages/automations/AutomationsPage.tsx +80 -68
- package/src/client/pages/automations/AutomationsPageLayout.tsx +46 -14
- package/src/client/pages/automations/README.md +57 -0
- package/src/client/pages/automations/TriggerFilters.tsx +22 -0
- package/src/client/pages/automations/automationFormat.ts +37 -23
- package/src/client/pages/code/CodeActivityChart.tsx +59 -101
- package/src/client/pages/code/CodePage.tsx +52 -55
- package/src/client/pages/code/RepositoryPage.tsx +6 -8
- package/src/client/pages/locations/LocationActivityChart.tsx +53 -70
- package/src/client/pages/locations/LocationDirectoryActivityChart.tsx +60 -80
- package/src/client/pages/memory/MemoryCostChart.tsx +79 -103
- package/src/client/pages/memory/MemoryDetails.tsx +218 -0
- package/src/client/pages/memory/MemoryPage.tsx +168 -112
- package/src/client/pages/memory/MemoryPageLayout.tsx +33 -9
- package/src/client/pages/memory/MemoryTimeline.tsx +46 -69
- package/src/client/pages/memory/memoryRecord.ts +1 -1
- package/src/client/pages/people/ContributionGrid.tsx +23 -16
- package/src/client/pages/people/PeopleActivityChart.tsx +68 -107
- package/src/client/pages/people/ProfileCodeChanges.tsx +5 -5
- package/src/client/pages/system/BaseSandboxCard.tsx +1 -1
- package/src/client/pages/system/ConversationActivityChart.tsx +49 -67
- package/src/client/pages/system/GuardianActivity.tsx +1 -2
- package/src/client/pages/system/PluginBarChart.tsx +106 -87
- package/src/client/pages/system/PluginReportRecordSet.tsx +25 -24
- package/src/client/pages/system/README.md +23 -0
- package/src/client/pages/system/SystemNavigation.tsx +5 -1
- package/src/client/pages/system/WorkspaceDeleteDialog.tsx +111 -0
- package/src/client/pages/system/WorkspaceDetails.tsx +200 -43
- package/src/client/pages/system/WorkspaceEditor.tsx +59 -61
- package/src/client/pages/system/WorkspaceFormPage.tsx +23 -47
- package/src/client/pages/system/WorkspaceList.tsx +20 -30
- package/src/client/pages/system/WorkspacesPage.tsx +117 -119
- package/src/client/pages/system/sandboxSize.ts +8 -0
- package/src/client/pages/system/workspaceQueries.ts +53 -0
- package/src/client/pages/user/PluginUserPage.tsx +51 -2
- package/src/client/pages/user/pluginUserPageData.ts +1 -6
- package/src/client/styles.ts +4 -0
- package/src/client.tsx +7 -1
- package/src/mock-reporting/automation-collection.ts +4 -2
- package/src/mock-reporting/fixtures.ts +23 -7
- package/src/mock-reporting/routes.ts +12 -0
- package/src/mock-reporting/watches.ts +94 -0
- package/src/shell.ts +4 -9
- package/src/tailwind.css +0 -10
- package/src/client/components/Button.tsx +0 -118
- package/src/client/components/Field.tsx +0 -53
- package/src/client/components/SegmentedTabs.tsx +0 -119
- package/src/client/components/Select.tsx +0 -52
- package/src/client/components/Skeleton.tsx +0 -17
- package/src/client/components/TextInput.tsx +0 -58
- package/src/client/components/Tooltip.tsx +0 -216
- package/src/client/components/charts/useChartLayout.ts +0 -27
- package/src/client/components/ui/sheet.LICENSE +0 -21
- package/src/client/conversations/ConversationDetailsFrame.tsx +0 -119
- package/src/client/conversations/CopyMarkdownButton.tsx +0 -65
- package/src/client/pages/automations/AutomationDetailsDrawer.tsx +0 -219
- package/src/client/pages/dev/ChartFixtures.tsx +0 -325
- package/src/client/pages/dev/ComponentsPage.tsx +0 -899
- package/src/client/pages/dev/ConversationFixture.tsx +0 -231
- package/src/client/pages/dev/ObjectFixtures.tsx +0 -138
- package/src/client/pages/dev/SegmentedFixtures.tsx +0 -59
- package/src/client/pages/dev/SelectFixtures.tsx +0 -62
- package/src/client/pages/dev/TranscriptActivityFixtures.tsx +0 -206
- package/src/client/pages/memory/MemoryDetailsDrawer.tsx +0 -167
- package/src/client/pages/system/SandboxSizeSummary.tsx +0 -47
- package/src/client/pages/system/SnapshotSummary.tsx +0 -78
|
@@ -1,34 +1,52 @@
|
|
|
1
1
|
import { useState, type ReactNode } from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { DetailsPanel, useDetailsPanel } from "../components/DetailsPanel";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
Tooltip,
|
|
6
|
+
TooltipContent,
|
|
7
|
+
TooltipTrigger,
|
|
8
|
+
} from "../components/ui/tooltip";
|
|
9
|
+
import {
|
|
10
|
+
Tabs,
|
|
11
|
+
TabsContent,
|
|
12
|
+
TabsList,
|
|
13
|
+
TabsTrigger,
|
|
14
|
+
} from "../components/ui/tabs";
|
|
9
15
|
import {
|
|
10
16
|
ConversationChildAgents,
|
|
11
17
|
useConversationChildAgents,
|
|
12
18
|
} from "./ConversationChildAgents";
|
|
19
|
+
import {
|
|
20
|
+
ConversationLinkedWork,
|
|
21
|
+
type ConversationLink,
|
|
22
|
+
} from "./ConversationLinkedWork";
|
|
13
23
|
import {
|
|
14
24
|
ConversationMemories,
|
|
15
25
|
useConversationMemories,
|
|
16
26
|
} from "./ConversationMemories";
|
|
27
|
+
import {
|
|
28
|
+
ConversationWatches,
|
|
29
|
+
useConversationWatches,
|
|
30
|
+
} from "./ConversationWatches";
|
|
17
31
|
import { ShareConversationButton } from "./ShareConversationButton";
|
|
18
32
|
import type { SubagentTranscriptTarget } from "./SubagentTranscriptDrawer";
|
|
19
33
|
|
|
20
34
|
type DetailsTab = "agents" | "summary" | "memories";
|
|
21
35
|
|
|
36
|
+
/** Keep the tabs fixed while each panel scrolls to the frame edge. */
|
|
37
|
+
const detailsPanelClass =
|
|
38
|
+
"min-h-0 overflow-y-auto overscroll-contain rounded-none px-4 pb-[max(1rem,env(safe-area-inset-bottom))] focus-visible:-outline-offset-2";
|
|
39
|
+
|
|
22
40
|
/**
|
|
23
|
-
* Show conversation details: the brief and facts first,
|
|
24
|
-
*
|
|
25
|
-
* header so every tab can reach them.
|
|
41
|
+
* Show conversation details: the brief, participants, and run facts first,
|
|
42
|
+
* then watches, linked work, and the usage breakdown. Share and Sentry links
|
|
43
|
+
* stay in the header so every tab can reach them.
|
|
26
44
|
*/
|
|
27
45
|
export function ConversationDetails(props: {
|
|
28
|
-
annotations: ReactNode;
|
|
29
46
|
brief: ReactNode;
|
|
30
47
|
conversationId: string;
|
|
31
48
|
identity: ReactNode;
|
|
49
|
+
links: ConversationLink[];
|
|
32
50
|
onClose(): void;
|
|
33
51
|
/** Open one child agent transcript. A details sheet closes first. */
|
|
34
52
|
onOpenSubagent(target: SubagentTranscriptTarget): void;
|
|
@@ -37,29 +55,47 @@ export function ConversationDetails(props: {
|
|
|
37
55
|
usage: ReactNode;
|
|
38
56
|
}) {
|
|
39
57
|
const [tab, setTab] = useState<DetailsTab>("summary");
|
|
40
|
-
const panel =
|
|
58
|
+
const panel = useDetailsPanel();
|
|
41
59
|
// Load both lists with details so each tab can show its count.
|
|
42
60
|
const memories = useConversationMemories(props.conversationId);
|
|
43
61
|
const agents = useConversationChildAgents(props.conversationId);
|
|
44
|
-
const
|
|
45
|
-
{ label: "Summary", value: "summary" },
|
|
46
|
-
{
|
|
47
|
-
count: memories.data?.memories.length,
|
|
48
|
-
label: "Memories",
|
|
49
|
-
value: "memories",
|
|
50
|
-
},
|
|
51
|
-
{ count: agents.data?.agents.length, label: "Subagents", value: "agents" },
|
|
52
|
-
] as const;
|
|
62
|
+
const watches = useConversationWatches(props.conversationId).data?.watches;
|
|
53
63
|
|
|
64
|
+
// People first, then run facts. Watches come before linked work: they say
|
|
65
|
+
// what can wake this agent later, so readers see them without another tab.
|
|
54
66
|
const sections = [
|
|
55
|
-
{ content: props.overview, key: "overview", title: undefined },
|
|
56
67
|
{ content: props.identity, key: "participants", title: "Participants" },
|
|
57
|
-
{ content: props.
|
|
68
|
+
{ content: props.overview, key: "overview", title: undefined },
|
|
69
|
+
{
|
|
70
|
+
content: watches?.length ? (
|
|
71
|
+
<ConversationWatches watches={watches} />
|
|
72
|
+
) : null,
|
|
73
|
+
count: watches?.length,
|
|
74
|
+
key: "watching",
|
|
75
|
+
title: "Watching",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
content: props.links.length ? (
|
|
79
|
+
<ConversationLinkedWork links={props.links} />
|
|
80
|
+
) : null,
|
|
81
|
+
count: props.links.length,
|
|
82
|
+
key: "linked-work",
|
|
83
|
+
title: "Linked work",
|
|
84
|
+
},
|
|
58
85
|
{ content: props.usage, key: "usage", title: "Usage" },
|
|
59
86
|
].filter((section) => section.content != null);
|
|
60
87
|
|
|
61
88
|
return (
|
|
62
|
-
<
|
|
89
|
+
<DetailsPanel
|
|
90
|
+
label="Conversation details"
|
|
91
|
+
title={
|
|
92
|
+
<h2
|
|
93
|
+
aria-label="Conversation details"
|
|
94
|
+
className="m-0 text-base font-semibold text-dashboard-text"
|
|
95
|
+
>
|
|
96
|
+
Details
|
|
97
|
+
</h2>
|
|
98
|
+
}
|
|
63
99
|
actions={
|
|
64
100
|
<>
|
|
65
101
|
<ShareConversationButton
|
|
@@ -68,32 +104,79 @@ export function ConversationDetails(props: {
|
|
|
68
104
|
layout="icon"
|
|
69
105
|
/>
|
|
70
106
|
{props.sentryConversationUrl ? (
|
|
71
|
-
<
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
107
|
+
<Tooltip>
|
|
108
|
+
<TooltipTrigger
|
|
109
|
+
render={
|
|
110
|
+
<a
|
|
111
|
+
aria-label="Open in Sentry"
|
|
112
|
+
className="grid size-9 place-items-center rounded-md text-dashboard-text-muted transition-colors hover:bg-dashboard-fill-strong hover:text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-dashboard-focus"
|
|
113
|
+
href={props.sentryConversationUrl}
|
|
114
|
+
rel="noopener noreferrer"
|
|
115
|
+
target="_blank"
|
|
116
|
+
>
|
|
117
|
+
<SentryGlyph />
|
|
118
|
+
</a>
|
|
119
|
+
}
|
|
120
|
+
/>
|
|
121
|
+
<TooltipContent size="compact" side="bottom">
|
|
122
|
+
Open in Sentry
|
|
123
|
+
</TooltipContent>
|
|
124
|
+
</Tooltip>
|
|
82
125
|
) : null}
|
|
83
126
|
</>
|
|
84
127
|
}
|
|
85
128
|
onClose={props.onClose}
|
|
86
129
|
>
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
label="Conversation details"
|
|
91
|
-
onChange={setTab}
|
|
130
|
+
<Tabs
|
|
131
|
+
className="h-full min-h-0 grid-rows-[auto_minmax(0,1fr)] gap-0"
|
|
132
|
+
onValueChange={(value: DetailsTab) => setTab(value)}
|
|
92
133
|
value={tab}
|
|
93
134
|
>
|
|
94
|
-
|
|
135
|
+
<TabsList
|
|
136
|
+
activateOnFocus
|
|
137
|
+
aria-label="Conversation details"
|
|
138
|
+
className="m-4"
|
|
139
|
+
>
|
|
140
|
+
<TabsTrigger value="summary">
|
|
141
|
+
<span className="truncate">Summary</span>
|
|
142
|
+
</TabsTrigger>
|
|
143
|
+
<TabsTrigger value="memories">
|
|
144
|
+
<span className="truncate">Memories</span>
|
|
145
|
+
<TabCount count={memories.data?.memories.length} />
|
|
146
|
+
</TabsTrigger>
|
|
147
|
+
<TabsTrigger value="agents">
|
|
148
|
+
<span className="truncate">Subagents</span>
|
|
149
|
+
<TabCount count={agents.data?.agents.length} />
|
|
150
|
+
</TabsTrigger>
|
|
151
|
+
</TabsList>
|
|
152
|
+
<TabsContent className={detailsPanelClass} value="summary">
|
|
153
|
+
{props.brief != null || sections.length > 0 ? (
|
|
154
|
+
<div className="grid min-w-0 gap-3">
|
|
155
|
+
{props.brief != null ? (
|
|
156
|
+
<div className="min-w-0 break-words px-1 pb-1 font-sans text-sm leading-relaxed text-dashboard-text-muted">
|
|
157
|
+
{props.brief}
|
|
158
|
+
</div>
|
|
159
|
+
) : null}
|
|
160
|
+
{sections.map((section) => (
|
|
161
|
+
<DetailsSection
|
|
162
|
+
count={section.count}
|
|
163
|
+
key={section.key}
|
|
164
|
+
title={section.title}
|
|
165
|
+
>
|
|
166
|
+
{section.content}
|
|
167
|
+
</DetailsSection>
|
|
168
|
+
))}
|
|
169
|
+
</div>
|
|
170
|
+
) : (
|
|
171
|
+
<p className="m-0 font-sans text-sm leading-relaxed text-dashboard-text-muted">
|
|
172
|
+
No additional conversation details.
|
|
173
|
+
</p>
|
|
174
|
+
)}
|
|
175
|
+
</TabsContent>
|
|
176
|
+
<TabsContent className={detailsPanelClass} value="memories">
|
|
95
177
|
<ConversationMemories conversationId={props.conversationId} />
|
|
96
|
-
|
|
178
|
+
</TabsContent>
|
|
179
|
+
<TabsContent className={detailsPanelClass} value="agents">
|
|
97
180
|
<ConversationChildAgents
|
|
98
181
|
conversationId={props.conversationId}
|
|
99
182
|
onOpenAgent={(target) => {
|
|
@@ -102,36 +185,38 @@ export function ConversationDetails(props: {
|
|
|
102
185
|
props.onOpenSubagent(target);
|
|
103
186
|
}}
|
|
104
187
|
/>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
) : (
|
|
119
|
-
<p className="m-0 font-sans text-sm leading-relaxed text-dashboard-text-muted">
|
|
120
|
-
No additional conversation details.
|
|
121
|
-
</p>
|
|
122
|
-
)}
|
|
123
|
-
</SegmentedTabs>
|
|
124
|
-
</ConversationDetailsFrame>
|
|
188
|
+
</TabsContent>
|
|
189
|
+
</Tabs>
|
|
190
|
+
</DetailsPanel>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Show a panel's entry count. Zero and unknown counts are hidden. */
|
|
195
|
+
function TabCount(props: { count: number | undefined }) {
|
|
196
|
+
if (!props.count) return null;
|
|
197
|
+
return (
|
|
198
|
+
<span className="min-w-5 shrink-0 rounded-full bg-dashboard-fill-strong px-1.5 text-center text-xs font-semibold leading-5 tabular-nums">
|
|
199
|
+
{props.count.toLocaleString("en-US")}
|
|
200
|
+
</span>
|
|
125
201
|
);
|
|
126
202
|
}
|
|
127
203
|
|
|
128
204
|
/** Group one kind of conversation detail in a compact card. */
|
|
129
|
-
function DetailsSection(props: {
|
|
205
|
+
function DetailsSection(props: {
|
|
206
|
+
children: ReactNode;
|
|
207
|
+
count?: number;
|
|
208
|
+
title?: string;
|
|
209
|
+
}) {
|
|
130
210
|
return (
|
|
131
211
|
<section className="grid min-w-0 gap-2.5 rounded-lg border border-dashboard-border-subtle bg-dashboard-surface-panel p-3">
|
|
132
212
|
{props.title ? (
|
|
133
|
-
<h3 className="m-0 font-sans text-xs font-medium text-dashboard-text-muted">
|
|
213
|
+
<h3 className="m-0 flex items-center gap-1.5 font-sans text-xs font-medium text-dashboard-text-muted">
|
|
134
214
|
{props.title}
|
|
215
|
+
{props.count ? (
|
|
216
|
+
<span className="tabular-nums text-dashboard-text-faint">
|
|
217
|
+
{props.count.toLocaleString("en-US")}
|
|
218
|
+
</span>
|
|
219
|
+
) : null}
|
|
135
220
|
</h3>
|
|
136
221
|
) : null}
|
|
137
222
|
<div className="min-w-0 break-words font-sans text-xs leading-relaxed text-dashboard-text-muted">
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { ConversationReportEvent } from "@sentry/junior/api/schema";
|
|
2
|
+
import { ChevronDown, ChevronUp } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../styles";
|
|
5
|
+
import { DetailsPanel } from "../components/DetailsPanel";
|
|
6
|
+
import { Button } from "../components/ui/button";
|
|
7
|
+
import { Skeleton } from "../components/ui/skeleton";
|
|
8
|
+
import type { ConversationTranscript } from "../types";
|
|
9
|
+
import { useEventTime } from "./eventTime";
|
|
10
|
+
import { EventDetails } from "./EventDetails";
|
|
11
|
+
import { ForkConversationButton } from "./ForkConversationButton";
|
|
12
|
+
|
|
13
|
+
// Step buttons keep focus at the ends of the log, so style the ARIA state.
|
|
14
|
+
const stepButtonClass =
|
|
15
|
+
"data-disabled:cursor-not-allowed data-disabled:opacity-50 data-disabled:hover:!bg-transparent data-disabled:hover:!text-dashboard-text-muted";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Show the selected event without blocking the main conversation's event log.
|
|
19
|
+
* Without an event, show a loading state while a linked event loads.
|
|
20
|
+
* `previous` and `next` are the adjacent visible rows of the event log.
|
|
21
|
+
*/
|
|
22
|
+
export function ConversationEventDetails(props: {
|
|
23
|
+
conversation?: ConversationTranscript;
|
|
24
|
+
event?: ConversationReportEvent;
|
|
25
|
+
next?: number;
|
|
26
|
+
onClose(): void;
|
|
27
|
+
onSelect?(seq: number): void;
|
|
28
|
+
overlay?: boolean;
|
|
29
|
+
previous?: number;
|
|
30
|
+
}) {
|
|
31
|
+
const { conversation, event, onSelect } = props;
|
|
32
|
+
const time = useEventTime();
|
|
33
|
+
const timestamp = event ? (
|
|
34
|
+
<time
|
|
35
|
+
className="block break-words font-mono text-xs text-dashboard-text-muted"
|
|
36
|
+
dateTime={event.createdAt}
|
|
37
|
+
title={event.createdAt}
|
|
38
|
+
>
|
|
39
|
+
{time.formatTimestamp(event.createdAt)}
|
|
40
|
+
</time>
|
|
41
|
+
) : null;
|
|
42
|
+
const title = event ? (
|
|
43
|
+
<>
|
|
44
|
+
<h2 className="m-0 mb-1 break-words font-mono text-sm font-semibold text-dashboard-text">
|
|
45
|
+
{event.data.type}
|
|
46
|
+
</h2>
|
|
47
|
+
{timestamp}
|
|
48
|
+
</>
|
|
49
|
+
) : (
|
|
50
|
+
<div className="grid gap-2 py-0.5">
|
|
51
|
+
<Skeleton className="h-3.5 w-28" />
|
|
52
|
+
<Skeleton className="h-3 w-40" />
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
const actions =
|
|
56
|
+
onSelect && event ? (
|
|
57
|
+
<>
|
|
58
|
+
<Button
|
|
59
|
+
aria-label="Previous event"
|
|
60
|
+
className={stepButtonClass}
|
|
61
|
+
disabled={props.previous === undefined}
|
|
62
|
+
focusableWhenDisabled
|
|
63
|
+
onClick={() => {
|
|
64
|
+
if (props.previous !== undefined) onSelect(props.previous);
|
|
65
|
+
}}
|
|
66
|
+
size="icon"
|
|
67
|
+
title="Previous event"
|
|
68
|
+
>
|
|
69
|
+
<ChevronUp aria-hidden="true" size={15} />
|
|
70
|
+
</Button>
|
|
71
|
+
<Button
|
|
72
|
+
aria-label="Next event"
|
|
73
|
+
className={stepButtonClass}
|
|
74
|
+
disabled={props.next === undefined}
|
|
75
|
+
focusableWhenDisabled
|
|
76
|
+
onClick={() => {
|
|
77
|
+
if (props.next !== undefined) onSelect(props.next);
|
|
78
|
+
}}
|
|
79
|
+
size="icon"
|
|
80
|
+
title="Next event"
|
|
81
|
+
>
|
|
82
|
+
<ChevronDown aria-hidden="true" size={15} />
|
|
83
|
+
</Button>
|
|
84
|
+
</>
|
|
85
|
+
) : undefined;
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<DetailsPanel
|
|
89
|
+
actions={actions}
|
|
90
|
+
label="Event details"
|
|
91
|
+
onClose={props.onClose}
|
|
92
|
+
overlay={props.overlay}
|
|
93
|
+
sheetTitle={event?.data.type}
|
|
94
|
+
title={title}
|
|
95
|
+
>
|
|
96
|
+
{/* Own the scroll here, so a new event starts at the top with closed
|
|
97
|
+
disclosures, and the sheet actions stay below the content. */}
|
|
98
|
+
<div
|
|
99
|
+
className={cn(
|
|
100
|
+
"h-full min-w-0 overflow-y-auto overscroll-contain p-4 pb-[max(1rem,env(safe-area-inset-bottom))]",
|
|
101
|
+
props.overlay && "xl:p-0",
|
|
102
|
+
)}
|
|
103
|
+
key={event?.seq ?? "loading"}
|
|
104
|
+
>
|
|
105
|
+
{event && conversation ? (
|
|
106
|
+
<>
|
|
107
|
+
<div className="mb-4 xl:hidden">{timestamp}</div>
|
|
108
|
+
{conversation.canFork &&
|
|
109
|
+
event.data.type === "message" &&
|
|
110
|
+
event.data.role === "assistant" &&
|
|
111
|
+
!event.data.redacted ? (
|
|
112
|
+
<div className="mb-3 flex items-center gap-2 text-sm">
|
|
113
|
+
<ForkConversationButton
|
|
114
|
+
conversationId={conversation.conversationId}
|
|
115
|
+
messageId={event.data.messageId}
|
|
116
|
+
/>
|
|
117
|
+
<span>Fork after this reply</span>
|
|
118
|
+
</div>
|
|
119
|
+
) : null}
|
|
120
|
+
<EventDetails event={event} />
|
|
121
|
+
</>
|
|
122
|
+
) : (
|
|
123
|
+
<EventDetailsLoading />
|
|
124
|
+
)}
|
|
125
|
+
</div>
|
|
126
|
+
</DetailsPanel>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Keep the body quiet while the event loads. The header placeholders carry the
|
|
132
|
+
* state, so the panel does not compete with the log skeleton.
|
|
133
|
+
*/
|
|
134
|
+
function EventDetailsLoading() {
|
|
135
|
+
return (
|
|
136
|
+
<div aria-busy="true" role="status">
|
|
137
|
+
<span className="sr-only">Loading event</span>
|
|
138
|
+
<Skeleton className="h-3 w-40 xl:hidden" />
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|