chat-wrapper.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { useCallback, useEffect, useMemo } from 'react'
  2. import Chat from '../chat'
  3. import type {
  4. ChatConfig,
  5. OnSend,
  6. } from '../types'
  7. import { useChat } from '../chat/hooks'
  8. import { useChatWithHistoryContext } from './context'
  9. import Header from './header'
  10. import ConfigPanel from './config-panel'
  11. import {
  12. fetchSuggestedQuestions,
  13. getUrl,
  14. stopChatMessageResponding,
  15. } from '@/service/share'
  16. const ChatWrapper = () => {
  17. const {
  18. appParams,
  19. appPrevChatList,
  20. currentConversationId,
  21. currentConversationItem,
  22. inputsForms,
  23. newConversationInputs,
  24. handleNewConversationCompleted,
  25. isMobile,
  26. isInstalledApp,
  27. appId,
  28. appMeta,
  29. handleFeedback,
  30. currentChatInstanceRef,
  31. appData,
  32. themeBuilder,
  33. } = useChatWithHistoryContext()
  34. const appConfig = useMemo(() => {
  35. const config = appParams || {}
  36. return {
  37. ...config,
  38. supportFeedback: true,
  39. opening_statement: currentConversationId ? currentConversationItem?.introduction : (config as any).opening_statement,
  40. } as ChatConfig
  41. }, [appParams, currentConversationItem?.introduction, currentConversationId])
  42. const {
  43. chatList,
  44. handleSend,
  45. handleStop,
  46. isResponding,
  47. suggestedQuestions,
  48. } = useChat(
  49. appConfig,
  50. {
  51. inputs: (currentConversationId ? currentConversationItem?.inputs : newConversationInputs) as any,
  52. promptVariables: inputsForms,
  53. },
  54. appPrevChatList,
  55. taskId => stopChatMessageResponding('', taskId, isInstalledApp, appId),
  56. )
  57. useEffect(() => {
  58. if (currentChatInstanceRef.current)
  59. currentChatInstanceRef.current.handleStop = handleStop
  60. }, [])
  61. const doSend: OnSend = useCallback((message, files) => {
  62. const data: any = {
  63. query: message,
  64. inputs: currentConversationId ? currentConversationItem?.inputs : newConversationInputs,
  65. conversation_id: currentConversationId,
  66. }
  67. if (appConfig?.file_upload?.image.enabled && files?.length)
  68. data.files = files
  69. handleSend(
  70. getUrl('chat-messages', isInstalledApp, appId || ''),
  71. data,
  72. {
  73. onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId),
  74. onConversationComplete: currentConversationId ? undefined : handleNewConversationCompleted,
  75. isPublicAPI: !isInstalledApp,
  76. },
  77. )
  78. }, [
  79. appConfig,
  80. currentConversationId,
  81. currentConversationItem,
  82. handleSend,
  83. newConversationInputs,
  84. handleNewConversationCompleted,
  85. isInstalledApp,
  86. appId,
  87. ])
  88. const chatNode = useMemo(() => {
  89. if (inputsForms.length) {
  90. return (
  91. <>
  92. <Header
  93. isMobile={isMobile}
  94. title={currentConversationItem?.name || ''}
  95. />
  96. {
  97. !currentConversationId && (
  98. <div className={`mx-auto w-full max-w-[720px] ${isMobile && 'px-4'}`}>
  99. <div className='mb-6' />
  100. <ConfigPanel />
  101. <div
  102. className='my-6 h-[1px]'
  103. style={{ background: 'linear-gradient(90deg, rgba(242, 244, 247, 0.00) 0%, #F2F4F7 49.17%, rgba(242, 244, 247, 0.00) 100%)' }}
  104. />
  105. </div>
  106. )
  107. }
  108. </>
  109. )
  110. }
  111. return (
  112. <Header
  113. isMobile={isMobile}
  114. title={currentConversationItem?.name || ''}
  115. />
  116. )
  117. }, [
  118. currentConversationId,
  119. inputsForms,
  120. currentConversationItem,
  121. isMobile,
  122. ])
  123. return (
  124. <Chat
  125. appData={appData}
  126. config={appConfig}
  127. chatList={chatList}
  128. isResponding={isResponding}
  129. chatContainerInnerClassName={`mx-auto pt-6 w-full max-w-[720px] ${isMobile && 'px-4'}`}
  130. chatFooterClassName='pb-4'
  131. chatFooterInnerClassName={`mx-auto w-full max-w-[720px] ${isMobile && 'px-4'}`}
  132. onSend={doSend}
  133. onStopResponding={handleStop}
  134. chatNode={chatNode}
  135. allToolIcons={appMeta?.tool_icons || {}}
  136. onFeedback={handleFeedback}
  137. suggestedQuestions={suggestedQuestions}
  138. hideProcessDetail
  139. themeBuilder={themeBuilder}
  140. />
  141. )
  142. }
  143. export default ChatWrapper