@sentry/junior-dashboard 0.265.0 → 0.267.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/dist/app.js +49 -12
- package/dist/client.js +94 -63
- package/dist/index.js +49 -12
- package/dist/tailwind.css +1 -1
- package/package.json +11 -5
- package/src/app.ts +0 -2
- package/src/auth.ts +4 -7
- package/src/client/App.tsx +35 -53
- package/src/client/components/ActorAvatar.tsx +10 -22
- package/src/client/components/ConnectionBanner.tsx +4 -3
- package/src/client/components/CopyButton.tsx +3 -4
- package/src/client/components/DetailsPanel.tsx +12 -13
- package/src/client/components/Drawer.tsx +46 -23
- package/src/client/components/EmptyTelemetry.tsx +5 -3
- package/src/client/components/ImageAttachment.tsx +49 -63
- package/src/client/components/InlineError.tsx +8 -4
- package/src/client/components/Notice.tsx +19 -26
- package/src/client/components/Pagination.tsx +26 -26
- package/src/client/components/ParticipantAvatarStack.tsx +13 -10
- package/src/client/components/README.md +28 -3
- package/src/client/components/SearchInput.tsx +51 -41
- package/src/client/components/VersionDriftBanner.tsx +9 -7
- package/src/client/components/charts/CacheWrites.tsx +52 -43
- package/src/client/components/ui/alert.tsx +64 -0
- package/src/client/components/ui/avatar.tsx +53 -0
- package/src/client/components/ui/button-group.tsx +59 -0
- package/src/client/components/ui/button.tsx +2 -1
- package/src/client/components/ui/dialog.tsx +60 -0
- package/src/client/components/ui/drawer.tsx +140 -0
- package/src/client/components/ui/empty.tsx +61 -0
- package/src/client/components/ui/input-group.tsx +96 -0
- package/src/client/components/ui/pagination.tsx +60 -0
- package/src/client/components/ui/separator.tsx +22 -0
- package/src/client/components/ui/spinner.tsx +21 -0
- package/src/client/components/ui/table.tsx +22 -1
- package/src/client/components/ui/tooltip.tsx +1 -1
- package/src/client/components/ui/useSheet.ts +5 -1
- package/src/client/conversations/ComposerImages.tsx +66 -14
- package/src/client/conversations/ConversationChildAgents.tsx +5 -5
- package/src/client/conversations/ConversationComposer.tsx +84 -12
- package/src/client/conversations/ConversationDetails.tsx +3 -27
- package/src/client/conversations/ConversationEventDetails.tsx +26 -10
- package/src/client/conversations/ConversationHeader.tsx +5 -4
- package/src/client/conversations/ConversationHeaderActions.tsx +7 -11
- package/src/client/conversations/ConversationPage.tsx +156 -2
- package/src/client/conversations/ConversationSidebar.tsx +5 -4
- package/src/client/conversations/ConversationTranscript.tsx +48 -16
- package/src/client/conversations/ConversationUsageBreakdown.tsx +108 -65
- package/src/client/conversations/ConversationWatches.tsx +67 -59
- package/src/client/conversations/DetailsList.tsx +77 -29
- package/src/client/conversations/EventDetails.tsx +46 -19
- package/src/client/conversations/EventUsage.tsx +99 -74
- package/src/client/conversations/ForkConversationButton.tsx +79 -73
- package/src/client/conversations/PendingMailboxStack.tsx +312 -119
- package/src/client/conversations/README.md +30 -10
- package/src/client/conversations/ShareConversationButton.tsx +3 -4
- package/src/client/conversations/SubagentTranscriptDrawer.tsx +19 -22
- package/src/client/conversations/TranscriptActivityGroup.tsx +22 -19
- package/src/client/conversations/TranscriptAttachment.tsx +39 -4
- package/src/client/conversations/TranscriptAutomationTriggerView.tsx +14 -19
- package/src/client/conversations/TranscriptEventView.tsx +35 -16
- package/src/client/conversations/TranscriptFailureView.tsx +10 -13
- package/src/client/conversations/TranscriptMarkdown.tsx +232 -436
- package/src/client/conversations/TranscriptMessageContextView.tsx +31 -20
- package/src/client/conversations/TranscriptMessageView.tsx +7 -1
- package/src/client/conversations/TranscriptStructuredEventView.tsx +25 -15
- package/src/client/conversations/TranscriptSummary.tsx +13 -7
- package/src/client/conversations/TranscriptTurnContextView.tsx +78 -56
- package/src/client/conversations/TranscriptView.tsx +7 -3
- package/src/client/conversations/UserInputRequestCard.tsx +244 -0
- package/src/client/conversations/conversationOutbox.ts +46 -0
- package/src/client/conversations/eventLog.ts +1 -0
- package/src/client/conversations/eventTime.ts +13 -1
- package/src/client/conversations/eventTranscript.ts +12 -5
- package/src/client/conversations/queries.ts +127 -26
- package/src/client/conversations/transcriptMarkdownLinks.ts +5 -367
- package/src/client/conversations/transcriptMentions.tsx +18 -5
- package/src/client/conversations/userInputRequest.ts +56 -0
- package/src/client/format.ts +10 -3
- package/src/client/pages/automations/{AutomationLifecycle.tsx → AutomationActions.tsx} +60 -69
- package/src/client/pages/automations/AutomationDraftChanges.tsx +171 -0
- package/src/client/pages/automations/AutomationEditor.tsx +182 -156
- package/src/client/pages/automations/AutomationEventFields.tsx +119 -45
- package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +1 -1
- package/src/client/pages/automations/AutomationFormSection.tsx +20 -2
- package/src/client/pages/automations/AutomationOutcomeFields.tsx +1 -1
- package/src/client/pages/automations/AutomationOverview.tsx +238 -0
- package/src/client/pages/automations/AutomationPage.tsx +343 -0
- package/src/client/pages/automations/AutomationRecentRuns.tsx +3 -2
- package/src/client/pages/automations/AutomationRow.tsx +11 -13
- package/src/client/pages/automations/AutomationRunDetails.tsx +4 -2
- package/src/client/pages/automations/{AutomationExecutionsPage.tsx → AutomationRunsTab.tsx} +94 -103
- package/src/client/pages/automations/AutomationStatus.tsx +164 -108
- package/src/client/pages/automations/AutomationVersionsTab.tsx +518 -0
- package/src/client/pages/automations/AutomationsPage.tsx +10 -98
- package/src/client/pages/automations/AutomationsPageLayout.tsx +5 -23
- package/src/client/pages/automations/README.md +56 -46
- package/src/client/types.ts +3 -0
- package/src/mock-reporting/fixtures.ts +44 -2
- package/src/mock-reporting/watches.ts +1 -1
- package/src/client/conversations/transcriptStyles.ts +0 -10
- package/src/client/pages/automations/AutomationDetails.tsx +0 -193
- package/src/client/pages/automations/AutomationEditPage.tsx +0 -176
- package/src/client/pages/automations/AutomationVersionsPage.tsx +0 -390
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { ConversationUsage } from "@sentry/junior/api/schema";
|
|
2
2
|
|
|
3
3
|
import { formatCostBreakdown, summarizeCost } from "../format";
|
|
4
|
+
import {
|
|
5
|
+
Table,
|
|
6
|
+
TableBody,
|
|
7
|
+
TableCell,
|
|
8
|
+
TableHead,
|
|
9
|
+
TableFooter,
|
|
10
|
+
TableHeader,
|
|
11
|
+
TableRow,
|
|
12
|
+
} from "../components/ui/table";
|
|
4
13
|
import { cn } from "../styles";
|
|
5
14
|
|
|
6
15
|
/** Align recorded token counts with their costs without adding overlapping counters. */
|
|
@@ -31,83 +40,53 @@ export function EventUsage({ usage }: { usage?: ConversationUsage }) {
|
|
|
31
40
|
);
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
const total = rows.find((row) => row.label === "Total");
|
|
34
44
|
return (
|
|
35
45
|
<>
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
>
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"py-2 text-left font-normal",
|
|
73
|
-
row.label === "Total"
|
|
74
|
-
? "font-semibold text-dashboard-text"
|
|
75
|
-
: "text-dashboard-text-muted",
|
|
76
|
-
)}
|
|
77
|
-
>
|
|
78
|
-
{row.label}
|
|
79
|
-
</th>
|
|
80
|
-
<td className="py-2 text-right font-sans tabular-nums text-dashboard-text">
|
|
81
|
-
{row.tokens === undefined ? (
|
|
82
|
-
<span
|
|
83
|
-
aria-label="Not recorded"
|
|
84
|
-
className="text-dashboard-text-faint"
|
|
85
|
-
>
|
|
86
|
-
—
|
|
87
|
-
</span>
|
|
88
|
-
) : (
|
|
89
|
-
row.tokens.toLocaleString("en-US")
|
|
90
|
-
)}
|
|
91
|
-
</td>
|
|
92
|
-
<td className="py-2 text-right font-sans tabular-nums text-dashboard-text">
|
|
93
|
-
{row.cost === undefined ? (
|
|
94
|
-
<span
|
|
95
|
-
aria-label="Not recorded separately"
|
|
96
|
-
className="text-dashboard-text-faint"
|
|
97
|
-
>
|
|
98
|
-
—
|
|
99
|
-
</span>
|
|
100
|
-
) : (
|
|
101
|
-
<span title={`${row.cost} USD`}>
|
|
102
|
-
{formatCostBreakdown({ total: row.cost })}
|
|
103
|
-
</span>
|
|
104
|
-
)}
|
|
105
|
-
</td>
|
|
106
|
-
</tr>
|
|
46
|
+
<Table
|
|
47
|
+
aria-label="Model call token and cost breakdown"
|
|
48
|
+
className="min-w-72 table-fixed text-xs leading-relaxed"
|
|
49
|
+
>
|
|
50
|
+
<colgroup>
|
|
51
|
+
<col />
|
|
52
|
+
<col className="w-24" />
|
|
53
|
+
<col className="w-24" />
|
|
54
|
+
</colgroup>
|
|
55
|
+
<TableHeader>
|
|
56
|
+
<TableRow className="border-dashboard-border">
|
|
57
|
+
<TableHead
|
|
58
|
+
scope="col"
|
|
59
|
+
className="px-0 py-2 leading-relaxed font-normal"
|
|
60
|
+
>
|
|
61
|
+
Usage
|
|
62
|
+
</TableHead>
|
|
63
|
+
<TableHead
|
|
64
|
+
scope="col"
|
|
65
|
+
className="px-0 py-2 text-right leading-relaxed font-normal"
|
|
66
|
+
>
|
|
67
|
+
Tokens
|
|
68
|
+
</TableHead>
|
|
69
|
+
<TableHead
|
|
70
|
+
scope="col"
|
|
71
|
+
className="px-0 py-2 text-right leading-relaxed font-normal"
|
|
72
|
+
>
|
|
73
|
+
Cost (USD)
|
|
74
|
+
</TableHead>
|
|
75
|
+
</TableRow>
|
|
76
|
+
</TableHeader>
|
|
77
|
+
<TableBody>
|
|
78
|
+
{rows
|
|
79
|
+
.filter((row) => row !== total)
|
|
80
|
+
.map((row) => (
|
|
81
|
+
<UsageRow key={row.label} {...row} />
|
|
107
82
|
))}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
83
|
+
</TableBody>
|
|
84
|
+
{total ? (
|
|
85
|
+
<TableFooter className="font-semibold">
|
|
86
|
+
<UsageRow {...total} total />
|
|
87
|
+
</TableFooter>
|
|
88
|
+
) : null}
|
|
89
|
+
</Table>
|
|
111
90
|
<p className="m-0 text-xs leading-relaxed text-dashboard-text-muted">
|
|
112
91
|
This call only · Estimated costs
|
|
113
92
|
<br />
|
|
@@ -116,3 +95,49 @@ export function EventUsage({ usage }: { usage?: ConversationUsage }) {
|
|
|
116
95
|
</>
|
|
117
96
|
);
|
|
118
97
|
}
|
|
98
|
+
|
|
99
|
+
function UsageRow(props: {
|
|
100
|
+
cost?: number;
|
|
101
|
+
label: string;
|
|
102
|
+
tokens?: number;
|
|
103
|
+
total?: boolean;
|
|
104
|
+
}) {
|
|
105
|
+
return (
|
|
106
|
+
<TableRow>
|
|
107
|
+
<TableHead
|
|
108
|
+
scope="row"
|
|
109
|
+
className={cn(
|
|
110
|
+
"px-0 py-2 leading-relaxed",
|
|
111
|
+
props.total
|
|
112
|
+
? "font-semibold text-dashboard-text"
|
|
113
|
+
: "font-normal text-dashboard-text-muted",
|
|
114
|
+
)}
|
|
115
|
+
>
|
|
116
|
+
{props.label}
|
|
117
|
+
</TableHead>
|
|
118
|
+
<TableCell className="px-0 py-2 text-right font-sans tabular-nums">
|
|
119
|
+
{props.tokens === undefined ? (
|
|
120
|
+
<span aria-label="Not recorded" className="text-dashboard-text-faint">
|
|
121
|
+
—
|
|
122
|
+
</span>
|
|
123
|
+
) : (
|
|
124
|
+
props.tokens.toLocaleString("en-US")
|
|
125
|
+
)}
|
|
126
|
+
</TableCell>
|
|
127
|
+
<TableCell className="px-0 py-2 text-right font-sans tabular-nums">
|
|
128
|
+
{props.cost === undefined ? (
|
|
129
|
+
<span
|
|
130
|
+
aria-label="Not recorded separately"
|
|
131
|
+
className="text-dashboard-text-faint"
|
|
132
|
+
>
|
|
133
|
+
—
|
|
134
|
+
</span>
|
|
135
|
+
) : (
|
|
136
|
+
<span title={`${props.cost} USD`}>
|
|
137
|
+
{formatCostBreakdown({ total: props.cost })}
|
|
138
|
+
</span>
|
|
139
|
+
)}
|
|
140
|
+
</TableCell>
|
|
141
|
+
</TableRow>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { GitFork } from "lucide-react";
|
|
2
|
-
import { useId, useState } from "react";
|
|
3
|
-
import { createPortal } from "react-dom";
|
|
2
|
+
import { useId, useRef, useState } from "react";
|
|
4
3
|
import { useNavigate } from "react-router";
|
|
5
4
|
import { Button } from "../components/ui/button";
|
|
6
5
|
import { Textarea } from "../components/ui/textarea";
|
|
7
|
-
import { Field, FieldLabel } from "../components/ui/field";
|
|
6
|
+
import { Field, FieldError, FieldLabel } from "../components/ui/field";
|
|
7
|
+
import {
|
|
8
|
+
Dialog,
|
|
9
|
+
DialogClose,
|
|
10
|
+
DialogContent,
|
|
11
|
+
DialogFooter,
|
|
12
|
+
DialogTitle,
|
|
13
|
+
} from "../components/ui/dialog";
|
|
14
|
+
import { useSheet } from "../components/ui/useSheet";
|
|
8
15
|
import {
|
|
9
16
|
Tooltip,
|
|
10
17
|
TooltipContent,
|
|
11
18
|
TooltipTrigger,
|
|
12
19
|
} from "../components/ui/tooltip";
|
|
13
|
-
import { Drawer } from "../components/Drawer";
|
|
14
20
|
import { DashboardApiError } from "../http";
|
|
15
21
|
import { conversationPath } from "./conversationRoutes";
|
|
16
22
|
import { useForkConversation } from "./queries";
|
|
@@ -36,26 +42,22 @@ export function ForkConversationButton(props: ForkTarget) {
|
|
|
36
42
|
/>
|
|
37
43
|
<TooltipContent size="compact">Fork after this message</TooltipContent>
|
|
38
44
|
</Tooltip>
|
|
39
|
-
{open
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
{...props}
|
|
43
|
-
onClose={() => setOpen(false)}
|
|
44
|
-
/>,
|
|
45
|
-
document.body,
|
|
46
|
-
)
|
|
47
|
-
: null}
|
|
45
|
+
{open ? (
|
|
46
|
+
<ForkConversationDialog {...props} onClose={() => setOpen(false)} />
|
|
47
|
+
) : null}
|
|
48
48
|
</>
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function ForkConversationDialog(props: ForkTarget & { onClose(): void }) {
|
|
53
|
-
const titleId = useId();
|
|
54
53
|
const inputId = useId();
|
|
54
|
+
const errorId = `${inputId}-error`;
|
|
55
|
+
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
55
56
|
const [idempotencyKey] = useState(() => crypto.randomUUID());
|
|
56
57
|
const [message, setMessage] = useState("");
|
|
57
58
|
const navigate = useNavigate();
|
|
58
59
|
const fork = useForkConversation(props.conversationId);
|
|
60
|
+
const sheet = useSheet(props.onClose, inputRef);
|
|
59
61
|
const submit = () => {
|
|
60
62
|
if (!message.trim() || fork.isPending) return;
|
|
61
63
|
fork.mutate(
|
|
@@ -68,68 +70,72 @@ function ForkConversationDialog(props: ForkTarget & { onClose(): void }) {
|
|
|
68
70
|
},
|
|
69
71
|
);
|
|
70
72
|
};
|
|
73
|
+
const error = fork.error
|
|
74
|
+
? (fork.error instanceof DashboardApiError && fork.error.apiError) ||
|
|
75
|
+
"Could not fork the conversation. Try again."
|
|
76
|
+
: undefined;
|
|
71
77
|
return (
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
onClose={() => {
|
|
82
|
-
if (!fork.isPending) props.onClose();
|
|
78
|
+
<Dialog
|
|
79
|
+
{...sheet.rootProps}
|
|
80
|
+
onOpenChange={(nextOpen, details) => {
|
|
81
|
+
// A pending fork must finish so its navigation is not lost.
|
|
82
|
+
if (!nextOpen && fork.isPending) {
|
|
83
|
+
details.cancel();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
sheet.rootProps.onOpenChange(nextOpen, details);
|
|
83
87
|
}}
|
|
84
|
-
width="narrow"
|
|
85
88
|
>
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
event
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
<p className="m-0">
|
|
94
|
-
Creates a fork of the conversation from this point.
|
|
95
|
-
</p>
|
|
96
|
-
<Field>
|
|
97
|
-
<FieldLabel htmlFor={inputId}>Message</FieldLabel>
|
|
98
|
-
<Textarea
|
|
99
|
-
id={inputId}
|
|
100
|
-
autoFocus
|
|
101
|
-
className="min-h-28 leading-relaxed"
|
|
102
|
-
placeholder="Message Junior…"
|
|
103
|
-
value={message}
|
|
104
|
-
disabled={fork.isPending}
|
|
105
|
-
onChange={(event) => setMessage(event.target.value)}
|
|
106
|
-
onKeyDown={(event) => {
|
|
107
|
-
// Same keys as the composer: Enter sends, Shift+Enter adds a line.
|
|
108
|
-
if (
|
|
109
|
-
event.key === "Enter" &&
|
|
110
|
-
!event.shiftKey &&
|
|
111
|
-
!event.nativeEvent.isComposing
|
|
112
|
-
) {
|
|
113
|
-
event.preventDefault();
|
|
114
|
-
submit();
|
|
115
|
-
}
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
</Field>
|
|
119
|
-
{fork.error ? (
|
|
120
|
-
<p role="alert" className="m-0 text-red-300">
|
|
121
|
-
{(fork.error instanceof DashboardApiError && fork.error.apiError) ||
|
|
122
|
-
"Could not fork the conversation. Try again."}
|
|
123
|
-
</p>
|
|
124
|
-
) : null}
|
|
125
|
-
<Button
|
|
126
|
-
variant="primary"
|
|
127
|
-
type="submit"
|
|
128
|
-
disabled={!message.trim() || fork.isPending}
|
|
89
|
+
<DialogContent {...sheet.contentProps}>
|
|
90
|
+
<form
|
|
91
|
+
className="grid gap-4"
|
|
92
|
+
onSubmit={(event) => {
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
submit();
|
|
95
|
+
}}
|
|
129
96
|
>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
97
|
+
<DialogTitle>Fork Conversation</DialogTitle>
|
|
98
|
+
<Field>
|
|
99
|
+
<FieldLabel htmlFor={inputId}>Message</FieldLabel>
|
|
100
|
+
<Textarea
|
|
101
|
+
ref={inputRef}
|
|
102
|
+
id={inputId}
|
|
103
|
+
aria-describedby={error ? errorId : undefined}
|
|
104
|
+
aria-invalid={error ? true : undefined}
|
|
105
|
+
className="min-h-24 leading-relaxed"
|
|
106
|
+
placeholder="Message Junior…"
|
|
107
|
+
value={message}
|
|
108
|
+
disabled={fork.isPending}
|
|
109
|
+
onChange={(event) => setMessage(event.target.value)}
|
|
110
|
+
onKeyDown={(event) => {
|
|
111
|
+
// Same keys as the composer: Enter sends, Shift+Enter adds a line.
|
|
112
|
+
if (
|
|
113
|
+
event.key === "Enter" &&
|
|
114
|
+
!event.shiftKey &&
|
|
115
|
+
!event.nativeEvent.isComposing
|
|
116
|
+
) {
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
submit();
|
|
119
|
+
}
|
|
120
|
+
}}
|
|
121
|
+
/>
|
|
122
|
+
<FieldError id={errorId}>{error}</FieldError>
|
|
123
|
+
</Field>
|
|
124
|
+
<DialogFooter>
|
|
125
|
+
<DialogClose
|
|
126
|
+
disabled={fork.isPending}
|
|
127
|
+
render={<Button>Cancel</Button>}
|
|
128
|
+
/>
|
|
129
|
+
<Button
|
|
130
|
+
variant="primary"
|
|
131
|
+
type="submit"
|
|
132
|
+
disabled={!message.trim() || fork.isPending}
|
|
133
|
+
>
|
|
134
|
+
{fork.isPending ? "Forking…" : "Fork and send"}
|
|
135
|
+
</Button>
|
|
136
|
+
</DialogFooter>
|
|
137
|
+
</form>
|
|
138
|
+
</DialogContent>
|
|
139
|
+
</Dialog>
|
|
134
140
|
);
|
|
135
141
|
}
|