/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */ import * as CLM from '@conversationlearner/models' ; import * as ClientFactory from '../services/clientFactory' ; import * as Client from '../services/client' ; import * as DialogUtils from '../Utils/dialogUtils' ; import * as DispatchUtils from '../Utils/dispatchUtils' ; import { ActionObject , ErrorType } from '../types' ; import { AT } from '../types/ActionTypes' ; import { Dispatch } from 'redux' ; import { PartialTrainDialog , SourceAndModelPair } from '../types/models' ; import { fetchApplicationTrainingStatusThunkAsync } from './appActions' ; import { AxiosError } from 'axios' ; import { setErrorDisplay } from './displayActions' ; import { EntityLabelConflictError } from '../types/errors' ; import { DispatcherAlgorithmType } from '../components/modals/DispatcherCreator' ; const createTrainDialogAsync = ( appId , trainDialog ) : ActionObject => ( { type : AT . CREATE_TRAIN_DIALOG_ASYNC , appId , trainDialog } ) ; const createTrainDialogFulfilled = ( trainDialog ) : ActionObject => ( { type : AT . CREATE_TRAIN_DIALOG_FULFILLED , trainDialog : trainDialog } ) ; const createTrainDialogRejected = ( ) : ActionObject => ( { type : AT . CREATE_TRAIN_DIALOG_REJECTED } ) ; export const createTrainDialogThunkAsync = ( appId , trainDialog ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . CREATE_TRAIN_DIALOG_ASYNC ) ; dispatch ( createTrainDialogAsync ( appId , trainDialog ) ) ; try { const createdTrainDialog = await clClient . trainDialogsCreate ( appId , trainDialog ) ; dispatch ( createTrainDialogFulfilled ( createdTrainDialog ) ) ; void dispatch ( fetchApplicationTrainingStatusThunkAsync ( appId ) ) ; return createdTrainDialog ; } catch ( e ) { dispatch ( createTrainDialogRejected ( ) ) ; const error = e as AxiosError ; if ( error . response ?. status === 409 ) { const textVariations = error . response . data . reason ; const conflictError = new EntityLabelConflictError ( error . message , textVariations ) ; throw conflictError ; } dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . CREATE_TRAIN_DIALOG_ASYNC ) ) ; throw error ; } } ; } ; const editTrainDialogAsync = ( appId , trainDialog ) : ActionObject => { return { type : AT . EDIT_TRAINDIALOG_ASYNC , appId : appId , trainDialog : trainDialog } ; } ; const editTrainDialogFulfilled = ( appId , trainDialog ) : ActionObject => { return { type : AT . EDIT_TRAINDIALOG_FULFILLED , appId , trainDialog : trainDialog } ; } ; export const editTrainDialogThunkAsync = ( appId , trainDialog , options ? ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . EDIT_TRAINDIALOG_ASYNC ) ; trainDialog . lastModifiedDateTime = `${ new Date ( ) . toISOString ( ) . slice ( 0 , 19 ) }+00:00` ; dispatch ( editTrainDialogAsync ( appId , trainDialog ) ) ; try { await clClient . trainDialogEdit ( appId , trainDialog , options ) ; dispatch ( editTrainDialogFulfilled ( appId , trainDialog ) ) ; if ( trainDialog . rounds ) { void dispatch ( fetchApplicationTrainingStatusThunkAsync ( appId ) ) ; } return trainDialog ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . EDIT_TRAINDIALOG_ASYNC ) ) ; throw error ; } } ; } ; const fetchTrainDialogAsync = ( appId , trainDialogId ) : ActionObject => { return { type : AT . FETCH_TRAIN_DIALOG_ASYNC , appId : appId , trainDialogId : trainDialogId } ; } ; const fetchTrainDialogFulfilled = ( trainDialog , replaceLocal ) : ActionObject => { return { type : AT . FETCH_TRAIN_DIALOG_FULFILLED , trainDialog , replaceLocal } ; } ; export const fetchTrainDialogThunkAsync = ( appId , trainDialogId , replaceLocal ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_TRAIN_DIALOG_ASYNC ) ; dispatch ( fetchTrainDialogAsync ( appId , trainDialogId ) ) ; try { const trainDialog = await clClient . trainDialog ( appId , trainDialogId ) ; dispatch ( fetchTrainDialogFulfilled ( trainDialog , replaceLocal ) ) ; return trainDialog ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_TRAIN_DIALOG_ASYNC ) ) ; throw e ; } } ; } ; const scoreFromTrainDialogAsync = ( appId , trainDialog ) : ActionObject => { return { type : AT . FETCH_SCOREFROMTRAINDIALOG_ASYNC , appId , trainDialog } ; } ; const scoreFromTrainDialogFulfilled = ( uiScoreResponse ) : ActionObject => { return { type : AT . FETCH_SCOREFROMTRAINDIALOG_FULFILLED , uiScoreResponse } ; } ; const scoreFromTrainDialogRejected = ( ) : ActionObject => ( { type : AT . FETCH_SCOREFROMTRAINDIALOG_REJECTED } ) ; export const scoreFromTrainDialogThunkAsync = ( appId , trainDialog ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_SCOREFROMTRAINDIALOG_ASYNC ) ; dispatch ( scoreFromTrainDialogAsync ( appId , trainDialog ) ) ; try { const uiScoreResponse = await clClient . trainDialogScoreFromTrainDialog ( appId , trainDialog ) ; dispatch ( scoreFromTrainDialogFulfilled ( uiScoreResponse ) ) ; return uiScoreResponse ; } catch ( e ) { dispatch ( scoreFromTrainDialogRejected ( ) ) ; const error = e as AxiosError ; if ( error . response ?. status === 409 ) { const textVariations = error . response . data . reason ; const conflictError = new EntityLabelConflictError ( error . message , textVariations ) ; throw conflictError ; } dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_SCOREFROMTRAINDIALOG_ASYNC ) ) ; throw error ; } } ; } ; const extractFromTrainDialogAsync = ( appId , trainDialog , userInput ) : ActionObject => { return { type : AT . FETCH_EXTRACTFROMTRAINDIALOG_ASYNC , appId , trainDialog , userInput } ; } ; const extractFromTrainDialogFulfilled = ( extractResponse ) : ActionObject => { return { type : AT . FETCH_EXTRACTFROMTRAINDIALOG_FULFILLED , extractResponse } ; } ; const extractFromTrainDialogRejected = ( ) : ActionObject => ( { type : AT . FETCH_EXTRACTFROMTRAINDIALOG_REJECTED } ) ; export const extractFromTrainDialogThunkAsync = ( appId , trainDialog , userInput ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_EXTRACTFROMTRAINDIALOG_ASYNC ) ; dispatch ( extractFromTrainDialogAsync ( appId , trainDialog , userInput ) ) ; try { const extractResponse = await clClient . trainDialogExtractFromTrainDialog ( appId , trainDialog , userInput ) ; dispatch ( extractFromTrainDialogFulfilled ( extractResponse ) ) ; return extractResponse ; } catch ( e ) { dispatch ( extractFromTrainDialogRejected ( ) ) ; const error = e as AxiosError ; if ( error . response ?. status === 409 ) { const textVariations = error . response . data . reason ; const conflictError = new EntityLabelConflictError ( error . message , textVariations ) ; throw conflictError ; } dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_EXTRACTFROMTRAINDIALOG_ASYNC ) ) ; throw error ; } } ; } ; const fetchAllTrainDialogsAsync = ( appId ) : ActionObject => { return { type : AT . FETCH_TRAIN_DIALOGS_ASYNC , appId : appId } ; } ; const fetchAllTrainDialogsFulfilled = ( trainDialogs ) : ActionObject => { return { type : AT . FETCH_TRAIN_DIALOGS_FULFILLED , allTrainDialogs : trainDialogs } ; } ; export const fetchAllTrainDialogsThunkAsync = ( appId ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_TRAIN_DIALOGS_ASYNC ) ; dispatch ( fetchAllTrainDialogsAsync ( appId ) ) ; try { const trainDialogs = await clClient . trainDialogs ( appId ) ; dispatch ( fetchAllTrainDialogsFulfilled ( trainDialogs ) ) ; return trainDialogs ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_TRAIN_DIALOGS_ASYNC ) ) ; return null ; } } ; } ; const regenerateDispatchDialogsAsync = ( ) : ActionObject => { return { type : AT . REGENERATE_DISPATCH_DIALOGS_ASYNC , } ; } ; const regenerateDispatchDialogsFulfilled = ( trainDialogs ) : ActionObject => { return { type : AT . REGENERATE_DISPATCH_DIALOGS_FULFILLED , trainDialogs } ; } ; export const regenerateDispatchTrainDialogsAsync = ( dispatchModelId , algorithmType , actions , existingTrainDialogs ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . REGENERATE_DISPATCH_DIALOGS_ASYNC ) ; dispatch ( regenerateDispatchDialogsAsync ( ) ) ; try { const sourceModelPairs = await Promise . all ( actions . filter ( a => a . actionType === CLM . ActionTypes . DISPATCH ) . map < Promise < SourceAndModelPair > > ( async ( a ) => { const dispatchAction = new CLM . DispatchAction ( a ) ; const model = await clClient . appGet ( dispatchAction . modelId ) ; const appDefinitionChange = await clClient . source ( model . appId , model . devPackageId ) ; return { model , source : appDefinitionChange . currentAppDefinition , action : a , } ; } ) ) ; const dispatcherSource = DispatchUtils . generateDispatcherSource ( sourceModelPairs , algorithmType ) ; await Promise . all ( existingTrainDialogs . map ( td => clClient . trainDialogsDelete ( dispatchModelId , td . trainDialogId ) ) ) ; await Promise . all ( dispatcherSource . trainDialogs . map ( td => clClient . trainDialogsCreate ( dispatchModelId , td ) ) ) ; dispatch ( regenerateDispatchDialogsFulfilled ( dispatcherSource . trainDialogs ) ) ; return dispatcherSource . trainDialogs ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . REGENERATE_DISPATCH_DIALOGS_ASYNC ) ) ; return [ ] ; } } ; } ; const trainDialogMergeAsync = ( ) : ActionObject => { return { type : AT . EDIT_TRAINDIALOG_MERGE_ASYNC } ; } ; const trainDialogMergeFulfilled = ( ) : ActionObject => { return { type : AT . EDIT_TRAINDIALOG_MERGE_FULFILLED } ; } ; export const trainDialogMergeThunkAsync = ( appId , newTrainDialog , existingTrainDialog , newDescription , newTags , sourceTrainDialogId ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . EDIT_TRAINDIALOG_MERGE_ASYNC ) ; dispatch ( trainDialogMergeAsync ( ) ) ; try { const promises = [ ] ; const mergedTrainDialog = DialogUtils . mergeTrainDialogs ( newTrainDialog , existingTrainDialog ) ; mergedTrainDialog . description = newDescription ?? mergedTrainDialog . description ; mergedTrainDialog . tags = newTags ?? mergedTrainDialog . tags ; if ( mergedTrainDialog . trainDialogId === existingTrainDialog . trainDialogId ) { mergedTrainDialog . lastModifiedDateTime = `${ new Date ( ) . toISOString ( ) . slice ( 0 , 19 ) }+00:00` ; promises . push ( clClient . trainDialogEdit ( appId , mergedTrainDialog ) ) ; if ( newTrainDialog . trainDialogId ) { promises . push ( clClient . trainDialogsDelete ( appId , newTrainDialog . trainDialogId ) ) ; } if ( sourceTrainDialogId ) { promises . push ( clClient . trainDialogsDelete ( appId , sourceTrainDialogId ) ) ; } await Promise . all ( promises ) ; } else { if ( sourceTrainDialogId ) { const updatedSourceDialog = { ... mergedTrainDialog , trainDialogId : sourceTrainDialogId , } ; promises . push ( clClient . trainDialogEdit ( appId , updatedSourceDialog ) ) ; if ( existingTrainDialog . trainDialogId ) { promises . push ( clClient . trainDialogsDelete ( appId , existingTrainDialog . trainDialogId ) ) ; } await Promise . all ( promises ) ; } else { const updatedNewDialog = { ... mergedTrainDialog , trainDialogId : newTrainDialog . trainDialogId , } ; promises . push ( clClient . trainDialogEdit ( appId , updatedNewDialog ) ) ; promises . push ( clClient . trainDialogsDelete ( appId , existingTrainDialog . trainDialogId ) ) ; await Promise . all ( promises ) ; } } void dispatch ( fetchAllTrainDialogsThunkAsync ( appId ) ) ; void dispatch ( fetchApplicationTrainingStatusThunkAsync ( appId ) ) ; dispatch ( trainDialogMergeFulfilled ( ) ) ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . EDIT_TRAINDIALOG_MERGE_ASYNC ) ) ; throw error ; } } ; } ; const trainDialogReplaceAsync = ( enableSpinner ) : ActionObject => { return { type : AT . EDIT_TRAINDIALOG_REPLACE_ASYNC , enableSpinner } ; } ; const trainDialogReplaceFulfilled = ( updatedTrainDialog , deletedTrainDialogId ) : ActionObject => { return { type : AT . EDIT_TRAINDIALOG_REPLACE_FULFILLED , updatedTrainDialog , deletedTrainDialogId } ; } ; export const trainDialogReplaceThunkAsync = ( appId , destinationTrainDialogId , newTrainDialog , enableSpinner = true ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . EDIT_TRAINDIALOG_REPLACE_ASYNC ) ; dispatch ( trainDialogReplaceAsync ( enableSpinner ) ) ; try { const promises = [ ] ; const updatedDestinationDialog = { ... newTrainDialog , trainDialogId : destinationTrainDialogId , } ; const deleteDialogId = destinationTrainDialogId !== newTrainDialog . trainDialogId ? newTrainDialog . trainDialogId : null ; if ( deleteDialogId ) { promises . push ( clClient . trainDialogsDelete ( appId , newTrainDialog . trainDialogId ) ) ; } promises . push ( clClient . trainDialogEdit ( appId , updatedDestinationDialog ) ) ; await Promise . all ( promises ) ; void dispatch ( fetchApplicationTrainingStatusThunkAsync ( appId ) ) ; dispatch ( trainDialogReplaceFulfilled ( updatedDestinationDialog , deleteDialogId ) ) ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . EDIT_TRAINDIALOG_REPLACE_ASYNC ) ) ; throw error ; } } ; } ; const trainDialogReplayAsync = ( appId , trainDialog ) : ActionObject => { return { type : AT . FETCH_TRAINDIALOGREPLAY_ASYNC , appId , trainDialog } ; } ; const trainDialogReplayFulfilled = ( trainDialog ) : ActionObject => { return { type : AT . FETCH_TRAINDIALOGREPLAY_FULFILLED , trainDialog } ; } ; export const trainDialogReplayThunkAsync = ( appId , trainDialog ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_TRAINDIALOGREPLAY_ASYNC ) ; dispatch ( trainDialogReplayAsync ( appId , trainDialog ) ) ; try { const updatedTrainDialog = await clClient . trainDialogReplay ( appId , trainDialog ) ; dispatch ( trainDialogReplayFulfilled ( updatedTrainDialog ) ) ; return updatedTrainDialog ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_TRAINDIALOGREPLAY_ASYNC ) ) ; throw error ; } } ; } ; const fetchTextVariationConflictAsync = ( appId , trainDialogId , textVariation ) : ActionObject => { return { type : AT . FETCH_TEXTVARIATION_CONFLICT_ASYNC , appId , trainDialogId , textVariation } ; } ; const fetchTextVariationConflictFulfilled = ( extractResponse ) : ActionObject => { return { type : AT . FETCH_TEXTVARIATION_CONFLICT_FULFILLED , extractResponse } ; } ; export const fetchTextVariationConflictThunkAsync = ( appId , trainDialogId , textVariation , filteredDialogId ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_TEXTVARIATION_CONFLICT_ASYNC ) ; dispatch ( fetchTextVariationConflictAsync ( appId , trainDialogId , textVariation ) ) ; try { const conflict = await clClient . fetchTextVariationConflict ( appId , trainDialogId , textVariation , filteredDialogId ) ; dispatch ( fetchTextVariationConflictFulfilled ( conflict ) ) ; return conflict ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_TEXTVARIATION_CONFLICT_ASYNC ) ) ; throw error ; } } ; } ; export const setTextVariationConflict = ( extractResponse ) : ActionObject => { return { type : AT . SET_TEXTVARIATION_CONFLICT , extractResponse } ; } ; const deleteTrainDialogAsync = ( trainDialogId , appId ) : ActionObject => { return { type : AT . DELETE_TRAIN_DIALOG_ASYNC , appId , trainDialogId } ; } ; const deleteTrainDialogRejected = ( ) : ActionObject => { return { type : AT . DELETE_TRAIN_DIALOG_REJECTED } ; } ; const deleteTrainDialogFulfilled = ( trainDialogId ) : ActionObject => { return { type : AT . DELETE_TRAIN_DIALOG_FULFILLED , trainDialogId } ; } ; export const deleteTrainDialogThunkAsync = ( app , trainDialogId ) => { return async ( dispatch ) => { dispatch ( deleteTrainDialogAsync ( trainDialogId , app . appId ) ) ; const clClient = ClientFactory . getInstance ( AT . DELETE_TRAIN_DIALOG_ASYNC ) ; try { await clClient . trainDialogsDelete ( app . appId , trainDialogId ) ; dispatch ( deleteTrainDialogFulfilled ( trainDialogId ) ) ; void dispatch ( fetchApplicationTrainingStatusThunkAsync ( app . appId ) ) ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . DELETE_TRAIN_DIALOG_REJECTED ) ) ; dispatch ( deleteTrainDialogRejected ( ) ) ; void dispatch ( fetchAllTrainDialogsThunkAsync ( app . appId ) ) ; } } ; } ; const fetchActivitiesAsync = ( noSpinnerDisplay ) : ActionObject => { return { type : AT . FETCH_ACTIVITIES_ASYNC , noSpinnerDisplay } ; } ; const fetchActivitiesFulfilled = ( teachWithActivities ) : ActionObject => { return { type : AT . FETCH_ACTIVITIES_FULFILLED , teachWithActivities , } ; } ; param appId param trainDialog param userName param userId param useMarkdown param noSpinnerDisplay export const fetchActivitiesThunkAsync = ( appId , trainDialog , userName , userId , useMarkdown = true , noSpinnerDisplay = false ) => { return async ( dispatch ) => { const clClient = ClientFactory . getInstance ( AT . FETCH_ACTIVITIES_ASYNC ) ; dispatch ( fetchActivitiesAsync ( noSpinnerDisplay ) ) ; try { const teachWithActivities = await clClient . history ( appId , trainDialog , userName , userId , useMarkdown ) ; dispatch ( fetchActivitiesFulfilled ( teachWithActivities ) ) ; return teachWithActivities ; } catch ( e ) { const error = e as AxiosError ; dispatch ( setErrorDisplay ( ErrorType . Error , error . message , error . response ? JSON . stringify ( error . response , null , '  ' ) : "" , AT . FETCH_ACTIVITIES_ASYNC ) ) ; throw e ; } } ; } ;