@sentry/junior-dashboard 0.264.0 → 0.265.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/BottomSheet.tsx +12 -2
- package/src/client/components/CopyButton.tsx +83 -0
- package/src/client/components/DetailsPanel.tsx +133 -0
- package/src/client/components/Drawer.tsx +15 -24
- package/src/client/components/FilterBar.tsx +16 -31
- package/src/client/components/Metric.tsx +33 -23
- package/src/client/components/PageContentSkeleton.tsx +1 -1
- package/src/client/components/Pagination.tsx +1 -1
- package/src/client/components/ParticipantAvatarStack.tsx +40 -36
- package/src/client/components/ProfileMenu.tsx +27 -93
- package/src/client/components/README.md +86 -77
- 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/charts/ActivityChart.tsx +173 -288
- package/src/client/components/charts/CacheWrites.tsx +63 -50
- 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/button.tsx +85 -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/field.tsx +49 -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/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/table.tsx +80 -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/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 +8 -3
- package/src/client/conversations/ConversationHeaderActions.tsx +90 -82
- 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 +48 -29
- package/src/client/conversations/ConversationWatches.tsx +165 -0
- package/src/client/conversations/ConversationWorkspace.tsx +12 -22
- package/src/client/conversations/ConversationWorkspaceLoading.tsx +1 -1
- package/src/client/conversations/DetailsList.tsx +124 -0
- package/src/client/conversations/EventDetails.tsx +42 -8
- package/src/client/conversations/ForkConversationButton.tsx +27 -16
- package/src/client/conversations/ObjectCard.tsx +20 -8
- package/src/client/conversations/PendingMailboxStack.tsx +52 -33
- package/src/client/conversations/README.md +86 -13
- package/src/client/conversations/ShareConversationButton.tsx +25 -13
- 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/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 +8 -2
- package/src/client/conversations/TranscriptMessageView.tsx +6 -1
- package/src/client/conversations/TranscriptReasoningView.tsx +54 -68
- package/src/client/conversations/TranscriptTimestamp.tsx +9 -7
- package/src/client/conversations/TranscriptToolView.tsx +1 -1
- package/src/client/conversations/TranscriptTurnContextView.tsx +99 -27
- package/src/client/conversations/TranscriptView.tsx +63 -27
- package/src/client/conversations/eventLog.ts +57 -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/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
|
@@ -18,7 +18,8 @@ shared controls and overlays.
|
|
|
18
18
|
The caller owns the native `details` element and its content.
|
|
19
19
|
- Activity rows (tools, reasoning, and grouped rail events) share one
|
|
20
20
|
layout: a 1rem icon column, an 8px gap, then the title and metadata.
|
|
21
|
-
|
|
21
|
+
Tool and reasoning rows use `ui/trace`. Transcript search forces them open.
|
|
22
|
+
Expanded content sits in `TraceCollapsibleContent` under the title.
|
|
22
23
|
`TranscriptActivityNesting` tells a rail event that it is inside an activity
|
|
23
24
|
group. Outside a group, the rail icon sits in the avatar column so the text
|
|
24
25
|
lines up with message text.
|
|
@@ -40,23 +41,46 @@ shared controls and overlays.
|
|
|
40
41
|
Automation. Render this text with `TranscriptText` or `MentionText`. Both
|
|
41
42
|
require `mentions`, so a caller cannot forget them. Do not resolve names in
|
|
42
43
|
the dashboard, and do not rewrite tokens into links on the server.
|
|
43
|
-
- `TranscriptTurnContextView` owns context content.
|
|
44
|
-
|
|
44
|
+
- `TranscriptTurnContextView` owns context content. A transcript with a
|
|
45
|
+
`turnContextPanel` shows the context in the page panel. See "Page panel".
|
|
46
|
+
Other transcripts, such as a subagent drawer, open a modal `Drawer`. Each
|
|
47
|
+
`Transcript` sets the panel for its own rows, so a nested transcript does not
|
|
48
|
+
use the panel of the page behind it. The panel keys context by message id,
|
|
49
|
+
so every control for one message shows the same open state.
|
|
45
50
|
|
|
46
|
-
Review these components together
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
browser tests cover opening, closing, and keyboard interaction.
|
|
51
|
+
Review these components together on the mock Conversations. Run
|
|
52
|
+
`JUNIOR_DASHBOARD_MOCK_CONVERSATIONS=true pnpm dev` for messages, events,
|
|
53
|
+
activity, context, typing, and attachments. Keep visual checks out of automated
|
|
54
|
+
assertions; browser tests cover opening, closing, and keyboard interaction.
|
|
50
55
|
|
|
51
56
|
## Conversation details
|
|
52
57
|
|
|
53
|
-
`ConversationPage` owns whether details are open.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
`ConversationPage` owns whether details are open. At 1440px and above, details
|
|
59
|
+
open by default. An explicit choice lasts for the current Conversation. The page
|
|
60
|
+
is keyed by the Conversation, so switching Conversations resets that choice.
|
|
61
|
+
`ConversationHeader` toggles details and restores focus through explicit control
|
|
62
|
+
refs after dismissal.
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
## Page panel
|
|
65
|
+
|
|
66
|
+
The Conversation page has one panel on the right. It shows Conversation
|
|
67
|
+
details, event details, or turn context. Only one shows at a time. Each uses
|
|
68
|
+
`DetailsPanel`: a 400px aside at 1280px and above, and a `BottomSheet` below.
|
|
69
|
+
|
|
70
|
+
- Event details and turn context show in place of Conversation details.
|
|
71
|
+
- When you close them, Conversation details show again if they are open. The
|
|
72
|
+
details stay open by choice or by the 1440px default.
|
|
73
|
+
- A link that opens an event sets details to closed. When you close that
|
|
74
|
+
event, no panel shows.
|
|
75
|
+
- The details control closes event details and turn context, then shows or
|
|
76
|
+
hides Conversation details.
|
|
77
|
+
- Turn context belongs to the Conversation view. A view change closes it.
|
|
78
|
+
Select the same context control again to close it.
|
|
79
|
+
- Closing a panel returns focus to the row or control that opened it.
|
|
80
|
+
|
|
81
|
+
`ConversationDetails` owns one set of tabs and content. It supplies its title and
|
|
82
|
+
actions to `DetailsPanel`, which uses a 400px aside at 1280px and above. The chat
|
|
83
|
+
and aside scroll separately.
|
|
60
84
|
Smaller windows use `BottomSheet` with a visible title and close control. The sheet and
|
|
61
85
|
side drawers use the shadcn Base UI `Sheet` and share the app's document
|
|
62
86
|
scroll lock. A resize changes the frame and keeps the selected tab. Tabs stay
|
|
@@ -64,3 +88,52 @@ fixed above the scrolling content in both layouts. The sheet title and close con
|
|
|
64
88
|
control, tap the backdrop, or press Escape to dismiss it. Base UI owns the
|
|
65
89
|
transition lifecycle.
|
|
66
90
|
A pending exit cannot close a new panel or a different Conversation.
|
|
91
|
+
|
|
92
|
+
## Event log
|
|
93
|
+
|
|
94
|
+
`ChatLayout` keeps the Conversation header outside the transcript scroll region.
|
|
95
|
+
`ConversationEventLog` fills the pane without a card border or page inset. Its
|
|
96
|
+
search toolbar and column labels stay together at the top while rows scroll.
|
|
97
|
+
`Transcript` shares the search value with its owner, or keeps it locally when
|
|
98
|
+
used alone. Event log search stays visible; the transcript search toggle is for
|
|
99
|
+
the Conversation view.
|
|
100
|
+
|
|
101
|
+
Rows keep time, event type, and summary in columns when the pane is at least
|
|
102
|
+
512px wide. Smaller panes put the summary below time and type. Model and usage
|
|
103
|
+
metadata share one optional line. Missing model metadata is omitted from rows.
|
|
104
|
+
Selected rows have a background and an accent edge. Up and Down select the
|
|
105
|
+
previous or next visible row while a row has focus. Selection stops at the
|
|
106
|
+
ends of the filtered list. The selected row stays clear of the fixed toolbar.
|
|
107
|
+
`eventLogRows` and `filterEventLogRows` own the row text and search match.
|
|
108
|
+
The page uses them too, so its step controls follow the same rows.
|
|
109
|
+
|
|
110
|
+
The timezone toggle uses `useEventTime` to share a UTC/local preference through
|
|
111
|
+
`@uidotdev/usehooks` and browser local storage. It applies to event row clocks
|
|
112
|
+
and detail timestamps. Local mode follows the browser timezone. The button uses
|
|
113
|
+
a generic zone name because a log can span standard and daylight-saving time.
|
|
114
|
+
Detail timestamps use the zone name for each event date. The mode, not
|
|
115
|
+
the timezone identifier, persists across visits and tabs. This hook belongs to
|
|
116
|
+
the client-rendered event viewer. Raw JSON retains the original ISO values.
|
|
117
|
+
|
|
118
|
+
## Event details
|
|
119
|
+
|
|
120
|
+
The URL owns the selected event in the main Conversation. `ConversationPage`
|
|
121
|
+
places `ConversationEventDetails` beside the log in the page panel. Selecting
|
|
122
|
+
another row changes the event and resets its scroll position and disclosures.
|
|
123
|
+
Closing returns focus to that row. Switching Conversations removes the panel.
|
|
124
|
+
|
|
125
|
+
The previous and next controls select the adjacent visible row. They follow
|
|
126
|
+
the event search, like Up and Down. They are necessary below 1280px, where the
|
|
127
|
+
sheet covers the log. At the ends of the list, the control is disabled but
|
|
128
|
+
keeps focus. The sheet title is the event type.
|
|
129
|
+
|
|
130
|
+
A linked event can be older than the loaded pages. While the event loads, the
|
|
131
|
+
panel stays open. Only its header shows placeholders, so it does not compete
|
|
132
|
+
with the log. While the transcript loads, `ConversationEventLogLoading` shows
|
|
133
|
+
the log toolbar, columns, and row skeletons in the event log view.
|
|
134
|
+
|
|
135
|
+
Standalone transcripts, such as a subagent drawer, keep selection in
|
|
136
|
+
`ConversationEventLog`. Their event details use a nested drawer on desktop and
|
|
137
|
+
`BottomSheet` on smaller screens. This keeps the main log free of modal behavior
|
|
138
|
+
while a nested transcript retains its parent drawer's focus rules. These event
|
|
139
|
+
details have the same previous and next controls.
|
|
@@ -2,8 +2,12 @@ import { useState } from "react";
|
|
|
2
2
|
import { useHref } from "react-router";
|
|
3
3
|
import { Check, Share2 } from "lucide-react";
|
|
4
4
|
|
|
5
|
-
import { Button } from "../components/
|
|
6
|
-
import {
|
|
5
|
+
import { Button } from "../components/ui/button";
|
|
6
|
+
import {
|
|
7
|
+
Tooltip,
|
|
8
|
+
TooltipContent,
|
|
9
|
+
TooltipTrigger,
|
|
10
|
+
} from "../components/ui/tooltip";
|
|
7
11
|
import { conversationPath } from "./conversationRoutes";
|
|
8
12
|
|
|
9
13
|
/** Share a conversation link without changing who can access it. */
|
|
@@ -72,17 +76,25 @@ export function ShareConversationButton(props: {
|
|
|
72
76
|
);
|
|
73
77
|
const button =
|
|
74
78
|
props.layout === "icon" ? (
|
|
75
|
-
<
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
<Tooltip>
|
|
80
|
+
<TooltipTrigger
|
|
81
|
+
render={
|
|
82
|
+
<Button
|
|
83
|
+
focusableWhenDisabled
|
|
84
|
+
aria-label={label}
|
|
85
|
+
className="text-dashboard-text-muted"
|
|
86
|
+
disabled={status === "sharing"}
|
|
87
|
+
onClick={() => void shareLink()}
|
|
88
|
+
size="icon"
|
|
89
|
+
>
|
|
90
|
+
<Icon aria-hidden="true" size={15} />
|
|
91
|
+
</Button>
|
|
92
|
+
}
|
|
93
|
+
/>
|
|
94
|
+
<TooltipContent size="compact" side="bottom">
|
|
95
|
+
{label}
|
|
96
|
+
</TooltipContent>
|
|
97
|
+
</Tooltip>
|
|
86
98
|
) : props.layout === "menu" ? (
|
|
87
99
|
<button
|
|
88
100
|
aria-label={label}
|
|
@@ -14,7 +14,7 @@ import { Drawer } from "../components/Drawer";
|
|
|
14
14
|
import { SearchInput } from "../components/SearchInput";
|
|
15
15
|
import { StatusChip } from "../components/StatusChip";
|
|
16
16
|
import { subagentStatusTone } from "./ConversationChildAgents";
|
|
17
|
-
import {
|
|
17
|
+
import { CopyButton } from "../components/CopyButton";
|
|
18
18
|
import {
|
|
19
19
|
TranscriptSearchToggle,
|
|
20
20
|
TranscriptViewToggle,
|
|
@@ -69,7 +69,8 @@ function SubagentTranscriptDrawerContent(props: {
|
|
|
69
69
|
? props.target.agentName
|
|
70
70
|
: undefined;
|
|
71
71
|
const startedAt = detail ? Date.parse(detail.startedAt) : undefined;
|
|
72
|
-
const searchOpenVisible =
|
|
72
|
+
const searchOpenVisible =
|
|
73
|
+
view === "rich" && (searchOpen || search.length > 0);
|
|
73
74
|
|
|
74
75
|
const titleId = "subagent-transcript-drawer-title";
|
|
75
76
|
|
|
@@ -77,21 +78,25 @@ function SubagentTranscriptDrawerContent(props: {
|
|
|
77
78
|
<Drawer
|
|
78
79
|
actions={
|
|
79
80
|
<>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
{view === "rich" ? (
|
|
82
|
+
<TranscriptSearchToggle
|
|
83
|
+
onClick={() => {
|
|
84
|
+
if (searchOpenVisible) {
|
|
85
|
+
setSearchOpen(false);
|
|
86
|
+
if (search.length > 0) setSearch("");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
setSearchOpen(true);
|
|
90
|
+
}}
|
|
91
|
+
open={searchOpenVisible}
|
|
92
|
+
/>
|
|
93
|
+
) : null}
|
|
91
94
|
<TranscriptViewToggle onChange={setView} value={view} />
|
|
92
|
-
<
|
|
95
|
+
<CopyButton
|
|
96
|
+
label="Copy as Markdown"
|
|
97
|
+
copyingLabel="Preparing Markdown"
|
|
93
98
|
key={props.target.conversationId}
|
|
94
|
-
|
|
99
|
+
getText={
|
|
95
100
|
detail
|
|
96
101
|
? async () =>
|
|
97
102
|
buildConversationMarkdown(
|
|
@@ -184,6 +189,7 @@ function SubagentTranscriptDrawerContent(props: {
|
|
|
184
189
|
loadingPreviousPage={query.isLoadingPreviousPage}
|
|
185
190
|
onLoadPreviousPage={query.loadPreviousPage}
|
|
186
191
|
search={search}
|
|
192
|
+
onSearchChange={setSearch}
|
|
187
193
|
transcript={detail}
|
|
188
194
|
view={view}
|
|
189
195
|
/>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { useState, type ReactNode } from "react";
|
|
2
2
|
import type { LucideIcon } from "lucide-react";
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
TraceCollapsible,
|
|
6
|
+
TraceCollapsibleContent,
|
|
7
|
+
TraceCollapsibleTrigger,
|
|
8
|
+
} from "../components/ui/trace";
|
|
4
9
|
import { cn } from "../styles";
|
|
5
10
|
import {
|
|
6
11
|
TranscriptHeadingMeta,
|
|
7
12
|
TranscriptHeadingRow,
|
|
8
13
|
} from "./TranscriptHeadingRow";
|
|
9
14
|
import { useTranscriptSearch } from "./transcriptSearch";
|
|
10
|
-
import { TranscriptSummary } from "./TranscriptSummary";
|
|
11
|
-
|
|
12
|
-
/** Frame expanded transcript activity content below its row title. */
|
|
13
|
-
export const transcriptActivityBodyClass =
|
|
14
|
-
"ml-6 mt-1.5 min-w-0 overflow-hidden rounded-md border border-dashboard-border-subtle bg-dashboard-surface-panel";
|
|
15
15
|
|
|
16
16
|
/** Render the shared expandable/non-expandable frame for transcript tools. */
|
|
17
17
|
export function ToolFrame(props: {
|
|
@@ -27,30 +27,22 @@ export function ToolFrame(props: {
|
|
|
27
27
|
const { active: searchActive } = useTranscriptSearch();
|
|
28
28
|
const [open, setOpen] = useState(false);
|
|
29
29
|
const metaText = props.meta.join(" · ");
|
|
30
|
-
const
|
|
31
|
-
|
|
30
|
+
const expandable = props.expandable ?? Boolean(props.children);
|
|
31
|
+
// Force-expand tool details during search so highlighted matches are visible.
|
|
32
|
+
const expanded = expandable && (searchActive || open);
|
|
32
33
|
const Icon = props.icon;
|
|
33
34
|
const row = (
|
|
34
35
|
<TranscriptHeadingRow
|
|
36
|
+
className="flex-1"
|
|
35
37
|
left={
|
|
36
38
|
<>
|
|
37
39
|
{props.signature}
|
|
38
|
-
{props.mobileSummaryMeta ? (
|
|
40
|
+
{props.mobileSummaryMeta && !expanded ? (
|
|
39
41
|
<>
|
|
40
|
-
<span
|
|
41
|
-
className={cn(
|
|
42
|
-
"hidden text-dashboard-text-muted max-md:inline",
|
|
43
|
-
!staticFrame && "max-md:group-open:hidden",
|
|
44
|
-
)}
|
|
45
|
-
>
|
|
42
|
+
<span className="hidden text-dashboard-text-muted max-md:inline">
|
|
46
43
|
·
|
|
47
44
|
</span>
|
|
48
|
-
<span
|
|
49
|
-
className={cn(
|
|
50
|
-
"hidden shrink-0 whitespace-nowrap text-dashboard-text-muted max-md:inline",
|
|
51
|
-
!staticFrame && "max-md:group-open:hidden",
|
|
52
|
-
)}
|
|
53
|
-
>
|
|
45
|
+
<span className="hidden shrink-0 whitespace-nowrap text-dashboard-text-muted max-md:inline">
|
|
54
46
|
{props.mobileSummaryMeta}
|
|
55
47
|
</span>
|
|
56
48
|
</>
|
|
@@ -59,7 +51,7 @@ export function ToolFrame(props: {
|
|
|
59
51
|
}
|
|
60
52
|
leftClassName={cn(
|
|
61
53
|
"gap-x-1 gap-y-0.5",
|
|
62
|
-
|
|
54
|
+
expandable && !expanded ? "flex-nowrap" : "flex-wrap",
|
|
63
55
|
)}
|
|
64
56
|
right={
|
|
65
57
|
metaText ? (
|
|
@@ -72,54 +64,46 @@ export function ToolFrame(props: {
|
|
|
72
64
|
/>
|
|
73
65
|
);
|
|
74
66
|
const header = Icon ? (
|
|
75
|
-
<
|
|
67
|
+
<span className="grid min-w-0 flex-1 grid-cols-[1rem_minmax(0,1fr)] items-center gap-2">
|
|
76
68
|
<Icon
|
|
77
69
|
aria-hidden="true"
|
|
78
70
|
className={cn("size-3.5 justify-self-center", props.iconClassName)}
|
|
79
71
|
strokeWidth={2}
|
|
80
72
|
/>
|
|
81
73
|
{row}
|
|
82
|
-
</
|
|
74
|
+
</span>
|
|
83
75
|
) : (
|
|
84
76
|
row
|
|
85
77
|
);
|
|
86
|
-
const mobileMeta =
|
|
87
|
-
metaText && props.children ? (
|
|
88
|
-
<div className="hidden min-w-0 break-words border-b border-dashboard-border-subtle px-2.5 py-1.5 font-sans text-xs tabular-nums leading-snug text-dashboard-text-muted max-md:block">
|
|
89
|
-
{metaText}
|
|
90
|
-
</div>
|
|
91
|
-
) : null;
|
|
92
78
|
|
|
93
|
-
|
|
94
|
-
<div className={transcriptActivityBodyClass}>
|
|
95
|
-
{mobileMeta}
|
|
96
|
-
{props.children}
|
|
97
|
-
</div>
|
|
98
|
-
) : null;
|
|
99
|
-
|
|
100
|
-
// Force-expand tool details during search so highlighted matches are visible.
|
|
101
|
-
if (staticFrame) {
|
|
79
|
+
if (!expandable) {
|
|
102
80
|
return (
|
|
103
|
-
<div className="min-w-0 max-w-full">
|
|
104
|
-
|
|
105
|
-
{header}
|
|
106
|
-
</div>
|
|
107
|
-
{body}
|
|
81
|
+
<div className="flex min-w-0 max-w-full py-1.5 font-mono text-xs leading-tight text-dashboard-text-muted">
|
|
82
|
+
{header}
|
|
108
83
|
</div>
|
|
109
84
|
);
|
|
110
85
|
}
|
|
111
86
|
|
|
112
87
|
return (
|
|
113
|
-
<
|
|
114
|
-
className="
|
|
115
|
-
open
|
|
116
|
-
|
|
88
|
+
<TraceCollapsible
|
|
89
|
+
className="max-w-full"
|
|
90
|
+
// Search holds rows open, so the row button is off until search ends.
|
|
91
|
+
disabled={searchActive}
|
|
92
|
+
open={expanded}
|
|
93
|
+
onOpenChange={setOpen}
|
|
117
94
|
>
|
|
118
|
-
<
|
|
95
|
+
<TraceCollapsibleTrigger className="-mx-2 w-auto font-mono text-xs leading-tight">
|
|
119
96
|
{header}
|
|
120
|
-
</
|
|
121
|
-
{/*
|
|
122
|
-
|
|
123
|
-
|
|
97
|
+
</TraceCollapsibleTrigger>
|
|
98
|
+
{/* The closed panel unmounts, so closed rows do not run Shiki. */}
|
|
99
|
+
<TraceCollapsibleContent>
|
|
100
|
+
{metaText ? (
|
|
101
|
+
<div className="hidden min-w-0 break-words border-b border-dashboard-border-subtle px-2.5 py-1.5 font-sans text-xs tabular-nums leading-snug text-dashboard-text-muted max-md:block">
|
|
102
|
+
{metaText}
|
|
103
|
+
</div>
|
|
104
|
+
) : null}
|
|
105
|
+
{props.children}
|
|
106
|
+
</TraceCollapsibleContent>
|
|
107
|
+
</TraceCollapsible>
|
|
124
108
|
);
|
|
125
109
|
}
|
|
@@ -2,7 +2,11 @@ import { Fragment, useState, type ReactNode } from "react";
|
|
|
2
2
|
import { ChevronRight } from "lucide-react";
|
|
3
3
|
|
|
4
4
|
import { ShimmerText } from "../components/ShimmerText";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Tooltip,
|
|
7
|
+
TooltipContent,
|
|
8
|
+
TooltipTrigger,
|
|
9
|
+
} from "../components/ui/tooltip";
|
|
6
10
|
import { formatMs } from "../format";
|
|
7
11
|
import type { RenderedTranscriptEntry } from "./transcriptRenderModel";
|
|
8
12
|
import { cn } from "../styles";
|
|
@@ -180,8 +184,12 @@ export function TranscriptActivityGroup(props: {
|
|
|
180
184
|
setUserOpen(!open);
|
|
181
185
|
}}
|
|
182
186
|
>
|
|
183
|
-
<Tooltip
|
|
184
|
-
<
|
|
187
|
+
<Tooltip>
|
|
188
|
+
<TooltipTrigger
|
|
189
|
+
render={
|
|
190
|
+
<span className="inline-flex min-w-0 max-w-full items-center gap-1" />
|
|
191
|
+
}
|
|
192
|
+
>
|
|
185
193
|
<span className="min-w-0 truncate group-open/activity-run:hidden">
|
|
186
194
|
<ShimmerText active={live}>{label}</ShimmerText>
|
|
187
195
|
</span>
|
|
@@ -193,7 +201,8 @@ export function TranscriptActivityGroup(props: {
|
|
|
193
201
|
className="size-3 shrink-0 opacity-55 transition-transform group-open/activity-run:rotate-90"
|
|
194
202
|
strokeWidth={2.2}
|
|
195
203
|
/>
|
|
196
|
-
</
|
|
204
|
+
</TooltipTrigger>
|
|
205
|
+
<TooltipContent>{summary}</TooltipContent>
|
|
197
206
|
</Tooltip>
|
|
198
207
|
</TranscriptSummary>
|
|
199
208
|
<TranscriptActivityNesting.Provider value>
|
|
@@ -2,7 +2,8 @@ import { ArrowRight, ChevronRight } from "lucide-react";
|
|
|
2
2
|
import { useId, useState } from "react";
|
|
3
3
|
import type { ConversationDetailReport } from "@sentry/junior/api/schema";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { buttonVariants } from "../components/ui/button";
|
|
6
|
+
import { Link } from "react-router";
|
|
6
7
|
import { ObjectIcon } from "../components/ObjectIcon";
|
|
7
8
|
import { automationPath, formatRelativeTime } from "../format";
|
|
8
9
|
import { messageRawText } from "./transcriptRenderModel";
|
|
@@ -70,13 +71,13 @@ export function TranscriptAutomationTriggerView(props: {
|
|
|
70
71
|
<HighlightText text={name} />
|
|
71
72
|
</span>
|
|
72
73
|
{automationId ? (
|
|
73
|
-
<
|
|
74
|
-
className="h-8 shrink-0 text-xs"
|
|
74
|
+
<Link
|
|
75
|
+
className={cn(buttonVariants(), "h-8 shrink-0 text-xs")}
|
|
75
76
|
to={automationPath(automationId)}
|
|
76
77
|
>
|
|
77
78
|
Open automation
|
|
78
79
|
<ArrowRight aria-hidden="true" size={14} />
|
|
79
|
-
</
|
|
80
|
+
</Link>
|
|
80
81
|
) : null}
|
|
81
82
|
</div>
|
|
82
83
|
{details.length > 0 ? (
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { ChevronRight } from "lucide-react";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Collapsible,
|
|
5
|
+
CollapsibleContent,
|
|
6
|
+
CollapsibleTrigger,
|
|
7
|
+
} from "../components/ui/collapsible";
|
|
8
|
+
import { dashboardDisclosureChevronClass } from "../styles";
|
|
1
9
|
import { formatCompactNumber, formatMessageTimestamp } from "../format";
|
|
2
10
|
import type { TranscriptViewContextEventPart } from "../types";
|
|
3
11
|
import { TranscriptText } from "./TranscriptText";
|
|
@@ -39,18 +47,24 @@ export function TranscriptContextEventView(props: {
|
|
|
39
47
|
: `Earlier context was summarized${compactionDetail}${compactionModel} before execution continued.`}
|
|
40
48
|
</div>
|
|
41
49
|
{event.summary ? (
|
|
42
|
-
<
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<TranscriptText
|
|
48
|
-
mentions={props.part.mentions ?? []}
|
|
49
|
-
role="system"
|
|
50
|
-
text={event.summary}
|
|
50
|
+
<Collapsible className="mt-2">
|
|
51
|
+
<CollapsibleTrigger className="group flex cursor-pointer select-none items-center gap-1 text-xs font-medium text-dashboard-text-muted focus-visible:outline-2 focus-visible:outline-dashboard-focus">
|
|
52
|
+
<ChevronRight
|
|
53
|
+
aria-hidden="true"
|
|
54
|
+
className={dashboardDisclosureChevronClass}
|
|
51
55
|
/>
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
Continuation summary
|
|
57
|
+
</CollapsibleTrigger>
|
|
58
|
+
<CollapsibleContent hiddenUntilFound>
|
|
59
|
+
<div className="mt-1.5 whitespace-pre-wrap text-xs leading-relaxed text-dashboard-text-muted">
|
|
60
|
+
<TranscriptText
|
|
61
|
+
mentions={props.part.mentions ?? []}
|
|
62
|
+
role="system"
|
|
63
|
+
text={event.summary}
|
|
64
|
+
/>
|
|
65
|
+
</div>
|
|
66
|
+
</CollapsibleContent>
|
|
67
|
+
</Collapsible>
|
|
54
68
|
) : null}
|
|
55
69
|
</article>
|
|
56
70
|
);
|
|
@@ -2,7 +2,7 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "../styles";
|
|
4
4
|
|
|
5
|
-
/** Align transcript labels and metadata as one centered heading row. */
|
|
5
|
+
/** Align transcript labels and metadata as one centered heading row. Spans keep it valid inside a row button. */
|
|
6
6
|
export function TranscriptHeadingRow(props: {
|
|
7
7
|
className?: string;
|
|
8
8
|
left: ReactNode;
|
|
@@ -14,31 +14,31 @@ export function TranscriptHeadingRow(props: {
|
|
|
14
14
|
props.right !== undefined && props.right !== null && props.right !== false;
|
|
15
15
|
|
|
16
16
|
return (
|
|
17
|
-
<
|
|
17
|
+
<span
|
|
18
18
|
className={cn(
|
|
19
19
|
"flex min-w-0 items-start justify-between gap-2 md:items-center md:gap-3",
|
|
20
20
|
props.className,
|
|
21
21
|
)}
|
|
22
22
|
>
|
|
23
|
-
<
|
|
23
|
+
<span
|
|
24
24
|
className={cn(
|
|
25
25
|
"flex min-w-0 items-center gap-2 overflow-hidden",
|
|
26
26
|
props.leftClassName,
|
|
27
27
|
)}
|
|
28
28
|
>
|
|
29
29
|
{props.left}
|
|
30
|
-
</
|
|
30
|
+
</span>
|
|
31
31
|
{hasRight ? (
|
|
32
|
-
<
|
|
32
|
+
<span
|
|
33
33
|
className={cn(
|
|
34
34
|
"min-w-0 max-w-[60%] shrink text-right md:max-w-none md:shrink-0",
|
|
35
35
|
props.rightClassName,
|
|
36
36
|
)}
|
|
37
37
|
>
|
|
38
38
|
{props.right}
|
|
39
|
-
</
|
|
39
|
+
</span>
|
|
40
40
|
) : null}
|
|
41
|
-
</
|
|
41
|
+
</span>
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TranscriptRow, TranscriptRows } from "./TranscriptRows";
|
|
2
|
-
import { Skeleton } from "../components/
|
|
2
|
+
import { Skeleton } from "../components/ui/skeleton";
|
|
3
3
|
|
|
4
4
|
/** Match the usual transcript rhythm while the selected conversation loads. */
|
|
5
5
|
export function TranscriptLoading() {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
Table,
|
|
5
|
+
TableBody,
|
|
6
|
+
TableCell,
|
|
7
|
+
TableHead,
|
|
8
|
+
TableHeader,
|
|
9
|
+
TableRow,
|
|
10
|
+
} from "../components/ui/table";
|
|
3
11
|
import { cn } from "../styles";
|
|
4
12
|
import {
|
|
5
13
|
findTranscriptMarkdownLinks,
|
|
@@ -184,51 +192,48 @@ function MarkdownTable(props: {
|
|
|
184
192
|
);
|
|
185
193
|
|
|
186
194
|
return (
|
|
187
|
-
<div className="min-w-0 max-w-full overflow-
|
|
188
|
-
<
|
|
189
|
-
<
|
|
190
|
-
<
|
|
195
|
+
<div className="min-w-0 max-w-full overflow-hidden rounded-md border border-dashboard-border bg-dashboard-fill-faint">
|
|
196
|
+
<Table className="w-max min-w-full">
|
|
197
|
+
<TableHeader className="bg-dashboard-overlay-soft">
|
|
198
|
+
<TableRow className="border-dashboard-border">
|
|
191
199
|
{Array.from({ length: columnCount }, (_, index) => {
|
|
192
200
|
const alignment = props.block.alignments[index] ?? null;
|
|
193
201
|
return (
|
|
194
|
-
<
|
|
202
|
+
<TableHead
|
|
195
203
|
className={cn(
|
|
196
|
-
"
|
|
204
|
+
"px-2.5 py-1.5",
|
|
197
205
|
tableCellAlignClass(alignment),
|
|
198
206
|
)}
|
|
199
207
|
key={`h-${index}`}
|
|
200
208
|
scope="col"
|
|
201
209
|
>
|
|
202
210
|
{renderInlineMarkdown(props.block.headers[index] ?? "")}
|
|
203
|
-
</
|
|
211
|
+
</TableHead>
|
|
204
212
|
);
|
|
205
213
|
})}
|
|
206
|
-
</
|
|
207
|
-
</
|
|
208
|
-
<
|
|
214
|
+
</TableRow>
|
|
215
|
+
</TableHeader>
|
|
216
|
+
<TableBody>
|
|
209
217
|
{props.block.rows.map((row, rowIndex) => (
|
|
210
|
-
<
|
|
211
|
-
className="border-b border-dashboard-border-subtle last:border-b-0"
|
|
212
|
-
key={`r-${rowIndex}`}
|
|
213
|
-
>
|
|
218
|
+
<TableRow key={`r-${rowIndex}`}>
|
|
214
219
|
{Array.from({ length: columnCount }, (_, index) => {
|
|
215
220
|
const alignment = props.block.alignments[index] ?? null;
|
|
216
221
|
return (
|
|
217
|
-
<
|
|
222
|
+
<TableCell
|
|
218
223
|
className={cn(
|
|
219
|
-
"
|
|
224
|
+
"px-2.5 py-1.5 align-top",
|
|
220
225
|
tableCellAlignClass(alignment),
|
|
221
226
|
)}
|
|
222
227
|
key={`c-${rowIndex}-${index}`}
|
|
223
228
|
>
|
|
224
229
|
{renderInlineMarkdown(row[index] ?? "")}
|
|
225
|
-
</
|
|
230
|
+
</TableCell>
|
|
226
231
|
);
|
|
227
232
|
})}
|
|
228
|
-
</
|
|
233
|
+
</TableRow>
|
|
229
234
|
))}
|
|
230
|
-
</
|
|
231
|
-
</
|
|
235
|
+
</TableBody>
|
|
236
|
+
</Table>
|
|
232
237
|
</div>
|
|
233
238
|
);
|
|
234
239
|
}
|