@@ -15,6 +15,7 @@ import {
1515 DropdownMenuTrigger ,
1616 Library ,
1717 Loader ,
18+ toast ,
1819} from '@/components/emcn'
1920import { DatePicker } from '@/components/emcn/components/date-picker/date-picker'
2021import { dollarsToCredits } from '@/lib/billing/credits/conversion'
@@ -53,11 +54,14 @@ import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/provide
5354import { getBlock } from '@/blocks/registry'
5455import { useFolderMap , useFolders } from '@/hooks/queries/folders'
5556import {
57+ fetchLogDetail ,
58+ logKeys ,
5659 prefetchLogDetail ,
5760 useCancelExecution ,
5861 useDashboardStats ,
5962 useLogDetail ,
6063 useLogsList ,
64+ useRetryExecution ,
6165} from '@/hooks/queries/logs'
6266import { useWorkflowMap , useWorkflows } from '@/hooks/queries/workflows'
6367import { useDebounce } from '@/hooks/use-debounce'
@@ -74,6 +78,7 @@ import {
7478import {
7579 DELETED_WORKFLOW_COLOR ,
7680 DELETED_WORKFLOW_LABEL ,
81+ extractRetryInput ,
7782 formatDate ,
7883 getDisplayStatus ,
7984 type LogStatus ,
@@ -536,6 +541,7 @@ export default function Logs() {
536541 } , [ contextMenuLog ] )
537542
538543 const cancelExecution = useCancelExecution ( )
544+ const retryExecution = useRetryExecution ( )
539545
540546 const handleCancelExecution = useCallback ( ( ) => {
541547 const workflowId = contextMenuLog ?. workflow ?. id || contextMenuLog ?. workflowId
@@ -546,6 +552,37 @@ export default function Logs() {
546552 // eslint-disable-next-line react-hooks/exhaustive-deps
547553 } , [ contextMenuLog ] )
548554
555+ const retryLog = useCallback (
556+ async ( log : WorkflowLog | null ) => {
557+ const workflowId = log ?. workflow ?. id || log ?. workflowId
558+ const logId = log ?. id
559+ if ( ! workflowId || ! logId ) return
560+
561+ try {
562+ const detailLog = await queryClient . fetchQuery ( {
563+ queryKey : logKeys . detail ( logId ) ,
564+ queryFn : ( { signal } ) => fetchLogDetail ( logId , signal ) ,
565+ staleTime : 30 * 1000 ,
566+ } )
567+ const input = extractRetryInput ( detailLog )
568+ await retryExecution . mutateAsync ( { workflowId, input } )
569+ toast . success ( 'Retry started' )
570+ } catch {
571+ toast . error ( 'Failed to retry execution' )
572+ }
573+ } ,
574+ // eslint-disable-next-line react-hooks/exhaustive-deps
575+ [ ]
576+ )
577+
578+ const handleRetryExecution = useCallback ( ( ) => {
579+ retryLog ( contextMenuLog )
580+ } , [ contextMenuLog , retryLog ] )
581+
582+ const handleRetrySidebarExecution = useCallback ( ( ) => {
583+ retryLog ( selectedLog )
584+ } , [ selectedLog , retryLog ] )
585+
549586 const contextMenuWorkflowId = contextMenuLog ?. workflow ?. id || contextMenuLog ?. workflowId
550587 const isFilteredByThisWorkflow = Boolean (
551588 contextMenuWorkflowId && workflowIds . length === 1 && workflowIds [ 0 ] === contextMenuWorkflowId
@@ -783,6 +820,7 @@ export default function Logs() {
783820 onNavigatePrev = { handleNavigatePrev }
784821 hasNext = { selectedLogIndex < sortedLogs . length - 1 }
785822 hasPrev = { selectedLogIndex > 0 }
823+ onRetryExecution = { handleRetrySidebarExecution }
786824 />
787825 ) ,
788826 [
@@ -791,6 +829,7 @@ export default function Logs() {
791829 handleCloseSidebar ,
792830 handleNavigateNext ,
793831 handleNavigatePrev ,
832+ handleRetrySidebarExecution ,
794833 selectedLogIndex ,
795834 sortedLogs . length ,
796835 ]
@@ -1191,6 +1230,7 @@ export default function Logs() {
11911230 onOpenWorkflow = { handleOpenWorkflow }
11921231 onOpenPreview = { handleOpenPreview }
11931232 onCancelExecution = { handleCancelExecution }
1233+ onRetryExecution = { handleRetryExecution }
11941234 onToggleWorkflowFilter = { handleToggleWorkflowFilter }
11951235 onClearAllFilters = { handleClearAllFilters }
11961236 isFilteredByThisWorkflow = { isFilteredByThisWorkflow }
0 commit comments