@@ -4,15 +4,19 @@ import styled from '@emotion/styled';
44import { AnimatePresence , motion } from 'framer-motion' ;
55
66import { addErrorMessage , addSuccessMessage } from 'sentry/actionCreators/indicator' ;
7- import { SeerLoadingIcon } from 'sentry/components/ai/SeerIcon' ;
7+ import { SeerLoadingIcon , SeerWaitingIcon } from 'sentry/components/ai/SeerIcon' ;
88import { Button } from 'sentry/components/core/button' ;
99import { TextArea } from 'sentry/components/core/textarea' ;
1010import { Tooltip } from 'sentry/components/core/tooltip' ;
11+ import { useUpdateInsightCard } from 'sentry/components/events/autofix/autofixInsightCards' ;
1112import { AutofixProgressBar } from 'sentry/components/events/autofix/autofixProgressBar' ;
1213import { FlyingLinesEffect } from 'sentry/components/events/autofix/FlyingLinesEffect' ;
1314import type { AutofixData } from 'sentry/components/events/autofix/types' ;
15+ import { AutofixStepType } from 'sentry/components/events/autofix/types' ;
1416import { makeAutofixQueryKey } from 'sentry/components/events/autofix/useAutofix' ;
1517import { useTypingAnimation } from 'sentry/components/events/autofix/useTypingAnimation' ;
18+ import { getAutofixRunErrorMessage } from 'sentry/components/events/autofix/utils' ;
19+ import { IconRefresh } from 'sentry/icons' ;
1620import { t } from 'sentry/locale' ;
1721import { space } from 'sentry/styles/space' ;
1822import { singleLineRenderer } from 'sentry/utils/marked/marked' ;
@@ -102,6 +106,104 @@ interface Props {
102106 responseRequired ?: boolean ;
103107}
104108
109+ interface ActiveLogDisplayProps {
110+ groupId : string ;
111+ runId : string ;
112+ activeLog ?: string ;
113+ autofixData ?: AutofixData ;
114+ isInitializingRun ?: boolean ;
115+ seerIconRef ?: React . RefObject < HTMLDivElement | null > ;
116+ }
117+
118+ function ActiveLogDisplay ( {
119+ activeLog = '' ,
120+ isInitializingRun = false ,
121+ seerIconRef,
122+ autofixData,
123+ groupId,
124+ runId,
125+ } : ActiveLogDisplayProps ) {
126+ const displayedActiveLog =
127+ useTypingAnimation ( {
128+ text : activeLog ,
129+ speed : 200 ,
130+ enabled : ! ! activeLog ,
131+ } ) || '' ;
132+
133+ // special case for errored step
134+ const errorMessage = getAutofixRunErrorMessage ( autofixData ) ;
135+ const erroredStep = autofixData ?. steps ?. find ( step => step . status === 'ERROR' ) ;
136+ const erroredStepIndex = erroredStep ?. index ?? 0 ;
137+ let retainInsightCardIndex : number | null = null ;
138+ if (
139+ erroredStep &&
140+ erroredStep . type === AutofixStepType . DEFAULT &&
141+ Array . isArray ( ( erroredStep as any ) . insights )
142+ ) {
143+ const insights = ( erroredStep as any ) . insights ;
144+ if ( insights . length > 0 ) {
145+ retainInsightCardIndex = insights . length ;
146+ }
147+ }
148+
149+ const { mutate : refreshStep , isPending : isRefreshing } = useUpdateInsightCard ( {
150+ groupId,
151+ runId,
152+ } ) ;
153+
154+ if ( errorMessage ) {
155+ return (
156+ < ActiveLogWrapper >
157+ < SeerIconContainer >
158+ < SeerWaitingIcon size = "lg" />
159+ </ SeerIconContainer >
160+ < ActiveLog > { errorMessage } </ ActiveLog >
161+ < Button
162+ size = "xs"
163+ borderless
164+ aria-label = { t ( 'Retry step' ) }
165+ title = { t ( 'Retry step' ) }
166+ onClick = { ( ) =>
167+ refreshStep ( {
168+ message : '' ,
169+ step_index : erroredStepIndex ,
170+ retain_insight_card_index : retainInsightCardIndex ,
171+ } )
172+ }
173+ disabled = { isRefreshing }
174+ style = { { marginLeft : 'auto' } }
175+ >
176+ < IconRefresh size = "sm" />
177+ </ Button >
178+ </ ActiveLogWrapper >
179+ ) ;
180+ }
181+ if ( activeLog ) {
182+ return (
183+ < ActiveLogWrapper >
184+ < Tooltip
185+ title = { t (
186+ "Seer is hard at work. Feel free to leave - it'll keep running in the background."
187+ ) }
188+ >
189+ < SeerIconContainer ref = { seerIconRef } >
190+ < StyledAnimatedSeerIcon size = "lg" />
191+ { seerIconRef ?. current && isInitializingRun && (
192+ < FlyingLinesEffect targetElement = { seerIconRef . current } />
193+ ) }
194+ </ SeerIconContainer >
195+ </ Tooltip >
196+ < ActiveLog
197+ dangerouslySetInnerHTML = { {
198+ __html : singleLineRenderer ( displayedActiveLog ) ,
199+ } }
200+ />
201+ </ ActiveLogWrapper >
202+ ) ;
203+ }
204+ return null ;
205+ }
206+
105207export function AutofixOutputStream ( {
106208 stream,
107209 activeLog = '' ,
@@ -118,12 +220,6 @@ export function AutofixOutputStream({
118220
119221 const isInitializingRun = activeLog === 'Ingesting Sentry data...' ;
120222
121- const displayedActiveLog = useTypingAnimation ( {
122- text : activeLog ,
123- speed : 200 ,
124- enabled : ! ! activeLog ,
125- } ) ;
126-
127223 const orgSlug = useOrganization ( ) . slug ;
128224
129225 const { mutate : send } = useMutation ( {
@@ -192,27 +288,16 @@ export function AutofixOutputStream({
192288 >
193289 < VerticalLine />
194290 < Container required = { responseRequired } >
195- { activeLog && (
196- < ActiveLogWrapper >
197- < Tooltip
198- title = { t (
199- "Seer is hard at work. Feel free to leave - it'll keep running in the background."
200- ) }
201- >
202- < SeerIconContainer ref = { seerIconRef } >
203- < StyledAnimatedSeerIcon size = "lg" />
204- { seerIconRef . current && isInitializingRun && (
205- < FlyingLinesEffect targetElement = { seerIconRef . current } />
206- ) }
207- </ SeerIconContainer >
208- </ Tooltip >
209- < ActiveLog
210- dangerouslySetInnerHTML = { {
211- __html : singleLineRenderer ( displayedActiveLog ) ,
212- } }
213- />
214- </ ActiveLogWrapper >
215- ) }
291+ { getAutofixRunErrorMessage ( autofixData ) || activeLog ? (
292+ < ActiveLogDisplay
293+ activeLog = { activeLog }
294+ isInitializingRun = { isInitializingRun }
295+ seerIconRef = { seerIconRef }
296+ autofixData = { autofixData }
297+ groupId = { groupId }
298+ runId = { runId }
299+ />
300+ ) : null }
216301 { autofixData && (
217302 < ProgressBarWrapper >
218303 < AutofixProgressBar autofixData = { autofixData } />
@@ -326,7 +411,7 @@ const ActiveLogWrapper = styled('div')`
326411const ActiveLog = styled ( 'div' ) `
327412 flex-grow: 1;
328413 word-break: break-word;
329- margin-top: ${ space ( 0.5 ) } ;
414+ margin-top: ${ space ( 0.25 ) } ;
330415` ;
331416
332417const VerticalLine = styled ( 'div' ) `
0 commit comments