export const useAppDispatch:()

in example-apps/chatbot-rag-app/frontend/src/store/provider.tsx [116:297]


export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const actions = globalSlice.actions

export const thunkActions = {
  search: (query: string) => {
    return async function fetchSearch(dispatch, getState) {
      if (getState().status === AppStatus.StreamingMessage) {
        dispatch(thunkActions.abortRequest())
      }

      dispatch(actions.reset())
      dispatch(thunkActions.chat(query))
    }
  },
  askQuestion: (question: string) => {
    return async function (dispatch, getState) {
      const state = getState()

      dispatch(
        actions.addMessage({
          conversation: {
            isHuman: true,
            content: question,
            id: state.conversation.length + 1,
          },
        })
      )
      dispatch(thunkActions.chat(question))
    }
  },
  chat: (question: string) => {
    return async function fetchSearch(dispatch, getState) {
      abortController = new AbortController()
      const conversationId = getState().conversation.length + 1

      dispatch(
        actions.addMessage({
          conversation: {
            isHuman: false,
            content: '',
            id: conversationId,
          },
        })
      )
      dispatch(actions.setStatus({ status: AppStatus.StreamingMessage }))

      let countRetiresError = 0
      let message = ''
      const sessionId = getState().sessionId
      const sourcesMap: Map<
        string,
        { name: string; url?: string; summary: string[] }
      > = new Map()

      await fetchEventSource(
        `${API_HOST}/chat${sessionId ? `?session_id=${sessionId}` : ''}`,
        {
          method: 'POST',
          openWhenHidden: true,
          body: JSON.stringify({
            question,
          }),
          headers: {
            'Content-Type': 'application/json',
          },
          signal: abortController.signal,
          async onmessage(event) {
            if (event.event === 'FatalError') {
              throw new FatalError(event.data)
            }

            if (event.data.startsWith(STREAMING_EVENTS.SESSION_ID)) {
              const sessionId = event.data.split(' ')[1].trim()
              dispatch(actions.setSessionId({ sessionId }))
            } else if (event.data.startsWith(STREAMING_EVENTS.SOURCE)) {
              const source = event.data.replace(
                `${STREAMING_EVENTS.SOURCE} `,
                ''
              )

              try {
                if (source) {
                  const parsedSource: {
                    name: string
                    page_content: string
                    url?: string
                    category?: string
                    updated_at?: string | null
                  } = JSON.parse(source.replaceAll('\n', ''))

                  if (parsedSource.page_content && parsedSource.name) {
                    dispatch(
                      actions.addSource({
                        source: {
                          name: parsedSource.name,
                          url: parsedSource.url,
                          summary: parsedSource.page_content,
                          icon: parsedSource.category,
                          updated_at: parsedSource.updated_at,
                        },
                      })
                    )
                  }
                }
              } catch (e) {
                console.log('error', source, event.data)
                console.error(e)
              }
            } else if (event.data === STREAMING_EVENTS.DONE) {
              const sources = parseSources(message)
              dispatch(
                actions.setMessageSource({
                  id: conversationId,
                  sources,
                })
              )
        
              dispatch(actions.setStatus({ status: AppStatus.Done }))
            } else {
              message += event.data

              dispatch(
                actions.updateMessage({
                  id: conversationId,
                  content: message.replace(/SOURCES:(.+)*/, ''),
                })
              )
            }
          },
          async onopen(response) {

            if (response.ok) {
              return
            } else if (
              response.status >= 400 &&
              response.status < 500 &&
              response.status !== 429
            ) {
              throw new FatalError()
            } else {
              throw new RetriableError()
            }
          },
          onerror(err) {

            if (err instanceof FatalError || countRetiresError > 3) {
              dispatch(actions.setStatus({ status: AppStatus.Error }))

              throw err
            } else {
              countRetiresError++
              console.error(err)
            }
          },
        }
      )
    }
  },
  abortRequest: () => {
    return function (dispatch, getState) {
      const messages = getState().conversation
      const lastMessage = messages[getState().conversation.length - 1]

      abortController?.abort()
      abortController = null

      if (!lastMessage.content) {
        dispatch(
          actions.removeMessage({
            id: lastMessage.id,
          })
        )
      }
      dispatch(
        actions.setStatus({
          status: messages.length ? AppStatus.Done : AppStatus.Idle,
        })
      )
    }
  },
}