@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,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
memo,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
useSyncExternalStore,
|
|
9
|
+
} from "react";
|
|
2
10
|
import { useSearchParams } from "react-router";
|
|
3
11
|
import type {
|
|
4
12
|
ConversationDetailReport,
|
|
@@ -18,7 +26,7 @@ import {
|
|
|
18
26
|
import { conversationIsResponding } from "./transcript";
|
|
19
27
|
import type { ConversationMailboxMessage } from "./conversationOutbox";
|
|
20
28
|
import { buildConversationMarkdown } from "../markdownExport";
|
|
21
|
-
import {
|
|
29
|
+
import { CopyButton } from "../components/CopyButton";
|
|
22
30
|
import { ConversationBrief } from "./ConversationBrief";
|
|
23
31
|
import {
|
|
24
32
|
CONVERSATION_EVENT_PARAM,
|
|
@@ -27,11 +35,24 @@ import {
|
|
|
27
35
|
import { ConversationComposer } from "./ConversationComposer";
|
|
28
36
|
import { ConversationHeader } from "./ConversationHeader";
|
|
29
37
|
import { ConversationDetails } from "./ConversationDetails";
|
|
30
|
-
import {
|
|
38
|
+
import { ConversationEventDetails } from "./ConversationEventDetails";
|
|
39
|
+
import { ConversationEventLogLoading } from "./ConversationEventLog";
|
|
40
|
+
import {
|
|
41
|
+
adjacentEventLogSeqs,
|
|
42
|
+
eventLogRows,
|
|
43
|
+
filterEventLogRows,
|
|
44
|
+
} from "./eventLog";
|
|
45
|
+
import { TranscriptSearchProvider } from "./transcriptSearch";
|
|
46
|
+
import {
|
|
47
|
+
TurnContextDetails,
|
|
48
|
+
type TurnContextPanel,
|
|
49
|
+
type TurnContextSelection,
|
|
50
|
+
} from "./TranscriptTurnContextView";
|
|
31
51
|
import { cn } from "../styles";
|
|
32
52
|
import { ConversationForkLinks } from "./ConversationForkLinks";
|
|
33
53
|
import { ConversationAgentTree } from "./ConversationAgentTree";
|
|
34
54
|
import { ConversationHeaderMeta } from "./ConversationHeaderMeta";
|
|
55
|
+
import { conversationLinks } from "./ConversationLinkedWork";
|
|
35
56
|
import {
|
|
36
57
|
ConversationAnnotations,
|
|
37
58
|
ConversationPrivacyChip,
|
|
@@ -75,6 +96,14 @@ import type {
|
|
|
75
96
|
|
|
76
97
|
export { liveModelId } from "./ConversationMeta";
|
|
77
98
|
|
|
99
|
+
const detailsDefaultOpenQuery = "(min-width: 1440px)";
|
|
100
|
+
|
|
101
|
+
function subscribeToDetailsLayout(onChange: () => void) {
|
|
102
|
+
const media = window.matchMedia(detailsDefaultOpenQuery);
|
|
103
|
+
media.addEventListener("change", onChange);
|
|
104
|
+
return () => media.removeEventListener("change", onChange);
|
|
105
|
+
}
|
|
106
|
+
|
|
78
107
|
/** Render the selected conversation transcript inside the workspace. */
|
|
79
108
|
export function ConversationPage(props: {
|
|
80
109
|
conversationId: string;
|
|
@@ -82,11 +111,12 @@ export function ConversationPage(props: {
|
|
|
82
111
|
onRead?(conversationId: string, lastReadAt: string): void;
|
|
83
112
|
pendingArchiveUpdate?: PendingArchiveConversationUpdate;
|
|
84
113
|
}) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
114
|
+
const detailsDefaultOpen = useSyncExternalStore(
|
|
115
|
+
subscribeToDetailsLayout,
|
|
116
|
+
() => window.matchMedia(detailsDefaultOpenQuery).matches,
|
|
117
|
+
() => false,
|
|
118
|
+
);
|
|
119
|
+
const pageRef = useRef<HTMLDivElement>(null);
|
|
90
120
|
const [subagentTarget, setSubagentTarget] =
|
|
91
121
|
useState<SubagentTranscriptTarget>();
|
|
92
122
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
@@ -94,6 +124,16 @@ export function ConversationPage(props: {
|
|
|
94
124
|
const selectedEventSeq = parseConversationEventSeq(
|
|
95
125
|
searchParams.get(CONVERSATION_EVENT_PARAM),
|
|
96
126
|
);
|
|
127
|
+
// Event details and turn context show over Conversation details. Closing
|
|
128
|
+
// them shows details again when details are open. A linked event starts
|
|
129
|
+
// with details closed, so closing it does not open a panel nobody chose.
|
|
130
|
+
const [detailsChoice, setDetailsChoice] = useState<boolean | undefined>(() =>
|
|
131
|
+
selectedEventSeq === undefined ? undefined : false,
|
|
132
|
+
);
|
|
133
|
+
const detailsOpen = detailsChoice ?? detailsDefaultOpen;
|
|
134
|
+
const [turnContext, setTurnContext] = useState<TurnContextSelection>();
|
|
135
|
+
const eventOpen = selectedEventSeq !== undefined;
|
|
136
|
+
const showDetails = detailsOpen && !eventOpen && !turnContext;
|
|
97
137
|
const [viewState, setView] = useState<TranscriptViewMode>(() =>
|
|
98
138
|
selectedEventSeq === undefined ? "rich" : "raw",
|
|
99
139
|
);
|
|
@@ -129,6 +169,10 @@ export function ConversationPage(props: {
|
|
|
129
169
|
onRead?.(conversation.id, conversation.lastSeenAt);
|
|
130
170
|
}, [conversation, onRead]);
|
|
131
171
|
const transcript = detail.data;
|
|
172
|
+
const selectedEvent =
|
|
173
|
+
transcript?.eventHistory.status === "expired"
|
|
174
|
+
? undefined
|
|
175
|
+
: transcript?.events.find((event) => event.seq === selectedEventSeq);
|
|
132
176
|
const visualStatus = conversation
|
|
133
177
|
? visualStatusForConversation(conversation)
|
|
134
178
|
: undefined;
|
|
@@ -165,6 +209,8 @@ export function ConversationPage(props: {
|
|
|
165
209
|
if (value !== "raw" && selectedEventSeq !== undefined) {
|
|
166
210
|
setSelectedEventSeq(undefined);
|
|
167
211
|
}
|
|
212
|
+
// Turn context belongs to a message in the Conversation view.
|
|
213
|
+
setTurnContext(undefined);
|
|
168
214
|
setView(value);
|
|
169
215
|
},
|
|
170
216
|
[selectedEventSeq, setSelectedEventSeq],
|
|
@@ -186,6 +232,35 @@ export function ConversationPage(props: {
|
|
|
186
232
|
useEffect(() => {
|
|
187
233
|
if (loadLinkedEvent) loadPreviousPageRef.current();
|
|
188
234
|
}, [loadLinkedEvent, oldestLoadedSeq]);
|
|
235
|
+
// Keep the panel while the transcript or a linked event loads.
|
|
236
|
+
const eventLoading =
|
|
237
|
+
eventOpen &&
|
|
238
|
+
!selectedEvent &&
|
|
239
|
+
(detail.isPending ||
|
|
240
|
+
(linkedEventMissing &&
|
|
241
|
+
(detail.hasPreviousPage || detail.isLoadingPreviousPage) &&
|
|
242
|
+
!detail.historyError));
|
|
243
|
+
const showEvent = Boolean(selectedEvent) || eventLoading;
|
|
244
|
+
// Step through the same filtered rows that the event log shows.
|
|
245
|
+
const events = transcript?.events;
|
|
246
|
+
const normalizedSearch = search.trim().toLowerCase();
|
|
247
|
+
const eventRows = useMemo(
|
|
248
|
+
() =>
|
|
249
|
+
eventOpen && events
|
|
250
|
+
? filterEventLogRows(eventLogRows(events), normalizedSearch)
|
|
251
|
+
: [],
|
|
252
|
+
[eventOpen, events, normalizedSearch],
|
|
253
|
+
);
|
|
254
|
+
const turnContextPanel = useMemo<TurnContextPanel>(
|
|
255
|
+
() => ({
|
|
256
|
+
openId: turnContext?.id,
|
|
257
|
+
onToggle: (selection) =>
|
|
258
|
+
setTurnContext((current) =>
|
|
259
|
+
current?.id === selection.id ? undefined : selection,
|
|
260
|
+
),
|
|
261
|
+
}),
|
|
262
|
+
[turnContext?.id],
|
|
263
|
+
);
|
|
189
264
|
const requestPin = useCallback(() => {
|
|
190
265
|
setPinRequestVersion((version) => version + 1);
|
|
191
266
|
}, []);
|
|
@@ -206,111 +281,139 @@ export function ConversationPage(props: {
|
|
|
206
281
|
[],
|
|
207
282
|
);
|
|
208
283
|
|
|
284
|
+
const closeEventDetails = () => {
|
|
285
|
+
const trigger = pageRef.current?.querySelector<HTMLButtonElement>(
|
|
286
|
+
`[data-event-seq="${selectedEventSeq}"] button`,
|
|
287
|
+
);
|
|
288
|
+
setSelectedEventSeq(undefined);
|
|
289
|
+
trigger?.focus({ preventScroll: true });
|
|
290
|
+
};
|
|
291
|
+
const closeTurnContext = () => {
|
|
292
|
+
// A message can have one context control per layout. Focus the visible one.
|
|
293
|
+
const trigger = [
|
|
294
|
+
...(pageRef.current?.querySelectorAll<HTMLButtonElement>(
|
|
295
|
+
`[data-turn-context-id="${CSS.escape(turnContext?.id ?? "")}"]`,
|
|
296
|
+
) ?? []),
|
|
297
|
+
].find((button) => button.getClientRects().length > 0);
|
|
298
|
+
setTurnContext(undefined);
|
|
299
|
+
trigger?.focus({ preventScroll: true });
|
|
300
|
+
};
|
|
301
|
+
|
|
209
302
|
return (
|
|
210
303
|
<div
|
|
304
|
+
ref={pageRef}
|
|
211
305
|
className={cn(
|
|
212
306
|
"grid h-full min-h-0 min-w-0",
|
|
213
|
-
|
|
307
|
+
(showDetails || showEvent || turnContext) &&
|
|
308
|
+
"xl:grid-cols-[minmax(0,1fr)_25rem]",
|
|
214
309
|
)}
|
|
215
310
|
>
|
|
216
311
|
<ChatLayout
|
|
312
|
+
header={
|
|
313
|
+
<ConversationHeader
|
|
314
|
+
agentTree={
|
|
315
|
+
agentTree ? <ConversationAgentTree nodes={agentTree} /> : null
|
|
316
|
+
}
|
|
317
|
+
conversationId={conversationId}
|
|
318
|
+
detailsOpen={showDetails}
|
|
319
|
+
onDetailsClick={() => {
|
|
320
|
+
if (eventOpen) setSelectedEventSeq(undefined);
|
|
321
|
+
setTurnContext(undefined);
|
|
322
|
+
setDetailsChoice(!showDetails);
|
|
323
|
+
}}
|
|
324
|
+
forks={
|
|
325
|
+
detail.data?.forkedFromConversationId ||
|
|
326
|
+
detail.data?.forks?.length ? (
|
|
327
|
+
<ConversationForkLinks
|
|
328
|
+
forkedFromConversationId={
|
|
329
|
+
detail.data.forkedFromConversationId
|
|
330
|
+
}
|
|
331
|
+
forkedFromTitle={detail.data.forkedFromTitle}
|
|
332
|
+
forks={detail.data.forks}
|
|
333
|
+
/>
|
|
334
|
+
) : null
|
|
335
|
+
}
|
|
336
|
+
copyAction={
|
|
337
|
+
<CopyButton
|
|
338
|
+
label="Copy as Markdown"
|
|
339
|
+
copyingLabel="Preparing Markdown"
|
|
340
|
+
key={conversationDetail?.conversationId ?? "loading"}
|
|
341
|
+
getText={
|
|
342
|
+
conversationDetail
|
|
343
|
+
? async () =>
|
|
344
|
+
buildConversationMarkdown(
|
|
345
|
+
await detail.loadCompleteTranscript(),
|
|
346
|
+
conversation,
|
|
347
|
+
)
|
|
348
|
+
: undefined
|
|
349
|
+
}
|
|
350
|
+
/>
|
|
351
|
+
}
|
|
352
|
+
linkedWork={
|
|
353
|
+
hasConversationAnnotations(detail.data?.annotations) ? (
|
|
354
|
+
<ConversationAnnotations detail={detail.data} />
|
|
355
|
+
) : null
|
|
356
|
+
}
|
|
357
|
+
archive={{
|
|
358
|
+
archived: Boolean(conversation?.archivedAt),
|
|
359
|
+
disabled: !conversation || archive.isPending,
|
|
360
|
+
error: Boolean(archive.error),
|
|
361
|
+
onClick: () =>
|
|
362
|
+
archive.mutate({
|
|
363
|
+
archived: !conversation?.archivedAt,
|
|
364
|
+
lastSeenAt: conversation!.lastSeenAt,
|
|
365
|
+
}),
|
|
366
|
+
pending: archive.isPending,
|
|
367
|
+
}}
|
|
368
|
+
live={live}
|
|
369
|
+
meta={
|
|
370
|
+
<ConversationHeaderMeta
|
|
371
|
+
identity={identity}
|
|
372
|
+
stats={
|
|
373
|
+
hasConversationStats({
|
|
374
|
+
conversation,
|
|
375
|
+
detail: detail.data,
|
|
376
|
+
variant: "compact",
|
|
377
|
+
}) ? (
|
|
378
|
+
<ConversationStats
|
|
379
|
+
conversation={conversation}
|
|
380
|
+
detail={detail.data}
|
|
381
|
+
variant="compact"
|
|
382
|
+
/>
|
|
383
|
+
) : null
|
|
384
|
+
}
|
|
385
|
+
/>
|
|
386
|
+
}
|
|
387
|
+
onSearchChange={setSearch}
|
|
388
|
+
onViewChange={onViewChange}
|
|
389
|
+
privacy={
|
|
390
|
+
<ConversationPrivacyChip visibility={conversation?.visibility} />
|
|
391
|
+
}
|
|
392
|
+
search={search}
|
|
393
|
+
title={title}
|
|
394
|
+
view={view}
|
|
395
|
+
/>
|
|
396
|
+
}
|
|
217
397
|
scrollMinTall
|
|
218
398
|
scrollAriaLabel="Conversation transcript"
|
|
219
|
-
scrollClassName=
|
|
399
|
+
scrollClassName={
|
|
400
|
+
view === "raw" ? undefined : "px-4 pb-4 md:px-7 md:pb-6"
|
|
401
|
+
}
|
|
220
402
|
scroll={
|
|
221
403
|
<section className="min-w-0">
|
|
222
|
-
<ConversationHeader
|
|
223
|
-
agentTree={
|
|
224
|
-
agentTree ? <ConversationAgentTree nodes={agentTree} /> : null
|
|
225
|
-
}
|
|
226
|
-
conversationId={conversationId}
|
|
227
|
-
detailsOpen={detailsOpen}
|
|
228
|
-
onDetailsClick={() => setDetailsChoice(!detailsOpen)}
|
|
229
|
-
forks={
|
|
230
|
-
detail.data?.forkedFromConversationId ||
|
|
231
|
-
detail.data?.forks?.length ? (
|
|
232
|
-
<ConversationForkLinks
|
|
233
|
-
forkedFromConversationId={
|
|
234
|
-
detail.data.forkedFromConversationId
|
|
235
|
-
}
|
|
236
|
-
forkedFromTitle={detail.data.forkedFromTitle}
|
|
237
|
-
forks={detail.data.forks}
|
|
238
|
-
/>
|
|
239
|
-
) : null
|
|
240
|
-
}
|
|
241
|
-
copyAction={
|
|
242
|
-
<CopyMarkdownButton
|
|
243
|
-
key={conversationDetail?.conversationId ?? "loading"}
|
|
244
|
-
getMarkdown={
|
|
245
|
-
conversationDetail
|
|
246
|
-
? async () =>
|
|
247
|
-
buildConversationMarkdown(
|
|
248
|
-
await detail.loadCompleteTranscript(),
|
|
249
|
-
conversation,
|
|
250
|
-
)
|
|
251
|
-
: undefined
|
|
252
|
-
}
|
|
253
|
-
/>
|
|
254
|
-
}
|
|
255
|
-
linkedWork={
|
|
256
|
-
hasConversationAnnotations(detail.data?.annotations) ? (
|
|
257
|
-
<ConversationAnnotations
|
|
258
|
-
detail={detail.data}
|
|
259
|
-
layout="strip"
|
|
260
|
-
/>
|
|
261
|
-
) : null
|
|
262
|
-
}
|
|
263
|
-
archive={{
|
|
264
|
-
archived: Boolean(conversation?.archivedAt),
|
|
265
|
-
disabled: !conversation || archive.isPending,
|
|
266
|
-
error: Boolean(archive.error),
|
|
267
|
-
onClick: () =>
|
|
268
|
-
archive.mutate({
|
|
269
|
-
archived: !conversation?.archivedAt,
|
|
270
|
-
lastSeenAt: conversation!.lastSeenAt,
|
|
271
|
-
}),
|
|
272
|
-
pending: archive.isPending,
|
|
273
|
-
}}
|
|
274
|
-
live={live}
|
|
275
|
-
meta={
|
|
276
|
-
<ConversationHeaderMeta
|
|
277
|
-
identity={identity}
|
|
278
|
-
stats={
|
|
279
|
-
hasConversationStats({
|
|
280
|
-
conversation,
|
|
281
|
-
detail: detail.data,
|
|
282
|
-
variant: "compact",
|
|
283
|
-
}) ? (
|
|
284
|
-
<ConversationStats
|
|
285
|
-
conversation={conversation}
|
|
286
|
-
detail={detail.data}
|
|
287
|
-
variant="compact"
|
|
288
|
-
/>
|
|
289
|
-
) : null
|
|
290
|
-
}
|
|
291
|
-
/>
|
|
292
|
-
}
|
|
293
|
-
onSearchChange={setSearch}
|
|
294
|
-
onViewChange={onViewChange}
|
|
295
|
-
privacy={
|
|
296
|
-
<ConversationPrivacyChip
|
|
297
|
-
visibility={conversation?.visibility}
|
|
298
|
-
/>
|
|
299
|
-
}
|
|
300
|
-
search={search}
|
|
301
|
-
title={title}
|
|
302
|
-
view={view}
|
|
303
|
-
/>
|
|
304
|
-
|
|
305
404
|
<div
|
|
306
405
|
className={
|
|
307
406
|
view === "raw"
|
|
308
|
-
? "w-full
|
|
407
|
+
? "w-full"
|
|
309
408
|
: "mx-auto w-full max-w-[52.5rem] pt-5 md:pt-7"
|
|
310
409
|
}
|
|
311
410
|
>
|
|
312
411
|
{detail.isPending ? (
|
|
313
|
-
|
|
412
|
+
view === "raw" ? (
|
|
413
|
+
<ConversationEventLogLoading />
|
|
414
|
+
) : (
|
|
415
|
+
<TranscriptLoading />
|
|
416
|
+
)
|
|
314
417
|
) : detail.error && !detail.data ? (
|
|
315
418
|
<Card className="border-dashboard-border bg-dashboard-fill-soft p-4 font-sans text-xs leading-relaxed text-dashboard-text-muted">
|
|
316
419
|
{detail.error.message}
|
|
@@ -337,8 +440,10 @@ export function ConversationPage(props: {
|
|
|
337
440
|
}
|
|
338
441
|
onOpenSubagentTranscript={onOpenSubagentTranscript}
|
|
339
442
|
search={search}
|
|
443
|
+
onSearchChange={setSearch}
|
|
340
444
|
selectedEventSeq={selectedEventSeq}
|
|
341
445
|
transcript={transcript}
|
|
446
|
+
turnContextPanel={turnContextPanel}
|
|
342
447
|
view={view}
|
|
343
448
|
/>
|
|
344
449
|
</>
|
|
@@ -366,18 +471,14 @@ export function ConversationPage(props: {
|
|
|
366
471
|
) : undefined
|
|
367
472
|
}
|
|
368
473
|
/>
|
|
369
|
-
{
|
|
474
|
+
{showDetails ? (
|
|
370
475
|
<ConversationDetails
|
|
371
476
|
conversationId={conversationId}
|
|
372
477
|
identity={identity}
|
|
373
478
|
sentryConversationUrl={detail.data?.sentryConversationUrl}
|
|
374
479
|
onClose={() => setDetailsChoice(false)}
|
|
375
480
|
onOpenSubagent={setSubagentTarget}
|
|
376
|
-
|
|
377
|
-
hasConversationAnnotations(detail.data?.annotations) ? (
|
|
378
|
-
<ConversationAnnotations detail={detail.data} />
|
|
379
|
-
) : null
|
|
380
|
-
}
|
|
481
|
+
links={conversationLinks(detail.data)}
|
|
381
482
|
brief={
|
|
382
483
|
detail.data?.brief ? (
|
|
383
484
|
<ConversationBrief brief={detail.data.brief} variant="summary" />
|
|
@@ -407,6 +508,24 @@ export function ConversationPage(props: {
|
|
|
407
508
|
}
|
|
408
509
|
/>
|
|
409
510
|
) : null}
|
|
511
|
+
{showEvent ? (
|
|
512
|
+
<ConversationEventDetails
|
|
513
|
+
conversation={transcript}
|
|
514
|
+
event={selectedEvent}
|
|
515
|
+
onClose={closeEventDetails}
|
|
516
|
+
onSelect={setSelectedEventSeq}
|
|
517
|
+
{...adjacentEventLogSeqs(eventRows, selectedEventSeq)}
|
|
518
|
+
/>
|
|
519
|
+
) : null}
|
|
520
|
+
{turnContext ? (
|
|
521
|
+
<TranscriptSearchProvider query={search}>
|
|
522
|
+
<TurnContextDetails
|
|
523
|
+
contexts={turnContext.contexts}
|
|
524
|
+
key={turnContext.id}
|
|
525
|
+
onClose={closeTurnContext}
|
|
526
|
+
/>
|
|
527
|
+
</TranscriptSearchProvider>
|
|
528
|
+
) : null}
|
|
410
529
|
<SubagentTranscriptDrawer
|
|
411
530
|
onClose={() => setSubagentTarget(undefined)}
|
|
412
531
|
target={subagentTarget}
|
|
@@ -19,7 +19,13 @@ import {
|
|
|
19
19
|
} from "./conversationSections";
|
|
20
20
|
import { EmptyTelemetry } from "../components/EmptyTelemetry";
|
|
21
21
|
import { SearchInput } from "../components/SearchInput";
|
|
22
|
-
import {
|
|
22
|
+
import { Button } from "../components/ui/button";
|
|
23
|
+
import { Skeleton } from "../components/ui/skeleton";
|
|
24
|
+
import {
|
|
25
|
+
Tooltip,
|
|
26
|
+
TooltipContent,
|
|
27
|
+
TooltipTrigger,
|
|
28
|
+
} from "../components/ui/tooltip";
|
|
23
29
|
import { ConversationSidebarAnnotations } from "./ConversationMeta";
|
|
24
30
|
import { ConversationListStatusIcon } from "./ConversationListStatusIcon";
|
|
25
31
|
|
|
@@ -104,15 +110,21 @@ export function ConversationSidebar(props: {
|
|
|
104
110
|
</h2>
|
|
105
111
|
<div className="flex items-center gap-0.5">
|
|
106
112
|
{isLanding ? null : (
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
<Tooltip>
|
|
114
|
+
<TooltipTrigger
|
|
115
|
+
render={
|
|
116
|
+
<Button
|
|
117
|
+
aria-label="New conversation"
|
|
118
|
+
className="size-7"
|
|
119
|
+
onClick={props.onNewConversation}
|
|
120
|
+
size="icon"
|
|
121
|
+
>
|
|
122
|
+
<SquarePen aria-hidden="true" size={15} />
|
|
123
|
+
</Button>
|
|
124
|
+
}
|
|
125
|
+
/>
|
|
126
|
+
<TooltipContent size="compact">New conversation</TooltipContent>
|
|
127
|
+
</Tooltip>
|
|
116
128
|
)}
|
|
117
129
|
</div>
|
|
118
130
|
</div>
|
|
@@ -321,25 +333,33 @@ const ConversationSidebarRow = memo(function ConversationSidebarRow(props: {
|
|
|
321
333
|
) : null}
|
|
322
334
|
</div>
|
|
323
335
|
</Link>
|
|
324
|
-
<
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
336
|
+
<Tooltip>
|
|
337
|
+
<TooltipTrigger
|
|
338
|
+
render={
|
|
339
|
+
<button
|
|
340
|
+
aria-label={`${props.conversation.archivedAt ? "Restore" : "Archive"} ${title}`}
|
|
341
|
+
className="absolute right-1.5 top-1/2 z-10 grid size-7 -translate-y-1/2 cursor-pointer place-items-center rounded-md bg-dashboard-surface-active text-dashboard-text-muted transition hover:text-dashboard-text focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-dashboard-focus sm:pointer-events-none sm:opacity-0 sm:focus:pointer-events-auto sm:focus:opacity-100 sm:group-focus-within:pointer-events-auto sm:group-focus-within:opacity-100 sm:group-hover:pointer-events-auto sm:group-hover:opacity-100 disabled:cursor-not-allowed"
|
|
342
|
+
disabled={archive.isPending}
|
|
343
|
+
onClick={() =>
|
|
344
|
+
archive.mutate({
|
|
345
|
+
archived: !props.conversation.archivedAt,
|
|
346
|
+
lastSeenAt: props.conversation.lastSeenAt,
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
type="button"
|
|
350
|
+
>
|
|
351
|
+
{props.conversation.archivedAt ? (
|
|
352
|
+
<ArchiveRestore aria-hidden="true" size={14} />
|
|
353
|
+
) : (
|
|
354
|
+
<Archive aria-hidden="true" size={14} />
|
|
355
|
+
)}
|
|
356
|
+
</button>
|
|
357
|
+
}
|
|
358
|
+
/>
|
|
359
|
+
<TooltipContent size="compact">
|
|
360
|
+
{props.conversation.archivedAt ? "Restore" : "Archive"}
|
|
361
|
+
</TooltipContent>
|
|
362
|
+
</Tooltip>
|
|
343
363
|
</div>
|
|
344
364
|
);
|
|
345
365
|
});
|