Ver código fonte

Feat/chat add origin (#1130)

zxhlyh 1 ano atrás
pai
commit
84c76bc04a
74 arquivos alterados com 2366 adições e 28 exclusões
  1. 12 3
      web/app/components/app/chat/answer/index.tsx
  2. 123 0
      web/app/components/app/chat/citation/index.tsx
  3. 123 0
      web/app/components/app/chat/citation/popup.tsx
  4. 46 0
      web/app/components/app/chat/citation/progress-tooltip.tsx
  5. 46 0
      web/app/components/app/chat/citation/tooltip.tsx
  6. 8 0
      web/app/components/app/chat/index.tsx
  7. 21 0
      web/app/components/app/chat/type.ts
  8. 0 0
      web/app/components/app/configuration/base/icons/citation.tsx
  9. 62 0
      web/app/components/app/configuration/config/feature/choose-feature/feature-item/preview-imgs/citation.svg
  10. 4 0
      web/app/components/app/configuration/config/feature/choose-feature/feature-item/style.module.css
  11. 10 0
      web/app/components/app/configuration/config/feature/choose-feature/index.tsx
  12. 8 0
      web/app/components/app/configuration/config/feature/use-feature.tsx
  13. 10 1
      web/app/components/app/configuration/config/index.tsx
  14. 19 1
      web/app/components/app/configuration/debug/index.tsx
  15. 25 0
      web/app/components/app/configuration/features/chat-group/citation/index.tsx
  16. 8 0
      web/app/components/app/configuration/features/chat-group/index.tsx
  17. 15 0
      web/app/components/app/configuration/index.tsx
  18. 48 0
      web/app/components/base/file-icon/index.tsx
  19. 12 0
      web/app/components/base/icons/assets/public/common/notion.svg
  20. 23 0
      web/app/components/base/icons/assets/public/files/html.svg
  21. 23 0
      web/app/components/base/icons/assets/public/files/json.svg
  22. 22 0
      web/app/components/base/icons/assets/public/files/pdf.svg
  23. 23 0
      web/app/components/base/icons/assets/public/files/txt.svg
  24. 23 0
      web/app/components/base/icons/assets/public/files/unknow.svg
  25. 18 0
      web/app/components/base/icons/assets/public/files/xlsx.svg
  26. 5 0
      web/app/components/base/icons/assets/vender/line/editor/bezier-curve-03.svg
  27. 5 0
      web/app/components/base/icons/assets/vender/line/editor/type-square.svg
  28. 10 0
      web/app/components/base/icons/assets/vender/line/general/target-04.svg
  29. 5 0
      web/app/components/base/icons/assets/vender/solid/editor/citations.svg
  30. 83 0
      web/app/components/base/icons/src/public/common/Notion.json
  31. 16 0
      web/app/components/base/icons/src/public/common/Notion.tsx
  32. 1 0
      web/app/components/base/icons/src/public/common/index.ts
  33. 178 0
      web/app/components/base/icons/src/public/files/Html.json
  34. 16 0
      web/app/components/base/icons/src/public/files/Html.tsx
  35. 178 0
      web/app/components/base/icons/src/public/files/Json.json
  36. 16 0
      web/app/components/base/icons/src/public/files/Json.tsx
  37. 169 0
      web/app/components/base/icons/src/public/files/Pdf.json
  38. 16 0
      web/app/components/base/icons/src/public/files/Pdf.tsx
  39. 180 0
      web/app/components/base/icons/src/public/files/Txt.json
  40. 16 0
      web/app/components/base/icons/src/public/files/Txt.tsx
  41. 199 0
      web/app/components/base/icons/src/public/files/Unknow.json
  42. 16 0
      web/app/components/base/icons/src/public/files/Unknow.tsx
  43. 145 0
      web/app/components/base/icons/src/public/files/Xlsx.json
  44. 16 0
      web/app/components/base/icons/src/public/files/Xlsx.tsx
  45. 6 0
      web/app/components/base/icons/src/public/files/index.ts
  46. 2 0
      web/app/components/base/icons/src/public/llm/Localai.tsx
  47. 2 0
      web/app/components/base/icons/src/public/llm/LocalaiText.tsx
  48. 38 0
      web/app/components/base/icons/src/vender/line/editor/BezierCurve03.json
  49. 16 0
      web/app/components/base/icons/src/vender/line/editor/BezierCurve03.tsx
  50. 38 0
      web/app/components/base/icons/src/vender/line/editor/TypeSquare.json
  51. 16 0
      web/app/components/base/icons/src/vender/line/editor/TypeSquare.tsx
  52. 2 0
      web/app/components/base/icons/src/vender/line/editor/index.ts
  53. 65 0
      web/app/components/base/icons/src/vender/line/general/Target04.json
  54. 16 0
      web/app/components/base/icons/src/vender/line/general/Target04.tsx
  55. 1 0
      web/app/components/base/icons/src/vender/line/general/index.ts
  56. 36 0
      web/app/components/base/icons/src/vender/solid/editor/Citations.json
  57. 16 0
      web/app/components/base/icons/src/vender/solid/editor/Citations.tsx
  58. 1 0
      web/app/components/base/icons/src/vender/solid/editor/index.ts
  59. 2 2
      web/app/components/base/portal-to-follow-elem/index.tsx
  60. 1 1
      web/app/components/explore/item-operation/index.tsx
  61. 18 1
      web/app/components/explore/universal-chat/index.tsx
  62. 23 2
      web/app/components/share/chat/index.tsx
  63. 3 2
      web/app/components/share/chatbot/index.tsx
  64. 7 1
      web/context/debug-configuration.ts
  65. 5 0
      web/i18n/lang/app-debug.en.ts
  66. 5 0
      web/i18n/lang/app-debug.zh.ts
  67. 8 0
      web/i18n/lang/common.en.ts
  68. 8 0
      web/i18n/lang/common.zh.ts
  69. 5 0
      web/models/debug.ts
  70. 9 5
      web/service/base.ts
  71. 4 3
      web/service/debug.ts
  72. 4 3
      web/service/share.ts
  73. 4 3
      web/service/universal-chat.ts
  74. 3 0
      web/types/app.ts

+ 12 - 3
web/app/components/app/chat/answer/index.tsx

@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
 import { UserCircleIcon } from '@heroicons/react/24/solid'
 import cn from 'classnames'
-import type { DisplayScene, FeedbackFunc, Feedbacktype, IChatItem, SubmitAnnotationFunc, ThoughtItem } from '../type'
+import type { CitationItem, DisplayScene, FeedbackFunc, Feedbacktype, IChatItem, SubmitAnnotationFunc, ThoughtItem } from '../type'
 import OperationBtn from '../operation'
 import LoadingAnim from '../loading-anim'
 import { EditIcon, EditIconSolid, OpeningStatementIcon, RatingIcon } from '../icon-component'
@@ -13,6 +13,7 @@ import s from '../style.module.css'
 import MoreInfo from '../more-info'
 import CopyBtn from '../copy-btn'
 import Thought from '../thought'
+import Citation from '../citation'
 import { randomString } from '@/utils'
 import type { Annotation, MessageRating } from '@/models/log'
 import AppContext from '@/context/app-context'
@@ -45,11 +46,14 @@ export type IAnswerProps = {
   isResponsing?: boolean
   answerIconClassName?: string
   thoughts?: ThoughtItem[]
+  citation?: CitationItem[]
   isThinking?: boolean
   dataSets?: DataSet[]
+  isShowCitation?: boolean
+  isShowCitationHitInfo?: boolean
 }
 // The component needs to maintain its own state to control whether to display input component
-const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedbackEdit = false, onFeedback, onSubmitAnnotation, displayScene = 'web', isResponsing, answerIconClassName, thoughts, isThinking, dataSets }) => {
+const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedbackEdit = false, onFeedback, onSubmitAnnotation, displayScene = 'web', isResponsing, answerIconClassName, thoughts, citation, isThinking, dataSets, isShowCitation, isShowCitationHitInfo = false }) => {
   const { id, content, more, feedback, adminFeedback, annotation: initAnnotation } = item
   const [showEdit, setShowEdit] = useState(false)
   const [loading, setLoading] = useState(false)
@@ -171,7 +175,7 @@ const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedba
             </div>
           }
         </div>
-        <div className={s.answerWrapWrap}>
+        <div className={cn(s.answerWrapWrap, 'chat-answer-container')}>
           <div className={`${s.answerWrap} ${showEdit ? 'w-full' : ''}`}>
             <div className={`${s.answer} relative text-sm text-gray-900`}>
               <div className={'ml-2 py-3 px-4 bg-gray-100 rounded-tr-2xl rounded-b-2xl'}>
@@ -237,6 +241,11 @@ const Answer: FC<IAnswerProps> = ({ item, feedbackDisabled = false, isHideFeedba
                     </div>
                   </>
                 }
+                {
+                  !!citation?.length && !isThinking && isShowCitation && !isResponsing && (
+                    <Citation data={citation} showHitInfo={isShowCitationHitInfo} />
+                  )
+                }
               </div>
               <div className='absolute top-[-14px] right-[-14px] flex flex-row justify-end gap-1'>
                 {!item.isOpeningStatement && (

+ 123 - 0
web/app/components/app/chat/citation/index.tsx

@@ -0,0 +1,123 @@
+import { useEffect, useMemo, useRef, useState } from 'react'
+import type { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import type { CitationItem } from '../type'
+import Popup from './popup'
+import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
+
+export type Resources = {
+  documentId: string
+  documentName: string
+  dataSourceType: string
+  sources: CitationItem[]
+}
+
+type CitationProps = {
+  data: CitationItem[]
+  showHitInfo?: boolean
+}
+const Citation: FC<CitationProps> = ({
+  data,
+  showHitInfo,
+}) => {
+  const { t } = useTranslation()
+  const elesRef = useRef<HTMLDivElement[]>([])
+  const [limitNumberInOneLine, setlimitNumberInOneLine] = useState(0)
+  const [showMore, setShowMore] = useState(false)
+  const resources = useMemo(() => data.reduce((prev: Resources[], next) => {
+    const documentId = next.document_id
+    const documentName = next.document_name
+    const dataSourceType = next.data_source_type
+    const documentIndex = prev.findIndex(i => i.documentId === documentId)
+
+    if (documentIndex > -1) {
+      prev[documentIndex].sources.push(next)
+    }
+    else {
+      prev.push({
+        documentId,
+        documentName,
+        dataSourceType,
+        sources: [next],
+      })
+    }
+
+    return prev
+  }, []), [data])
+
+  const handleAdjustResourcesLayout = () => {
+    const containerWidth = document.querySelector('.chat-answer-container')!.clientWidth - 40
+    let totalWidth = 0
+    for (let i = 0; i < resources.length; i++) {
+      totalWidth += elesRef.current[i].clientWidth
+
+      if (totalWidth + i * 4 > containerWidth!) {
+        totalWidth -= elesRef.current[i].clientWidth
+
+        if (totalWidth + 34 > containerWidth!)
+          setlimitNumberInOneLine(i - 1)
+        else
+          setlimitNumberInOneLine(i)
+
+        break
+      }
+      else {
+        setlimitNumberInOneLine(i + 1)
+      }
+    }
+  }
+
+  useEffect(() => {
+    handleAdjustResourcesLayout()
+  }, [])
+
+  const resourcesLength = resources.length
+
+  return (
+    <div className='mt-3 -mb-1'>
+      <div className='flex items-center mb-2 text-xs font-medium text-gray-500'>
+        {t('common.chat.citation.title')}
+        <div className='grow ml-2 h-[1px] bg-black/5' />
+      </div>
+      <div className='relative flex flex-wrap'>
+        {
+          resources.map((res, index) => (
+            <div
+              key={index}
+              className='absolute top-0 left-0 w-auto mr-1 mb-1 pl-7 pr-2 max-w-[240px] h-7 text-xs whitespace-nowrap opacity-0 -z-10'
+              ref={ele => (elesRef.current[index] = ele!)}
+            >
+              {res.documentName}
+            </div>
+          ))
+        }
+        {
+          resources.slice(0, showMore ? resourcesLength : limitNumberInOneLine).map((res, index) => (
+            <div key={index} className='mr-1 mb-1 cursor-pointer'>
+              <Popup
+                data={res}
+                showHitInfo={showHitInfo}
+              />
+            </div>
+          ))
+        }
+        {
+          limitNumberInOneLine < resourcesLength && (
+            <div
+              className='flex items-center px-2 h-7 bg-white rounded-lg text-xs font-medium text-gray-500 cursor-pointer'
+              onClick={() => setShowMore(v => !v)}
+            >
+              {
+                !showMore
+                  ? `+ ${resourcesLength - limitNumberInOneLine}`
+                  : <ChevronDown className='w-4 h-4 text-gray-600 rotate-180' />
+              }
+            </div>
+          )
+        }
+      </div>
+    </div>
+  )
+}
+
+export default Citation

+ 123 - 0
web/app/components/app/chat/citation/popup.tsx

@@ -0,0 +1,123 @@
+import { Fragment, useState } from 'react'
+import type { FC } from 'react'
+import Link from 'next/link'
+import { useTranslation } from 'react-i18next'
+import Tooltip from './tooltip'
+import ProgressTooltip from './progress-tooltip'
+import type { Resources } from './index'
+import {
+  PortalToFollowElem,
+  PortalToFollowElemContent,
+  PortalToFollowElemTrigger,
+} from '@/app/components/base/portal-to-follow-elem'
+import FileIcon from '@/app/components/base/file-icon'
+import {
+  Hash02,
+  Target04,
+} from '@/app/components/base/icons/src/vender/line/general'
+import { ArrowUpRight } from '@/app/components/base/icons/src/vender/line/arrows'
+import {
+  BezierCurve03,
+  TypeSquare,
+} from '@/app/components/base/icons/src/vender/line/editor'
+
+type PopupProps = {
+  data: Resources
+  showHitInfo?: boolean
+}
+
+const Popup: FC<PopupProps> = ({
+  data,
+  showHitInfo = false,
+}) => {
+  const { t } = useTranslation()
+  const [open, setOpen] = useState(false)
+  const fileType = data.dataSourceType === 'upload_file'
+    ? (/\.([^.]*)$/g.exec(data.documentName)?.[1] || '')
+    : 'notion'
+
+  return (
+    <PortalToFollowElem
+      open={open}
+      onOpenChange={setOpen}
+      placement='top-start'
+      offset={{
+        mainAxis: 8,
+        crossAxis: -2,
+      }}
+    >
+      <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
+        <div className='flex items-center px-2 max-w-[240px] h-7 bg-white rounded-lg'>
+          <FileIcon type={fileType} className='mr-1 w-4 h-4' />
+          <div className='text-xs text-gray-600 truncate'>{data.documentName}</div>
+        </div>
+      </PortalToFollowElemTrigger>
+      <PortalToFollowElemContent style={{ zIndex: 1000 }}>
+        <div className='w-[360px] bg-gray-50 rounded-xl shadow-lg'>
+          <div className='px-4 pt-3 pb-2'>
+            <div className='flex items-center h-[18px]'>
+              <FileIcon type={fileType} className='mr-1 w-4 h-4' />
+              <div className='text-xs font-medium text-gray-600 truncate'>{data.documentName}</div>
+            </div>
+          </div>
+          <div className='px-4 py-0.5 max-h-[450px] bg-white rounded-lg overflow-auto'>
+            {
+              data.sources.map((source, index) => (
+                <Fragment key={index}>
+                  <div className='group py-3'>
+                    {
+                      showHitInfo && (
+                        <div className='flex items-center justify-between mb-2'>
+                          <div className='flex items-center px-1.5 h-5 border border-gray-200 rounded-md'>
+                            <Hash02 className='mr-0.5 w-3 h-3 text-gray-400' />
+                            <div className='text-[11px] font-medium text-gray-500'>{source.segment_position}</div>
+                          </div>
+                          <Link
+                            href={`/datasets/${source.dataset_id}/documents/${source.document_id}`}
+                            className='hidden items-center h-[18px] text-xs text-primary-600 group-hover:flex'>
+                            Link to dataset
+                            <ArrowUpRight className='ml-1 w-3 h-3' />
+                          </Link>
+                        </div>
+                      )
+                    }
+                    <div className='text-[13px] text-gray-800'>{source.content}</div>
+                    {
+                      showHitInfo && (
+                        <div className='flex items-center mt-2 text-xs font-medium text-gray-500'>
+                          <Tooltip
+                            text={t('common.chat.citation.characters')}
+                            data={source.word_count}
+                            icon={<TypeSquare className='mr-1 w-3 h-3' />}
+                          />
+                          <Tooltip
+                            text={t('common.chat.citation.hitCount')}
+                            data={source.hit_count}
+                            icon={<Target04 className='mr-1 w-3 h-3' />}
+                          />
+                          <Tooltip
+                            text={t('common.chat.citation.vectorHash')}
+                            data={source.index_node_hash.substring(0, 7)}
+                            icon={<BezierCurve03 className='mr-1 w-3 h-3' />}
+                          />
+                          <ProgressTooltip data={Number(source.score.toFixed(2))} />
+                        </div>
+                      )
+                    }
+                  </div>
+                  {
+                    index !== data.sources.length - 1 && (
+                      <div className='my-1 h-[1px] bg-black/5' />
+                    )
+                  }
+                </Fragment>
+              ))
+            }
+          </div>
+        </div>
+      </PortalToFollowElemContent>
+    </PortalToFollowElem>
+  )
+}
+
+export default Popup

+ 46 - 0
web/app/components/app/chat/citation/progress-tooltip.tsx

@@ -0,0 +1,46 @@
+import { useState } from 'react'
+import type { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import {
+  PortalToFollowElem,
+  PortalToFollowElemContent,
+  PortalToFollowElemTrigger,
+} from '@/app/components/base/portal-to-follow-elem'
+
+type ProgressTooltipProps = {
+  data: number
+}
+
+const ProgressTooltip: FC<ProgressTooltipProps> = ({
+  data,
+}) => {
+  const { t } = useTranslation()
+  const [open, setOpen] = useState(false)
+
+  return (
+    <PortalToFollowElem
+      open={open}
+      onOpenChange={setOpen}
+      placement='top-start'
+    >
+      <PortalToFollowElemTrigger
+        onMouseEnter={() => setOpen(true)}
+        onMouseLeave={() => setOpen(false)}
+      >
+        <div className='grow flex items-center'>
+          <div className='mr-1 w-16 h-1.5 rounded-[3px] border border-gray-400 overflow-hidden'>
+            <div className='bg-gray-400 h-full' style={{ width: `${data * 100}%` }}></div>
+          </div>
+          {data}
+        </div>
+      </PortalToFollowElemTrigger>
+      <PortalToFollowElemContent style={{ zIndex: 1001 }}>
+        <div className='p-3 bg-white text-xs font-medium text-gray-500 rounded-lg shadow-lg'>
+          {t('common.chat.citation.hitScore')} {data}
+        </div>
+      </PortalToFollowElemContent>
+    </PortalToFollowElem>
+  )
+}
+
+export default ProgressTooltip

+ 46 - 0
web/app/components/app/chat/citation/tooltip.tsx

@@ -0,0 +1,46 @@
+import React, { useState } from 'react'
+import type { FC } from 'react'
+import {
+  PortalToFollowElem,
+  PortalToFollowElemContent,
+  PortalToFollowElemTrigger,
+} from '@/app/components/base/portal-to-follow-elem'
+
+type TooltipProps = {
+  data: number | string
+  text: string
+  icon: React.ReactNode
+}
+
+const Tooltip: FC<TooltipProps> = ({
+  data,
+  text,
+  icon,
+}) => {
+  const [open, setOpen] = useState(false)
+
+  return (
+    <PortalToFollowElem
+      open={open}
+      onOpenChange={setOpen}
+      placement='top-start'
+    >
+      <PortalToFollowElemTrigger
+        onMouseEnter={() => setOpen(true)}
+        onMouseLeave={() => setOpen(false)}
+      >
+        <div className='flex items-center mr-6'>
+          {icon}
+          {data}
+        </div>
+      </PortalToFollowElemTrigger>
+      <PortalToFollowElemContent style={{ zIndex: 1001 }}>
+        <div className='p-3 bg-white text-xs font-medium text-gray-500 rounded-lg shadow-lg'>
+          {text} {data}
+        </div>
+      </PortalToFollowElemContent>
+    </PortalToFollowElem>
+  )
+}
+
+export default Tooltip

+ 8 - 0
web/app/components/app/chat/index.tsx

@@ -48,9 +48,11 @@ export type IChatProps = {
   isShowSuggestion?: boolean
   suggestionList?: string[]
   isShowSpeechToText?: boolean
+  isShowCitation?: boolean
   answerIconClassName?: string
   isShowConfigElem?: boolean
   dataSets?: DataSet[]
+  isShowCitationHitInfo?: boolean
 }
 
 const Chat: FC<IChatProps> = ({
@@ -74,9 +76,11 @@ const Chat: FC<IChatProps> = ({
   isShowSuggestion,
   suggestionList,
   isShowSpeechToText,
+  isShowCitation,
   answerIconClassName,
   isShowConfigElem,
   dataSets,
+  isShowCitationHitInfo,
 }) => {
   const { t } = useTranslation()
   const { notify } = useContext(ToastContext)
@@ -162,6 +166,7 @@ const Chat: FC<IChatProps> = ({
           if (item.isAnswer) {
             const isLast = item.id === chatList[chatList.length - 1].id
             const thoughts = item.agent_thoughts?.filter(item => item.thought !== '[DONE]')
+            const citation = item.citation
             const isThinking = !item.content && item.agent_thoughts && item.agent_thoughts?.length > 0 && !item.agent_thoughts.some(item => item.thought === '[DONE]')
             return <Answer
               key={item.id}
@@ -174,8 +179,11 @@ const Chat: FC<IChatProps> = ({
               isResponsing={isResponsing && isLast}
               answerIconClassName={answerIconClassName}
               thoughts={thoughts}
+              citation={citation}
               isThinking={isThinking}
               dataSets={dataSets}
+              isShowCitation={isShowCitation}
+              isShowCitationHitInfo={isShowCitationHitInfo}
             />
           }
           return <Question key={item.id} id={item.id} content={item.content} more={item.more} useCurrentUserAvatar={useCurrentUserAvatar} />

+ 21 - 0
web/app/components/app/chat/type.ts

@@ -23,10 +23,26 @@ export type ThoughtItem = {
   tool_input: string
   message_id: string
 }
+export type CitationItem = {
+  content: string
+  data_source_type: string
+  dataset_name: string
+  dataset_id: string
+  document_id: string
+  document_name: string
+  hit_count: number
+  index_node_hash: string
+  segment_id: string
+  segment_position: number
+  score: number
+  word_count: number
+}
+
 export type IChatItem = {
   id: string
   content: string
   agent_thoughts?: ThoughtItem[]
+  citation?: CitationItem[]
   /**
    * Specific message type
    */
@@ -51,3 +67,8 @@ export type IChatItem = {
   useCurrentUserAvatar?: boolean
   isOpeningStatement?: boolean
 }
+
+export type MessageEnd = {
+  id: string
+  retriever_resources?: CitationItem[]
+}

+ 0 - 0
web/app/components/app/configuration/base/icons/citation.tsx


Diferenças do arquivo suprimidas por serem muito extensas
+ 62 - 0
web/app/components/app/configuration/config/feature/choose-feature/feature-item/preview-imgs/citation.svg


+ 4 - 0
web/app/components/app/configuration/config/feature/choose-feature/feature-item/style.module.css

@@ -26,4 +26,8 @@
 
 .speechToTextPreview {
   background-image: url(./preview-imgs/speech-to-text.svg);
+}
+
+.citationPreview {
+  background-image: url(./preview-imgs/citation.svg);
 }

+ 10 - 0
web/app/components/app/configuration/config/feature/choose-feature/index.tsx

@@ -8,11 +8,13 @@ import FeatureItem from './feature-item'
 import Modal from '@/app/components/base/modal'
 import SuggestedQuestionsAfterAnswerIcon from '@/app/components/app/configuration/base/icons/suggested-questions-after-answer-icon'
 import { Microphone01 } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices'
+import { Citations } from '@/app/components/base/icons/src/vender/solid/editor'
 type IConfig = {
   openingStatement: boolean
   moreLikeThis: boolean
   suggestedQuestionsAfterAnswer: boolean
   speechToText: boolean
+  citation: boolean
 }
 
 export type IChooseFeatureProps = {
@@ -85,6 +87,14 @@ const ChooseFeature: FC<IChooseFeatureProps> = ({
                   />
                 )
               }
+              <FeatureItem
+                icon={<Citations className='w-4 h-4 text-[#FD853A]' />}
+                previewImgClassName='citationPreview'
+                title={t('appDebug.feature.citation.title')}
+                description={t('appDebug.feature.citation.description')}
+                value={config.citation}
+                onChange={value => onChange('citation', value)}
+              />
             </>
           </FeatureGroup>
         )}

+ 8 - 0
web/app/components/app/configuration/config/feature/use-feature.tsx

@@ -9,6 +9,8 @@ function useFeature({
   setSuggestedQuestionsAfterAnswer,
   speechToText,
   setSpeechToText,
+  citation,
+  setCitation,
 }: {
   introduction: string
   setIntroduction: (introduction: string) => void
@@ -18,6 +20,8 @@ function useFeature({
   setSuggestedQuestionsAfterAnswer: (suggestedQuestionsAfterAnswer: boolean) => void
   speechToText: boolean
   setSpeechToText: (speechToText: boolean) => void
+  citation: boolean
+  setCitation: (citation: boolean) => void
 }) {
   const [tempshowOpeningStatement, setTempShowOpeningStatement] = React.useState(!!introduction)
   useEffect(() => {
@@ -36,6 +40,7 @@ function useFeature({
     moreLikeThis,
     suggestedQuestionsAfterAnswer,
     speechToText,
+    citation,
   }
   const handleFeatureChange = (key: string, value: boolean) => {
     switch (key) {
@@ -53,6 +58,9 @@ function useFeature({
         break
       case 'speechToText':
         setSpeechToText(value)
+        break
+      case 'citation':
+        setCitation(value)
     }
   }
   return {

+ 10 - 1
web/app/components/app/configuration/config/index.tsx

@@ -36,6 +36,8 @@ const Config: FC = () => {
     setSuggestedQuestionsAfterAnswerConfig,
     speechToTextConfig,
     setSpeechToTextConfig,
+    citationConfig,
+    setCitationConfig,
   } = useContext(ConfigContext)
   const isChatApp = mode === AppType.chat
   const { speech2textDefaultModel } = useProviderContext()
@@ -88,9 +90,15 @@ const Config: FC = () => {
         draft.enabled = value
       }))
     },
+    citation: citationConfig.enabled,
+    setCitation: (value) => {
+      setCitationConfig(produce(citationConfig, (draft) => {
+        draft.enabled = value
+      }))
+    },
   })
 
-  const hasChatConfig = isChatApp && (featureConfig.openingStatement || featureConfig.suggestedQuestionsAfterAnswer || (featureConfig.speechToText && !!speech2textDefaultModel))
+  const hasChatConfig = isChatApp && (featureConfig.openingStatement || featureConfig.suggestedQuestionsAfterAnswer || (featureConfig.speechToText && !!speech2textDefaultModel) || featureConfig.citation)
   const hasToolbox = false
 
   const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false)
@@ -161,6 +169,7 @@ const Config: FC = () => {
               }
               isShowSuggestedQuestionsAfterAnswer={featureConfig.suggestedQuestionsAfterAnswer}
               isShowSpeechText={featureConfig.speechToText && !!speech2textDefaultModel}
+              isShowCitation={featureConfig.citation}
             />
           )
         }

+ 19 - 1
web/app/components/app/configuration/debug/index.tsx

@@ -40,6 +40,7 @@ const Debug: FC<IDebug> = ({
     introduction,
     suggestedQuestionsAfterAnswerConfig,
     speechToTextConfig,
+    citationConfig,
     moreLikeThisConfig,
     inputs,
     // setInputs,
@@ -162,6 +163,7 @@ const Debug: FC<IDebug> = ({
       },
       suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
       speech_to_text: speechToTextConfig,
+      retriever_resource: citationConfig,
       agent_mode: {
         enabled: true,
         tools: [...postDatasets],
@@ -199,7 +201,7 @@ const Debug: FC<IDebug> = ({
     setChatList(newList)
 
     // answer
-    const responseItem = {
+    const responseItem: IChatItem = {
       id: `${Date.now()}`,
       content: '',
       isAnswer: true,
@@ -266,6 +268,19 @@ const Debug: FC<IDebug> = ({
           setIsShowSuggestion(true)
         }
       },
+      onMessageEnd: (messageEnd) => {
+        responseItem.citation = messageEnd.retriever_resources
+
+        const newListWithAnswer = produce(
+          getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
+          (draft) => {
+            if (!draft.find(item => item.id === questionId))
+              draft.push({ ...questionItem })
+
+            draft.push({ ...responseItem })
+          })
+        setChatList(newListWithAnswer)
+      },
       onError() {
         setResponsingFalse()
         // role back placeholder answer
@@ -312,6 +327,7 @@ const Debug: FC<IDebug> = ({
       opening_statement: introduction,
       suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
       speech_to_text: speechToTextConfig,
+      retriever_resource: citationConfig,
       more_like_this: moreLikeThisConfig,
       agent_mode: {
         enabled: true,
@@ -391,6 +407,8 @@ const Debug: FC<IDebug> = ({
                   isShowSuggestion={doShowSuggestion}
                   suggestionList={suggestQuestions}
                   isShowSpeechToText={speechToTextConfig.enabled && !!speech2textDefaultModel}
+                  isShowCitation={citationConfig.enabled}
+                  isShowCitationHitInfo
                 />
               </div>
             </div>

+ 25 - 0
web/app/components/app/configuration/features/chat-group/citation/index.tsx

@@ -0,0 +1,25 @@
+'use client'
+import React, { type FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Panel from '@/app/components/app/configuration/base/feature-panel'
+import { Citations } from '@/app/components/base/icons/src/vender/solid/editor'
+
+const Citation: FC = () => {
+  const { t } = useTranslation()
+
+  return (
+    <Panel
+      title={
+        <div className='flex items-center gap-2'>
+          <div>{t('appDebug.feature.citation.title')}</div>
+        </div>
+      }
+      headerIcon={<Citations className='w-4 h-4 text-[#FD853A]' />}
+      headerRight={
+        <div className='text-xs text-gray-500'>{t('appDebug.feature.citation.resDes')}</div>
+      }
+      noBodySpacing
+    />
+  )
+}
+export default React.memo(Citation)

+ 8 - 0
web/app/components/app/configuration/features/chat-group/index.tsx

@@ -7,6 +7,7 @@ import type { IOpeningStatementProps } from './opening-statement'
 import OpeningStatement from './opening-statement'
 import SuggestedQuestionsAfterAnswer from './suggested-questions-after-answer'
 import SpeechToText from './speech-to-text'
+import Citation from './citation'
 
 /*
 * Include
@@ -19,12 +20,14 @@ type ChatGroupProps = {
   openingStatementConfig: IOpeningStatementProps
   isShowSuggestedQuestionsAfterAnswer: boolean
   isShowSpeechText: boolean
+  isShowCitation: boolean
 }
 const ChatGroup: FC<ChatGroupProps> = ({
   isShowOpeningStatement,
   openingStatementConfig,
   isShowSuggestedQuestionsAfterAnswer,
   isShowSpeechText,
+  isShowCitation,
 }) => {
   const { t } = useTranslation()
 
@@ -43,6 +46,11 @@ const ChatGroup: FC<ChatGroupProps> = ({
             <SpeechToText />
           )
         }
+        {
+          isShowCitation && (
+            <Citation />
+          )
+        }
       </div>
     </div>
   )

+ 15 - 0
web/app/components/app/configuration/index.tsx

@@ -56,6 +56,9 @@ const Configuration: FC = () => {
   const [speechToTextConfig, setSpeechToTextConfig] = useState<MoreLikeThisConfig>({
     enabled: false,
   })
+  const [citationConfig, setCitationConfig] = useState<MoreLikeThisConfig>({
+    enabled: false,
+  })
   const [formattingChanged, setFormattingChanged] = useState(false)
   const [inputs, setInputs] = useState<Inputs>({})
   const [query, setQuery] = useState('')
@@ -77,6 +80,7 @@ const Configuration: FC = () => {
     more_like_this: null,
     suggested_questions_after_answer: null,
     speech_to_text: null,
+    retriever_resource: null,
     dataSets: [],
   })
 
@@ -110,6 +114,9 @@ const Configuration: FC = () => {
     setSpeechToTextConfig(modelConfig.speech_to_text || {
       enabled: false,
     })
+    setCitationConfig(modelConfig.retriever_resource || {
+      enabled: false,
+    })
   }
 
   const { textGenerationModelList } = useProviderContext()
@@ -159,6 +166,9 @@ const Configuration: FC = () => {
       if (modelConfig.speech_to_text)
         setSpeechToTextConfig(modelConfig.speech_to_text)
 
+      if (modelConfig.retriever_resource)
+        setCitationConfig(modelConfig.retriever_resource)
+
       const config = {
         modelConfig: {
           provider: model.provider,
@@ -171,6 +181,7 @@ const Configuration: FC = () => {
           more_like_this: modelConfig.more_like_this,
           suggested_questions_after_answer: modelConfig.suggested_questions_after_answer,
           speech_to_text: modelConfig.speech_to_text,
+          retriever_resource: modelConfig.retriever_resource,
           dataSets: datasets || [],
         },
         completionParams: model.completion_params,
@@ -202,6 +213,7 @@ const Configuration: FC = () => {
       more_like_this: moreLikeThisConfig,
       suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
       speech_to_text: speechToTextConfig,
+      retriever_resource: citationConfig,
       agent_mode: {
         enabled: true,
         tools: [...postDatasets],
@@ -219,6 +231,7 @@ const Configuration: FC = () => {
       draft.more_like_this = moreLikeThisConfig
       draft.suggested_questions_after_answer = suggestedQuestionsAfterAnswerConfig
       draft.speech_to_text = speechToTextConfig
+      draft.retriever_resource = citationConfig
       draft.dataSets = dataSets
     })
     setPublishedConfig({
@@ -263,6 +276,8 @@ const Configuration: FC = () => {
       setSuggestedQuestionsAfterAnswerConfig,
       speechToTextConfig,
       setSpeechToTextConfig,
+      citationConfig,
+      setCitationConfig,
       formattingChanged,
       setFormattingChanged,
       inputs,

+ 48 - 0
web/app/components/base/file-icon/index.tsx

@@ -0,0 +1,48 @@
+import type { FC } from 'react'
+import {
+  Csv,
+  Html,
+  Json,
+  Md,
+  Pdf,
+  Txt,
+  Unknow,
+  Xlsx,
+} from '@/app/components/base/icons/src/public/files'
+import { Notion } from '@/app/components/base/icons/src/public/common'
+
+type FileIconProps = {
+  type: string
+  className?: string
+}
+
+const FileIcon: FC<FileIconProps> = ({
+  type,
+  className,
+}) => {
+  switch (type) {
+    case 'csv':
+      return <Csv className={className} />
+    case 'htm':
+    case 'html':
+      return <Html className={className} />
+    case 'json':
+      return <Json className={className} />
+    case 'md':
+    case 'markdown':
+      return <Md className={className} />
+    case 'pdf':
+      return <Pdf className={className} />
+    case 'txt':
+      return <Txt className={className} />
+    case 'xls':
+    case 'xlsx':
+      return <Xlsx className={className} />
+    case 'notion':
+      return <Notion className={className} />
+    default:
+      return <Unknow className={className} />
+  }
+}
+
+export default FileIcon

+ 12 - 0
web/app/components/base/icons/assets/public/common/notion.svg

@@ -0,0 +1,12 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_5364_42310)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3.5725 18.2611L1.4229 15.5832C0.905706 14.9389 0.625 14.1466 0.625 13.3312V3.63437C0.625 2.4129 1.60224 1.39936 2.86295 1.31328L12.8326 0.632614C13.5569 0.583164 14.2768 0.775682 14.8717 1.17794L18.3745 3.5462C19.0015 3.97012 19.375 4.66312 19.375 5.40266V16.427C19.375 17.6223 18.4141 18.6121 17.1798 18.688L6.11458 19.3692C5.12958 19.4298 4.17749 19.0148 3.5725 18.2611Z" fill="white"/>
+<path d="M7.03006 8.48663V8.35968C7.03006 8.03787 7.28779 7.77098 7.61997 7.7488L10.0396 7.58726L13.3857 12.5146V8.19003L12.5244 8.07522V8.01492C12.5244 7.68933 12.788 7.42068 13.1244 7.40344L15.326 7.29066V7.60749C15.326 7.75622 15.2154 7.88343 15.0638 7.90907L14.534 7.99868V15.0022L13.8691 15.2309C13.3136 15.4219 12.6952 15.2174 12.3772 14.7376L9.12879 9.83568V14.5143L10.1287 14.7056L10.1147 14.7984C10.0711 15.0889 9.82028 15.3086 9.51687 15.3221L7.03006 15.4328C6.99718 15.1204 7.23132 14.8409 7.55431 14.807L7.88143 14.7726V8.53447L7.03006 8.48663Z" fill="black"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12.9218 1.85418L2.95217 2.53485C2.35499 2.57562 1.89209 3.05572 1.89209 3.63431V13.3311C1.89209 13.8748 2.07923 14.4029 2.42402 14.8325L4.57362 17.5104C4.92117 17.9433 5.46812 18.1817 6.03397 18.1469L17.0991 17.4658C17.6663 17.4309 18.1078 16.9761 18.1078 16.4269V5.4026C18.1078 5.06281 17.9362 4.74441 17.6481 4.54963L14.1453 2.18137C13.7883 1.94002 13.3564 1.82451 12.9218 1.85418ZM3.44654 3.78556C3.30788 3.6829 3.37387 3.46903 3.54806 3.45654L12.9889 2.77938C13.2897 2.75781 13.5886 2.84064 13.8318 3.01299L15.7261 4.35502C15.798 4.40597 15.7642 4.51596 15.6752 4.5208L5.67742 5.06454C5.37485 5.081 5.0762 4.99211 4.83563 4.814L3.44654 3.78556ZM5.20848 6.76913C5.20848 6.44433 5.47088 6.17604 5.80642 6.15777L16.3769 5.5821C16.7039 5.56429 16.9792 5.81577 16.9792 6.13232V15.6782C16.9792 16.0024 16.7177 16.2705 16.3829 16.2895L5.8793 16.8871C5.51537 16.9079 5.20848 16.6282 5.20848 16.2759V6.76913Z" fill="black"/>
+</g>
+<defs>
+<clipPath id="clip0_5364_42310">
+<rect width="20" height="20" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 23 - 0
web/app/components/base/icons/assets/public/files/html.svg

@@ -0,0 +1,23 @@
+<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_3055_14424)">
+<path d="M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z" fill="#EC5B27"/>
+</g>
+<g opacity="0.96">
+<path d="M10.2704 24.0002V18.3042H8.87042V20.4962H7.38242V18.3042H5.98242V24.0002H7.38242V21.7442H8.87042V24.0002H10.2704Z" fill="white"/>
+<path d="M15.2839 19.5522V18.3042H11.0839V19.5522H12.4839V24.0002H13.8839V19.5522H15.2839Z" fill="white"/>
+<path d="M21.4116 24.0002V18.3042H20.0356L18.7556 20.8162L17.4756 18.3042H16.0996V24.0002H17.4996V21.2722L18.3076 22.6802H19.2036L20.0116 21.2722V24.0002H21.4116Z" fill="white"/>
+<path d="M26.3525 24.0002V22.7522H23.9605V18.3042H22.5605V24.0002H26.3525Z" fill="white"/>
+</g>
+<path opacity="0.5" d="M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z" fill="white"/>
+<defs>
+<filter id="filter0_d_3055_14424" x="2" y="0.333496" width="28" height="33.3335" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3055_14424"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3055_14424" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 23 - 0
web/app/components/base/icons/assets/public/files/json.svg

@@ -0,0 +1,23 @@
+<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_3055_14428)">
+<path d="M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z" fill="#2D2D2E"/>
+</g>
+<g opacity="0.96">
+<path d="M9.83907 22.0479V18.3039H8.43907V22.0159C8.43907 22.5599 8.12707 22.7999 7.69507 22.7999C7.38307 22.7999 7.23907 22.6879 7.06307 22.5119L6.14307 23.4239C6.60707 23.8879 7.03107 24.0479 7.69507 24.0479C8.76707 24.0479 9.83907 23.3999 9.83907 22.0479Z" fill="white"/>
+<path d="M14.7321 22.2559C14.7321 21.7279 14.6121 21.3039 14.3081 21.0079C14.0681 20.7679 13.7001 20.6079 13.1881 20.5359L12.5001 20.4399C12.3001 20.4159 12.1801 20.3439 12.1081 20.2719C12.0201 20.1839 11.9961 20.0799 11.9961 20.0079C11.9961 19.7599 12.1961 19.4799 12.6841 19.4799C12.9321 19.4799 13.4041 19.4559 13.7641 19.8159L14.6441 18.9359C14.1561 18.4479 13.5401 18.2559 12.7241 18.2559C11.4281 18.2559 10.6441 19.0159 10.6441 20.0559C10.6441 20.5439 10.7721 20.9279 11.0361 21.1999C11.2921 21.4639 11.6761 21.6319 12.1801 21.7039L12.8681 21.7999C13.0521 21.8239 13.1721 21.8799 13.2441 21.9519C13.3241 22.0399 13.3561 22.1519 13.3561 22.2879C13.3561 22.6159 13.0921 22.7999 12.5401 22.7999C12.0841 22.7999 11.5641 22.6959 11.2681 22.3999L10.3721 23.2959C10.9481 23.8879 11.6601 24.0479 12.5321 24.0479C13.7321 24.0479 14.7321 23.4159 14.7321 22.2559Z" fill="white"/>
+<path d="M19.8023 21.1519C19.8023 20.2959 19.8263 19.4959 19.2263 18.8959C18.8103 18.4799 18.3303 18.2559 17.6343 18.2559C16.9383 18.2559 16.4583 18.4799 16.0423 18.8959C15.4423 19.4959 15.4663 20.2959 15.4663 21.1519C15.4663 22.0079 15.4423 22.8079 16.0423 23.4079C16.4583 23.8239 16.9383 24.0479 17.6343 24.0479C18.3303 24.0479 18.8103 23.8239 19.2263 23.4079C19.8263 22.8079 19.8023 22.0079 19.8023 21.1519ZM18.4023 21.1519C18.4023 22.1919 18.3223 22.3759 18.1943 22.5439C18.0903 22.6799 17.8903 22.7999 17.6343 22.7999C17.3783 22.7999 17.1783 22.6799 17.0743 22.5439C16.9463 22.3759 16.8663 22.1919 16.8663 21.1519C16.8663 20.1119 16.9463 19.9199 17.0743 19.7519C17.1783 19.6159 17.3783 19.5039 17.6343 19.5039C17.8903 19.5039 18.0903 19.6159 18.1943 19.7519C18.3223 19.9199 18.4023 20.1119 18.4023 21.1519Z" fill="white"/>
+<path d="M25.2154 23.9999V18.3039H23.8154V21.1679L21.9914 18.3039H20.7674V23.9999H22.1674V21.1359L23.9914 23.9999H25.2154Z" fill="white"/>
+</g>
+<path opacity="0.5" d="M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z" fill="white"/>
+<defs>
+<filter id="filter0_d_3055_14428" x="2" y="0.333496" width="28" height="33.3335" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3055_14428"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3055_14428" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 22 - 0
web/app/components/base/icons/assets/public/files/pdf.svg

@@ -0,0 +1,22 @@
+<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_3055_14420)">
+<path d="M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z" fill="#DD3633"/>
+</g>
+<g opacity="0.96">
+<path d="M13.2801 20.1362C13.2801 19.2002 12.6001 18.3042 11.3361 18.3042H9.08008V24.0002H10.4801V21.9682H11.3361C12.6001 21.9682 13.2801 21.0722 13.2801 20.1362ZM11.8801 20.1362C11.8801 20.4322 11.6561 20.7122 11.2721 20.7122H10.4801V19.5602H11.2721C11.6561 19.5602 11.8801 19.8402 11.8801 20.1362Z" fill="white"/>
+<path d="M18.3357 21.1522C18.3357 20.2562 18.4077 19.5282 17.7437 18.8642C17.3517 18.4722 16.7997 18.3042 16.2077 18.3042H14.0957V24.0002H16.2077C16.7997 24.0002 17.3517 23.8322 17.7437 23.4402C18.4077 22.7762 18.3357 22.0482 18.3357 21.1522ZM16.9357 21.1522C16.9357 22.1202 16.8957 22.2722 16.7837 22.4322C16.6557 22.6242 16.4637 22.7522 16.1117 22.7522H15.4957V19.5522H16.1117C16.4637 19.5522 16.6557 19.6802 16.7837 19.8722C16.8957 20.0322 16.9357 20.1922 16.9357 21.1522Z" fill="white"/>
+<path d="M23.1786 19.5522V18.3042H19.3066V24.0002H20.7066V21.8002H22.8186V20.5522H20.7066V19.5522H23.1786Z" fill="white"/>
+</g>
+<path opacity="0.5" d="M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z" fill="white"/>
+<defs>
+<filter id="filter0_d_3055_14420" x="2" y="0.333496" width="28" height="33.3335" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3055_14420"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3055_14420" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 23 - 0
web/app/components/base/icons/assets/public/files/txt.svg

@@ -0,0 +1,23 @@
+<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_3055_14432)">
+<path d="M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z" fill="#E3E5E8"/>
+<path d="M4.25 7.73349C4.25 6.60926 4.25019 5.78113 4.30367 5.12666C4.3569 4.47511 4.46169 4.01774 4.65873 3.63103C5.01825 2.92542 5.59193 2.35175 6.29754 1.99222C6.68424 1.79518 7.14162 1.6904 7.79317 1.63716C8.44763 1.58369 9.27577 1.5835 10.4 1.5835H18.5631L27.75 10.7704V24.2668C27.75 25.3911 27.7498 26.2192 27.6963 26.8737C27.6431 27.5252 27.5383 27.9826 27.3413 28.3693C26.9817 29.0749 26.4081 29.6486 25.7025 30.0081C25.3158 30.2051 24.8584 30.3099 24.2068 30.3632C23.5524 30.4166 22.7242 30.4168 21.6 30.4168H10.4C9.27577 30.4168 8.44763 30.4166 7.79317 30.3632C7.14162 30.3099 6.68424 30.2051 6.29754 30.0081C5.59193 29.6486 5.01825 29.0749 4.65873 28.3693C4.46169 27.9826 4.3569 27.5252 4.30367 26.8737C4.25019 26.2192 4.25 25.3911 4.25 24.2668V7.73349Z" stroke="black" stroke-opacity="0.03" stroke-width="0.5"/>
+</g>
+<g opacity="0.96">
+<path d="M13.2254 19.5522V18.3042H9.02539V19.5522H10.4254V24.0002H11.8254V19.5522H13.2254Z" fill="#667085"/>
+<path d="M18.5371 24.0002L16.7611 21.0802L18.4251 18.3042H16.8331L16.0011 19.9122L15.1691 18.3042H13.5771L15.2411 21.0802L13.4651 24.0002H15.0651L16.0011 22.2482L16.9371 24.0002H18.5371Z" fill="#667085"/>
+<path d="M22.9754 19.5522V18.3042H18.7754V19.5522H20.1754V24.0002H21.5754V19.5522H22.9754Z" fill="#667085"/>
+</g>
+<path opacity="0.5" d="M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z" fill="white"/>
+<defs>
+<filter id="filter0_d_3055_14432" x="2" y="0.333496" width="28" height="33.3335" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3055_14432"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3055_14432" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 23 - 0
web/app/components/base/icons/assets/public/files/unknow.svg

@@ -0,0 +1,23 @@
+<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_3055_14436)">
+<path d="M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z" fill="#E3E5E8"/>
+<path d="M4.25 7.73349C4.25 6.60926 4.25019 5.78113 4.30367 5.12666C4.3569 4.47511 4.46169 4.01774 4.65873 3.63103C5.01825 2.92542 5.59193 2.35175 6.29754 1.99222C6.68424 1.79518 7.14162 1.6904 7.79317 1.63716C8.44763 1.58369 9.27577 1.5835 10.4 1.5835H18.5631L27.75 10.7704V24.2668C27.75 25.3911 27.7498 26.2192 27.6963 26.8737C27.6431 27.5252 27.5383 27.9826 27.3413 28.3693C26.9817 29.0749 26.4081 29.6486 25.7025 30.0081C25.3158 30.2051 24.8584 30.3099 24.2068 30.3632C23.5524 30.4166 22.7242 30.4168 21.6 30.4168H10.4C9.27577 30.4168 8.44763 30.4166 7.79317 30.3632C7.14162 30.3099 6.68424 30.2051 6.29754 30.0081C5.59193 29.6486 5.01825 29.0749 4.65873 28.3693C4.46169 27.9826 4.3569 27.5252 4.30367 26.8737C4.25019 26.2192 4.25 25.3911 4.25 24.2668V7.73349Z" stroke="black" stroke-opacity="0.03" stroke-width="0.5"/>
+</g>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9998 23.1992C15.8014 23.1992 15.6039 23.1968 15.4077 23.1924V24.0549C15.4077 24.3819 15.6728 24.647 15.9998 24.647C16.3268 24.647 16.592 24.3819 16.592 24.0549V23.1924C16.3957 23.1968 16.1983 23.1992 15.9998 23.1992Z" fill="#98A2B3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0984 22.8838L11.757 23.8593C11.649 24.168 11.8117 24.5058 12.1203 24.6138C12.185 24.6364 12.251 24.6472 12.3159 24.6472C12.5605 24.6472 12.7894 24.4944 12.8747 24.2505L13.2936 23.0534C12.8807 23.0073 12.481 22.9506 12.0984 22.8838Z" fill="#98A2B3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M20.2431 23.8593L19.9018 22.8838C19.5192 22.9506 19.1195 23.0073 18.7065 23.0534L19.1254 24.2505C19.2108 24.4944 19.4396 24.6472 19.6843 24.6472C19.7491 24.6472 19.8151 24.6364 19.8798 24.6138C20.1885 24.5058 20.3511 24.168 20.2431 23.8593Z" fill="#98A2B3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1624 17.2634C20.2697 17.6416 20.3254 18.0369 20.3254 18.4409C20.3254 18.9087 20.05 19.3327 19.6226 19.5228C19.5564 19.5522 17.9801 20.2436 16.0359 20.2436C14.0917 20.2436 12.5153 19.5522 12.4492 19.5228C12.0218 19.3327 11.7464 18.9086 11.7464 18.4409C11.7464 18.0312 11.8037 17.6305 11.914 17.2476C10.3343 17.5645 8.5 18.2009 8.5 19.4464C8.5 20.2859 9.32512 20.9477 10.9525 21.4134C11.4194 21.547 11.9381 21.66 12.4949 21.7506C12.8783 21.813 13.28 21.8648 13.6953 21.9056C14.2455 21.9597 14.8197 21.9942 15.4079 22.0082C15.6039 22.0128 15.8013 22.0153 16 22.0153C16.1987 22.0153 16.3962 22.0128 16.5921 22.0082C17.1803 21.9943 17.7545 21.9596 18.3047 21.9056C18.72 21.8648 19.1217 21.8131 19.5051 21.7506C20.062 21.66 20.5807 21.547 21.0476 21.4134C22.6749 20.9477 23.5 20.2859 23.5 19.4464C23.5 18.2187 21.7108 17.5833 20.1624 17.2634Z" fill="#98A2B3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M18.8441 17.1144C18.7585 16.9335 18.6559 16.7622 18.5384 16.6025C18.4174 16.4382 18.2809 16.286 18.1307 16.1486C17.5784 15.6437 16.8433 15.3354 16.036 15.3354C15.2318 15.3354 14.499 15.6411 13.9476 16.1426C13.7974 16.2791 13.6609 16.4303 13.5399 16.5937C13.4217 16.753 13.3185 16.924 13.2322 17.1048C13.039 17.5095 12.9307 17.9624 12.9307 18.4407C12.9307 18.4407 14.321 19.0592 16.036 19.0592C17.751 19.0592 19.1412 18.4407 19.1412 18.4407C19.1412 17.9662 19.0344 17.5167 18.8441 17.1144Z" fill="#98A2B3"/>
+<path opacity="0.5" d="M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z" fill="white"/>
+<defs>
+<filter id="filter0_d_3055_14436" x="2" y="0.333496" width="28" height="33.3335" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3055_14436"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3055_14436" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 18 - 0
web/app/components/base/icons/assets/public/files/xlsx.svg

@@ -0,0 +1,18 @@
+<svg width="24" height="26" viewBox="0 0 24 26" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_5938_927)">
+<path d="M3 5.8C3 4.11984 3 3.27976 3.32698 2.63803C3.6146 2.07354 4.07354 1.6146 4.63803 1.32698C5.27976 1 6.11984 1 7.8 1H14L21 8V18.2C21 19.8802 21 20.7202 20.673 21.362C20.3854 21.9265 19.9265 22.3854 19.362 22.673C18.7202 23 17.8802 23 16.2 23H7.8C6.11984 23 5.27976 23 4.63803 22.673C4.07354 22.3854 3.6146 21.9265 3.32698 21.362C3 20.7202 3 19.8802 3 18.2V5.8Z" fill="#169951"/>
+</g>
+<path opacity="0.5" d="M14 1L21 8H16C14.8954 8 14 7.10457 14 6V1Z" fill="white"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M17 12C17.5523 12 18 12.4477 18 13V18C18 18.5523 17.5523 19 17 19H7C6.44772 19 6 18.5523 6 18V13C6 12.4477 6.44772 12 7 12H17ZM11.5 13H7L7 15H11.5V13ZM12.5 18H17V16H12.5V18ZM11.5 16V18H7L7 16H11.5ZM12.5 15H17V13H12.5V15Z" fill="white" fill-opacity="0.96"/>
+<defs>
+<filter id="filter0_d_5938_927" x="1" y="0" width="22" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5938_927"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5938_927" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 5 - 0
web/app/components/base/icons/assets/vender/line/editor/bezier-curve-03.svg

@@ -0,0 +1,5 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="bezier-curve-03">
+<path id="Icon" d="M5.42857 3.5L2.57143 8.5M3 9.5H8.9999M9.42857 8.5L6.57143 3.5M1.8 10.5H2.2C2.48003 10.5 2.62004 10.5 2.727 10.4455C2.82108 10.3976 2.89757 10.3211 2.9455 10.227C3 10.12 3 9.98003 3 9.7V9.3C3 9.01997 3 8.87996 2.9455 8.773C2.89757 8.67892 2.82108 8.60243 2.727 8.5545C2.62004 8.5 2.48003 8.5 2.2 8.5H1.8C1.51997 8.5 1.37996 8.5 1.273 8.5545C1.17892 8.60243 1.10243 8.67892 1.0545 8.773C1 8.87996 1 9.01997 1 9.3V9.7C1 9.98003 1 10.12 1.0545 10.227C1.10243 10.3211 1.17892 10.3976 1.273 10.4455C1.37996 10.5 1.51997 10.5 1.8 10.5ZM9.8 10.5H10.2C10.48 10.5 10.62 10.5 10.727 10.4455C10.8211 10.3976 10.8976 10.3211 10.9455 10.227C11 10.12 11 9.98003 11 9.7V9.3C11 9.01997 11 8.87996 10.9455 8.773C10.8976 8.67892 10.8211 8.60243 10.727 8.5545C10.62 8.5 10.48 8.5 10.2 8.5H9.8C9.51997 8.5 9.37996 8.5 9.273 8.5545C9.17892 8.60243 9.10243 8.67892 9.0545 8.773C9 8.87996 9 9.01997 9 9.3V9.7C9 9.98003 9 10.12 9.0545 10.227C9.10243 10.3211 9.17892 10.3976 9.273 10.4455C9.37996 10.5 9.51997 10.5 9.8 10.5ZM5.8 3.5H6.2C6.48003 3.5 6.62004 3.5 6.727 3.4455C6.82108 3.39757 6.89757 3.32108 6.9455 3.227C7 3.12004 7 2.98003 7 2.7V2.3C7 2.01997 7 1.87996 6.9455 1.773C6.89757 1.67892 6.82108 1.60243 6.727 1.5545C6.62004 1.5 6.48003 1.5 6.2 1.5H5.8C5.51997 1.5 5.37996 1.5 5.273 1.5545C5.17892 1.60243 5.10243 1.67892 5.0545 1.773C5 1.87996 5 2.01997 5 2.3V2.7C5 2.98003 5 3.12004 5.0545 3.227C5.10243 3.32108 5.17892 3.39757 5.273 3.4455C5.37996 3.5 5.51997 3.5 5.8 3.5Z" stroke="#667085" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+</svg>

+ 5 - 0
web/app/components/base/icons/assets/vender/line/editor/type-square.svg

@@ -0,0 +1,5 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="type-square">
+<path id="Icon" d="M4 3.5H8M6 3.5V8.5M3.9 10.5H8.1C8.94008 10.5 9.36012 10.5 9.68099 10.3365C9.96323 10.1927 10.1927 9.96323 10.3365 9.68099C10.5 9.36012 10.5 8.94008 10.5 8.1V3.9C10.5 3.05992 10.5 2.63988 10.3365 2.31901C10.1927 2.03677 9.96323 1.8073 9.68099 1.66349C9.36012 1.5 8.94008 1.5 8.1 1.5H3.9C3.05992 1.5 2.63988 1.5 2.31901 1.66349C2.03677 1.8073 1.8073 2.03677 1.66349 2.31901C1.5 2.63988 1.5 3.05992 1.5 3.9V8.1C1.5 8.94008 1.5 9.36012 1.66349 9.68099C1.8073 9.96323 2.03677 10.1927 2.31901 10.3365C2.63988 10.5 3.05992 10.5 3.9 10.5Z" stroke="#667085" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+</svg>

+ 10 - 0
web/app/components/base/icons/assets/vender/line/general/target-04.svg

@@ -0,0 +1,10 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="Left Icon" clip-path="url(#clip0_10386_42171)">
+<path id="Icon" d="M7.99998 4V2.5L9.49998 1L9.99998 2L11 2.5L9.49998 4H7.99998ZM7.99998 4L5.99999 5.99997M11 6C11 8.76142 8.76142 11 6 11C3.23858 11 1 8.76142 1 6C1 3.23858 3.23858 1 6 1M8.5 6C8.5 7.38071 7.38071 8.5 6 8.5C4.61929 8.5 3.5 7.38071 3.5 6C3.5 4.61929 4.61929 3.5 6 3.5" stroke="#667085" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+<defs>
+<clipPath id="clip0_10386_42171">
+<rect width="12" height="12" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 5 - 0
web/app/components/base/icons/assets/vender/solid/editor/citations.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="citations">
+<path id="Subtract" d="M0.666992 7.99996C0.666992 3.94987 3.95024 0.666626 8.00033 0.666626C12.0504 0.666626 15.3337 3.94987 15.3337 7.99996C15.3337 12.05 12.0504 15.3333 8.00033 15.3333C3.95024 15.3333 0.666992 12.05 0.666992 7.99996ZM4.66699 7.9801V9.97196H7.35742V7.48922H5.87533C5.85644 7.21231 5.90365 6.94484 6.01693 6.68681C6.2372 6.19592 6.66829 5.84979 7.31022 5.6484V4.66663C6.44803 4.83655 5.79036 5.19527 5.33724 5.7428C4.89041 6.29032 4.66699 7.03609 4.66699 7.9801ZM10.0264 6.70569C10.2466 6.19592 10.6746 5.84349 11.3102 5.6484V4.66663C10.4732 4.83655 9.82183 5.19212 9.35612 5.73336C8.8967 6.27459 8.66699 7.02351 8.66699 7.9801V9.97196H11.3574V7.48922H9.87533C9.85015 7.23748 9.9005 6.9763 10.0264 6.70569Z" fill="#FD853A"/>
+</g>
+</svg>

+ 83 - 0
web/app/components/base/icons/src/public/common/Notion.json

@@ -0,0 +1,83 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "20",
+			"height": "20",
+			"viewBox": "0 0 20 20",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"clip-path": "url(#clip0_5364_42310)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"fill-rule": "evenodd",
+							"clip-rule": "evenodd",
+							"d": "M3.5725 18.2611L1.4229 15.5832C0.905706 14.9389 0.625 14.1466 0.625 13.3312V3.63437C0.625 2.4129 1.60224 1.39936 2.86295 1.31328L12.8326 0.632614C13.5569 0.583164 14.2768 0.775682 14.8717 1.17794L18.3745 3.5462C19.0015 3.97012 19.375 4.66312 19.375 5.40266V16.427C19.375 17.6223 18.4141 18.6121 17.1798 18.688L6.11458 19.3692C5.12958 19.4298 4.17749 19.0148 3.5725 18.2611Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M7.03006 8.48663V8.35968C7.03006 8.03787 7.28779 7.77098 7.61997 7.7488L10.0396 7.58726L13.3857 12.5146V8.19003L12.5244 8.07522V8.01492C12.5244 7.68933 12.788 7.42068 13.1244 7.40344L15.326 7.29066V7.60749C15.326 7.75622 15.2154 7.88343 15.0638 7.90907L14.534 7.99868V15.0022L13.8691 15.2309C13.3136 15.4219 12.6952 15.2174 12.3772 14.7376L9.12879 9.83568V14.5143L10.1287 14.7056L10.1147 14.7984C10.0711 15.0889 9.82028 15.3086 9.51687 15.3221L7.03006 15.4328C6.99718 15.1204 7.23132 14.8409 7.55431 14.807L7.88143 14.7726V8.53447L7.03006 8.48663Z",
+							"fill": "black"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"fill-rule": "evenodd",
+							"clip-rule": "evenodd",
+							"d": "M12.9218 1.85418L2.95217 2.53485C2.35499 2.57562 1.89209 3.05572 1.89209 3.63431V13.3311C1.89209 13.8748 2.07923 14.4029 2.42402 14.8325L4.57362 17.5104C4.92117 17.9433 5.46812 18.1817 6.03397 18.1469L17.0991 17.4658C17.6663 17.4309 18.1078 16.9761 18.1078 16.4269V5.4026C18.1078 5.06281 17.9362 4.74441 17.6481 4.54963L14.1453 2.18137C13.7883 1.94002 13.3564 1.82451 12.9218 1.85418ZM3.44654 3.78556C3.30788 3.6829 3.37387 3.46903 3.54806 3.45654L12.9889 2.77938C13.2897 2.75781 13.5886 2.84064 13.8318 3.01299L15.7261 4.35502C15.798 4.40597 15.7642 4.51596 15.6752 4.5208L5.67742 5.06454C5.37485 5.081 5.0762 4.99211 4.83563 4.814L3.44654 3.78556ZM5.20848 6.76913C5.20848 6.44433 5.47088 6.17604 5.80642 6.15777L16.3769 5.5821C16.7039 5.56429 16.9792 5.81577 16.9792 6.13232V15.6782C16.9792 16.0024 16.7177 16.2705 16.3829 16.2895L5.8793 16.8871C5.51537 16.9079 5.20848 16.6282 5.20848 16.2759V6.76913Z",
+							"fill": "black"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "clipPath",
+						"attributes": {
+							"id": "clip0_5364_42310"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "rect",
+								"attributes": {
+									"width": "20",
+									"height": "20",
+									"fill": "white"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Notion"
+}

+ 16 - 0
web/app/components/base/icons/src/public/common/Notion.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Notion.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Notion'
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/public/common/index.ts

@@ -1,3 +1,4 @@
 export { default as Dify } from './Dify'
 export { default as Github } from './Github'
 export { default as MessageChatSquare } from './MessageChatSquare'
+export { default as Notion } from './Notion'

+ 178 - 0
web/app/components/base/icons/src/public/files/Html.json

@@ -0,0 +1,178 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "32",
+			"height": "34",
+			"viewBox": "0 0 32 34",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"filter": "url(#filter0_d_3055_14424)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z",
+							"fill": "#EC5B27"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"opacity": "0.96"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M10.2704 24.0002V18.3042H8.87042V20.4962H7.38242V18.3042H5.98242V24.0002H7.38242V21.7442H8.87042V24.0002H10.2704Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M15.2839 19.5522V18.3042H11.0839V19.5522H12.4839V24.0002H13.8839V19.5522H15.2839Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M21.4116 24.0002V18.3042H20.0356L18.7556 20.8162L17.4756 18.3042H16.0996V24.0002H17.4996V21.2722L18.3076 22.6802H19.2036L20.0116 21.2722V24.0002H21.4116Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M26.3525 24.0002V22.7522H23.9605V18.3042H22.5605V24.0002H26.3525Z",
+							"fill": "white"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"opacity": "0.5",
+					"d": "M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z",
+					"fill": "white"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "filter",
+						"attributes": {
+							"id": "filter0_d_3055_14424",
+							"x": "2",
+							"y": "0.333496",
+							"width": "28",
+							"height": "33.3335",
+							"filterUnits": "userSpaceOnUse",
+							"color-interpolation-filters": "sRGB"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "feFlood",
+								"attributes": {
+									"flood-opacity": "0",
+									"result": "BackgroundImageFix"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"in": "SourceAlpha",
+									"type": "matrix",
+									"values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
+									"result": "hardAlpha"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feOffset",
+								"attributes": {
+									"dy": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feGaussianBlur",
+								"attributes": {
+									"stdDeviation": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"type": "matrix",
+									"values": "0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in2": "BackgroundImageFix",
+									"result": "effect1_dropShadow_3055_14424"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in": "SourceGraphic",
+									"in2": "effect1_dropShadow_3055_14424",
+									"result": "shape"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Html"
+}

+ 16 - 0
web/app/components/base/icons/src/public/files/Html.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Html.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Html'
+
+export default Icon

+ 178 - 0
web/app/components/base/icons/src/public/files/Json.json

@@ -0,0 +1,178 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "32",
+			"height": "34",
+			"viewBox": "0 0 32 34",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"filter": "url(#filter0_d_3055_14428)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z",
+							"fill": "#2D2D2E"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"opacity": "0.96"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M9.83907 22.0479V18.3039H8.43907V22.0159C8.43907 22.5599 8.12707 22.7999 7.69507 22.7999C7.38307 22.7999 7.23907 22.6879 7.06307 22.5119L6.14307 23.4239C6.60707 23.8879 7.03107 24.0479 7.69507 24.0479C8.76707 24.0479 9.83907 23.3999 9.83907 22.0479Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M14.7321 22.2559C14.7321 21.7279 14.6121 21.3039 14.3081 21.0079C14.0681 20.7679 13.7001 20.6079 13.1881 20.5359L12.5001 20.4399C12.3001 20.4159 12.1801 20.3439 12.1081 20.2719C12.0201 20.1839 11.9961 20.0799 11.9961 20.0079C11.9961 19.7599 12.1961 19.4799 12.6841 19.4799C12.9321 19.4799 13.4041 19.4559 13.7641 19.8159L14.6441 18.9359C14.1561 18.4479 13.5401 18.2559 12.7241 18.2559C11.4281 18.2559 10.6441 19.0159 10.6441 20.0559C10.6441 20.5439 10.7721 20.9279 11.0361 21.1999C11.2921 21.4639 11.6761 21.6319 12.1801 21.7039L12.8681 21.7999C13.0521 21.8239 13.1721 21.8799 13.2441 21.9519C13.3241 22.0399 13.3561 22.1519 13.3561 22.2879C13.3561 22.6159 13.0921 22.7999 12.5401 22.7999C12.0841 22.7999 11.5641 22.6959 11.2681 22.3999L10.3721 23.2959C10.9481 23.8879 11.6601 24.0479 12.5321 24.0479C13.7321 24.0479 14.7321 23.4159 14.7321 22.2559Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M19.8023 21.1519C19.8023 20.2959 19.8263 19.4959 19.2263 18.8959C18.8103 18.4799 18.3303 18.2559 17.6343 18.2559C16.9383 18.2559 16.4583 18.4799 16.0423 18.8959C15.4423 19.4959 15.4663 20.2959 15.4663 21.1519C15.4663 22.0079 15.4423 22.8079 16.0423 23.4079C16.4583 23.8239 16.9383 24.0479 17.6343 24.0479C18.3303 24.0479 18.8103 23.8239 19.2263 23.4079C19.8263 22.8079 19.8023 22.0079 19.8023 21.1519ZM18.4023 21.1519C18.4023 22.1919 18.3223 22.3759 18.1943 22.5439C18.0903 22.6799 17.8903 22.7999 17.6343 22.7999C17.3783 22.7999 17.1783 22.6799 17.0743 22.5439C16.9463 22.3759 16.8663 22.1919 16.8663 21.1519C16.8663 20.1119 16.9463 19.9199 17.0743 19.7519C17.1783 19.6159 17.3783 19.5039 17.6343 19.5039C17.8903 19.5039 18.0903 19.6159 18.1943 19.7519C18.3223 19.9199 18.4023 20.1119 18.4023 21.1519Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M25.2154 23.9999V18.3039H23.8154V21.1679L21.9914 18.3039H20.7674V23.9999H22.1674V21.1359L23.9914 23.9999H25.2154Z",
+							"fill": "white"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"opacity": "0.5",
+					"d": "M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z",
+					"fill": "white"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "filter",
+						"attributes": {
+							"id": "filter0_d_3055_14428",
+							"x": "2",
+							"y": "0.333496",
+							"width": "28",
+							"height": "33.3335",
+							"filterUnits": "userSpaceOnUse",
+							"color-interpolation-filters": "sRGB"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "feFlood",
+								"attributes": {
+									"flood-opacity": "0",
+									"result": "BackgroundImageFix"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"in": "SourceAlpha",
+									"type": "matrix",
+									"values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
+									"result": "hardAlpha"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feOffset",
+								"attributes": {
+									"dy": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feGaussianBlur",
+								"attributes": {
+									"stdDeviation": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"type": "matrix",
+									"values": "0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in2": "BackgroundImageFix",
+									"result": "effect1_dropShadow_3055_14428"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in": "SourceGraphic",
+									"in2": "effect1_dropShadow_3055_14428",
+									"result": "shape"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Json"
+}

+ 16 - 0
web/app/components/base/icons/src/public/files/Json.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Json.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Json'
+
+export default Icon

+ 169 - 0
web/app/components/base/icons/src/public/files/Pdf.json

@@ -0,0 +1,169 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "32",
+			"height": "34",
+			"viewBox": "0 0 32 34",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"filter": "url(#filter0_d_3055_14420)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z",
+							"fill": "#DD3633"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"opacity": "0.96"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M13.2801 20.1362C13.2801 19.2002 12.6001 18.3042 11.3361 18.3042H9.08008V24.0002H10.4801V21.9682H11.3361C12.6001 21.9682 13.2801 21.0722 13.2801 20.1362ZM11.8801 20.1362C11.8801 20.4322 11.6561 20.7122 11.2721 20.7122H10.4801V19.5602H11.2721C11.6561 19.5602 11.8801 19.8402 11.8801 20.1362Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M18.3357 21.1522C18.3357 20.2562 18.4077 19.5282 17.7437 18.8642C17.3517 18.4722 16.7997 18.3042 16.2077 18.3042H14.0957V24.0002H16.2077C16.7997 24.0002 17.3517 23.8322 17.7437 23.4402C18.4077 22.7762 18.3357 22.0482 18.3357 21.1522ZM16.9357 21.1522C16.9357 22.1202 16.8957 22.2722 16.7837 22.4322C16.6557 22.6242 16.4637 22.7522 16.1117 22.7522H15.4957V19.5522H16.1117C16.4637 19.5522 16.6557 19.6802 16.7837 19.8722C16.8957 20.0322 16.9357 20.1922 16.9357 21.1522Z",
+							"fill": "white"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M23.1786 19.5522V18.3042H19.3066V24.0002H20.7066V21.8002H22.8186V20.5522H20.7066V19.5522H23.1786Z",
+							"fill": "white"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"opacity": "0.5",
+					"d": "M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z",
+					"fill": "white"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "filter",
+						"attributes": {
+							"id": "filter0_d_3055_14420",
+							"x": "2",
+							"y": "0.333496",
+							"width": "28",
+							"height": "33.3335",
+							"filterUnits": "userSpaceOnUse",
+							"color-interpolation-filters": "sRGB"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "feFlood",
+								"attributes": {
+									"flood-opacity": "0",
+									"result": "BackgroundImageFix"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"in": "SourceAlpha",
+									"type": "matrix",
+									"values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
+									"result": "hardAlpha"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feOffset",
+								"attributes": {
+									"dy": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feGaussianBlur",
+								"attributes": {
+									"stdDeviation": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"type": "matrix",
+									"values": "0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in2": "BackgroundImageFix",
+									"result": "effect1_dropShadow_3055_14420"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in": "SourceGraphic",
+									"in2": "effect1_dropShadow_3055_14420",
+									"result": "shape"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Pdf"
+}

+ 16 - 0
web/app/components/base/icons/src/public/files/Pdf.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Pdf.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Pdf'
+
+export default Icon

+ 180 - 0
web/app/components/base/icons/src/public/files/Txt.json

@@ -0,0 +1,180 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "32",
+			"height": "34",
+			"viewBox": "0 0 32 34",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"filter": "url(#filter0_d_3055_14432)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z",
+							"fill": "#E3E5E8"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4.25 7.73349C4.25 6.60926 4.25019 5.78113 4.30367 5.12666C4.3569 4.47511 4.46169 4.01774 4.65873 3.63103C5.01825 2.92542 5.59193 2.35175 6.29754 1.99222C6.68424 1.79518 7.14162 1.6904 7.79317 1.63716C8.44763 1.58369 9.27577 1.5835 10.4 1.5835H18.5631L27.75 10.7704V24.2668C27.75 25.3911 27.7498 26.2192 27.6963 26.8737C27.6431 27.5252 27.5383 27.9826 27.3413 28.3693C26.9817 29.0749 26.4081 29.6486 25.7025 30.0081C25.3158 30.2051 24.8584 30.3099 24.2068 30.3632C23.5524 30.4166 22.7242 30.4168 21.6 30.4168H10.4C9.27577 30.4168 8.44763 30.4166 7.79317 30.3632C7.14162 30.3099 6.68424 30.2051 6.29754 30.0081C5.59193 29.6486 5.01825 29.0749 4.65873 28.3693C4.46169 27.9826 4.3569 27.5252 4.30367 26.8737C4.25019 26.2192 4.25 25.3911 4.25 24.2668V7.73349Z",
+							"stroke": "black",
+							"stroke-opacity": "0.03",
+							"stroke-width": "0.5"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"opacity": "0.96"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M13.2254 19.5522V18.3042H9.02539V19.5522H10.4254V24.0002H11.8254V19.5522H13.2254Z",
+							"fill": "#667085"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M18.5371 24.0002L16.7611 21.0802L18.4251 18.3042H16.8331L16.0011 19.9122L15.1691 18.3042H13.5771L15.2411 21.0802L13.4651 24.0002H15.0651L16.0011 22.2482L16.9371 24.0002H18.5371Z",
+							"fill": "#667085"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M22.9754 19.5522V18.3042H18.7754V19.5522H20.1754V24.0002H21.5754V19.5522H22.9754Z",
+							"fill": "#667085"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"opacity": "0.5",
+					"d": "M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z",
+					"fill": "white"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "filter",
+						"attributes": {
+							"id": "filter0_d_3055_14432",
+							"x": "2",
+							"y": "0.333496",
+							"width": "28",
+							"height": "33.3335",
+							"filterUnits": "userSpaceOnUse",
+							"color-interpolation-filters": "sRGB"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "feFlood",
+								"attributes": {
+									"flood-opacity": "0",
+									"result": "BackgroundImageFix"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"in": "SourceAlpha",
+									"type": "matrix",
+									"values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
+									"result": "hardAlpha"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feOffset",
+								"attributes": {
+									"dy": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feGaussianBlur",
+								"attributes": {
+									"stdDeviation": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"type": "matrix",
+									"values": "0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in2": "BackgroundImageFix",
+									"result": "effect1_dropShadow_3055_14432"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in": "SourceGraphic",
+									"in2": "effect1_dropShadow_3055_14432",
+									"result": "shape"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Txt"
+}

+ 16 - 0
web/app/components/base/icons/src/public/files/Txt.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Txt.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Txt'
+
+export default Icon

+ 199 - 0
web/app/components/base/icons/src/public/files/Unknow.json

@@ -0,0 +1,199 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "32",
+			"height": "34",
+			"viewBox": "0 0 32 34",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"filter": "url(#filter0_d_3055_14436)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4 7.73349C4 5.49329 4 4.37318 4.43597 3.51753C4.81947 2.76489 5.43139 2.15296 6.18404 1.76947C7.03969 1.3335 8.15979 1.3335 10.4 1.3335H18.6667L28 10.6668V24.2668C28 26.507 28 27.6271 27.564 28.4828C27.1805 29.2354 26.5686 29.8474 25.816 30.2309C24.9603 30.6668 23.8402 30.6668 21.6 30.6668H10.4C8.15979 30.6668 7.03969 30.6668 6.18404 30.2309C5.43139 29.8474 4.81947 29.2354 4.43597 28.4828C4 27.6271 4 26.507 4 24.2668V7.73349Z",
+							"fill": "#E3E5E8"
+						},
+						"children": []
+					},
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M4.25 7.73349C4.25 6.60926 4.25019 5.78113 4.30367 5.12666C4.3569 4.47511 4.46169 4.01774 4.65873 3.63103C5.01825 2.92542 5.59193 2.35175 6.29754 1.99222C6.68424 1.79518 7.14162 1.6904 7.79317 1.63716C8.44763 1.58369 9.27577 1.5835 10.4 1.5835H18.5631L27.75 10.7704V24.2668C27.75 25.3911 27.7498 26.2192 27.6963 26.8737C27.6431 27.5252 27.5383 27.9826 27.3413 28.3693C26.9817 29.0749 26.4081 29.6486 25.7025 30.0081C25.3158 30.2051 24.8584 30.3099 24.2068 30.3632C23.5524 30.4166 22.7242 30.4168 21.6 30.4168H10.4C9.27577 30.4168 8.44763 30.4166 7.79317 30.3632C7.14162 30.3099 6.68424 30.2051 6.29754 30.0081C5.59193 29.6486 5.01825 29.0749 4.65873 28.3693C4.46169 27.9826 4.3569 27.5252 4.30367 26.8737C4.25019 26.2192 4.25 25.3911 4.25 24.2668V7.73349Z",
+							"stroke": "black",
+							"stroke-opacity": "0.03",
+							"stroke-width": "0.5"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M15.9998 23.1992C15.8014 23.1992 15.6039 23.1968 15.4077 23.1924V24.0549C15.4077 24.3819 15.6728 24.647 15.9998 24.647C16.3268 24.647 16.592 24.3819 16.592 24.0549V23.1924C16.3957 23.1968 16.1983 23.1992 15.9998 23.1992Z",
+					"fill": "#98A2B3"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M12.0984 22.8838L11.757 23.8593C11.649 24.168 11.8117 24.5058 12.1203 24.6138C12.185 24.6364 12.251 24.6472 12.3159 24.6472C12.5605 24.6472 12.7894 24.4944 12.8747 24.2505L13.2936 23.0534C12.8807 23.0073 12.481 22.9506 12.0984 22.8838Z",
+					"fill": "#98A2B3"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M20.2431 23.8593L19.9018 22.8838C19.5192 22.9506 19.1195 23.0073 18.7065 23.0534L19.1254 24.2505C19.2108 24.4944 19.4396 24.6472 19.6843 24.6472C19.7491 24.6472 19.8151 24.6364 19.8798 24.6138C20.1885 24.5058 20.3511 24.168 20.2431 23.8593Z",
+					"fill": "#98A2B3"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M20.1624 17.2634C20.2697 17.6416 20.3254 18.0369 20.3254 18.4409C20.3254 18.9087 20.05 19.3327 19.6226 19.5228C19.5564 19.5522 17.9801 20.2436 16.0359 20.2436C14.0917 20.2436 12.5153 19.5522 12.4492 19.5228C12.0218 19.3327 11.7464 18.9086 11.7464 18.4409C11.7464 18.0312 11.8037 17.6305 11.914 17.2476C10.3343 17.5645 8.5 18.2009 8.5 19.4464C8.5 20.2859 9.32512 20.9477 10.9525 21.4134C11.4194 21.547 11.9381 21.66 12.4949 21.7506C12.8783 21.813 13.28 21.8648 13.6953 21.9056C14.2455 21.9597 14.8197 21.9942 15.4079 22.0082C15.6039 22.0128 15.8013 22.0153 16 22.0153C16.1987 22.0153 16.3962 22.0128 16.5921 22.0082C17.1803 21.9943 17.7545 21.9596 18.3047 21.9056C18.72 21.8648 19.1217 21.8131 19.5051 21.7506C20.062 21.66 20.5807 21.547 21.0476 21.4134C22.6749 20.9477 23.5 20.2859 23.5 19.4464C23.5 18.2187 21.7108 17.5833 20.1624 17.2634Z",
+					"fill": "#98A2B3"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M18.8441 17.1144C18.7585 16.9335 18.6559 16.7622 18.5384 16.6025C18.4174 16.4382 18.2809 16.286 18.1307 16.1486C17.5784 15.6437 16.8433 15.3354 16.036 15.3354C15.2318 15.3354 14.499 15.6411 13.9476 16.1426C13.7974 16.2791 13.6609 16.4303 13.5399 16.5937C13.4217 16.753 13.3185 16.924 13.2322 17.1048C13.039 17.5095 12.9307 17.9624 12.9307 18.4407C12.9307 18.4407 14.321 19.0592 16.036 19.0592C17.751 19.0592 19.1412 18.4407 19.1412 18.4407C19.1412 17.9662 19.0344 17.5167 18.8441 17.1144Z",
+					"fill": "#98A2B3"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"opacity": "0.5",
+					"d": "M18.6665 1.3335L27.9998 10.6668H21.3332C19.8604 10.6668 18.6665 9.47292 18.6665 8.00016V1.3335Z",
+					"fill": "white"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "filter",
+						"attributes": {
+							"id": "filter0_d_3055_14436",
+							"x": "2",
+							"y": "0.333496",
+							"width": "28",
+							"height": "33.3335",
+							"filterUnits": "userSpaceOnUse",
+							"color-interpolation-filters": "sRGB"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "feFlood",
+								"attributes": {
+									"flood-opacity": "0",
+									"result": "BackgroundImageFix"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"in": "SourceAlpha",
+									"type": "matrix",
+									"values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
+									"result": "hardAlpha"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feOffset",
+								"attributes": {
+									"dy": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feGaussianBlur",
+								"attributes": {
+									"stdDeviation": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"type": "matrix",
+									"values": "0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in2": "BackgroundImageFix",
+									"result": "effect1_dropShadow_3055_14436"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in": "SourceGraphic",
+									"in2": "effect1_dropShadow_3055_14436",
+									"result": "shape"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Unknow"
+}

+ 16 - 0
web/app/components/base/icons/src/public/files/Unknow.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Unknow.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Unknow'
+
+export default Icon

+ 145 - 0
web/app/components/base/icons/src/public/files/Xlsx.json

@@ -0,0 +1,145 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "24",
+			"height": "26",
+			"viewBox": "0 0 24 26",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"filter": "url(#filter0_d_5938_927)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"d": "M3 5.8C3 4.11984 3 3.27976 3.32698 2.63803C3.6146 2.07354 4.07354 1.6146 4.63803 1.32698C5.27976 1 6.11984 1 7.8 1H14L21 8V18.2C21 19.8802 21 20.7202 20.673 21.362C20.3854 21.9265 19.9265 22.3854 19.362 22.673C18.7202 23 17.8802 23 16.2 23H7.8C6.11984 23 5.27976 23 4.63803 22.673C4.07354 22.3854 3.6146 21.9265 3.32698 21.362C3 20.7202 3 19.8802 3 18.2V5.8Z",
+							"fill": "#169951"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"opacity": "0.5",
+					"d": "M14 1L21 8H16C14.8954 8 14 7.10457 14 6V1Z",
+					"fill": "white"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "path",
+				"attributes": {
+					"fill-rule": "evenodd",
+					"clip-rule": "evenodd",
+					"d": "M17 12C17.5523 12 18 12.4477 18 13V18C18 18.5523 17.5523 19 17 19H7C6.44772 19 6 18.5523 6 18V13C6 12.4477 6.44772 12 7 12H17ZM11.5 13H7L7 15H11.5V13ZM12.5 18H17V16H12.5V18ZM11.5 16V18H7L7 16H11.5ZM12.5 15H17V13H12.5V15Z",
+					"fill": "white",
+					"fill-opacity": "0.96"
+				},
+				"children": []
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "filter",
+						"attributes": {
+							"id": "filter0_d_5938_927",
+							"x": "1",
+							"y": "0",
+							"width": "22",
+							"height": "26",
+							"filterUnits": "userSpaceOnUse",
+							"color-interpolation-filters": "sRGB"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "feFlood",
+								"attributes": {
+									"flood-opacity": "0",
+									"result": "BackgroundImageFix"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"in": "SourceAlpha",
+									"type": "matrix",
+									"values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
+									"result": "hardAlpha"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feOffset",
+								"attributes": {
+									"dy": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feGaussianBlur",
+								"attributes": {
+									"stdDeviation": "1"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feColorMatrix",
+								"attributes": {
+									"type": "matrix",
+									"values": "0 0 0 0 0.0627451 0 0 0 0 0.0941176 0 0 0 0 0.156863 0 0 0 0.05 0"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in2": "BackgroundImageFix",
+									"result": "effect1_dropShadow_5938_927"
+								},
+								"children": []
+							},
+							{
+								"type": "element",
+								"name": "feBlend",
+								"attributes": {
+									"mode": "normal",
+									"in": "SourceGraphic",
+									"in2": "effect1_dropShadow_5938_927",
+									"result": "shape"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Xlsx"
+}

+ 16 - 0
web/app/components/base/icons/src/public/files/Xlsx.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Xlsx.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Xlsx'
+
+export default Icon

+ 6 - 0
web/app/components/base/icons/src/public/files/index.ts

@@ -1,2 +1,8 @@
 export { default as Csv } from './Csv'
+export { default as Html } from './Html'
+export { default as Json } from './Json'
 export { default as Md } from './Md'
+export { default as Pdf } from './Pdf'
+export { default as Txt } from './Txt'
+export { default as Unknow } from './Unknow'
+export { default as Xlsx } from './Xlsx'

+ 2 - 0
web/app/components/base/icons/src/public/llm/Localai.tsx

@@ -11,4 +11,6 @@ const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseP
   ref,
 ) => <IconBase {...props} ref={ref} data={data as IconData} />)
 
+Icon.displayName = 'Localai'
+
 export default Icon

+ 2 - 0
web/app/components/base/icons/src/public/llm/LocalaiText.tsx

@@ -11,4 +11,6 @@ const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseP
   ref,
 ) => <IconBase {...props} ref={ref} data={data as IconData} />)
 
+Icon.displayName = 'LocalaiText'
+
 export default Icon

+ 38 - 0
web/app/components/base/icons/src/vender/line/editor/BezierCurve03.json

@@ -0,0 +1,38 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "12",
+			"height": "12",
+			"viewBox": "0 0 12 12",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"id": "bezier-curve-03"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"id": "Icon",
+							"d": "M5.42857 3.5L2.57143 8.5M3 9.5H8.9999M9.42857 8.5L6.57143 3.5M1.8 10.5H2.2C2.48003 10.5 2.62004 10.5 2.727 10.4455C2.82108 10.3976 2.89757 10.3211 2.9455 10.227C3 10.12 3 9.98003 3 9.7V9.3C3 9.01997 3 8.87996 2.9455 8.773C2.89757 8.67892 2.82108 8.60243 2.727 8.5545C2.62004 8.5 2.48003 8.5 2.2 8.5H1.8C1.51997 8.5 1.37996 8.5 1.273 8.5545C1.17892 8.60243 1.10243 8.67892 1.0545 8.773C1 8.87996 1 9.01997 1 9.3V9.7C1 9.98003 1 10.12 1.0545 10.227C1.10243 10.3211 1.17892 10.3976 1.273 10.4455C1.37996 10.5 1.51997 10.5 1.8 10.5ZM9.8 10.5H10.2C10.48 10.5 10.62 10.5 10.727 10.4455C10.8211 10.3976 10.8976 10.3211 10.9455 10.227C11 10.12 11 9.98003 11 9.7V9.3C11 9.01997 11 8.87996 10.9455 8.773C10.8976 8.67892 10.8211 8.60243 10.727 8.5545C10.62 8.5 10.48 8.5 10.2 8.5H9.8C9.51997 8.5 9.37996 8.5 9.273 8.5545C9.17892 8.60243 9.10243 8.67892 9.0545 8.773C9 8.87996 9 9.01997 9 9.3V9.7C9 9.98003 9 10.12 9.0545 10.227C9.10243 10.3211 9.17892 10.3976 9.273 10.4455C9.37996 10.5 9.51997 10.5 9.8 10.5ZM5.8 3.5H6.2C6.48003 3.5 6.62004 3.5 6.727 3.4455C6.82108 3.39757 6.89757 3.32108 6.9455 3.227C7 3.12004 7 2.98003 7 2.7V2.3C7 2.01997 7 1.87996 6.9455 1.773C6.89757 1.67892 6.82108 1.60243 6.727 1.5545C6.62004 1.5 6.48003 1.5 6.2 1.5H5.8C5.51997 1.5 5.37996 1.5 5.273 1.5545C5.17892 1.60243 5.10243 1.67892 5.0545 1.773C5 1.87996 5 2.01997 5 2.3V2.7C5 2.98003 5 3.12004 5.0545 3.227C5.10243 3.32108 5.17892 3.39757 5.273 3.4455C5.37996 3.5 5.51997 3.5 5.8 3.5Z",
+							"stroke": "currentColor",
+							"stroke-linecap": "round",
+							"stroke-linejoin": "round"
+						},
+						"children": []
+					}
+				]
+			}
+		]
+	},
+	"name": "BezierCurve03"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/line/editor/BezierCurve03.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './BezierCurve03.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'BezierCurve03'
+
+export default Icon

+ 38 - 0
web/app/components/base/icons/src/vender/line/editor/TypeSquare.json

@@ -0,0 +1,38 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "12",
+			"height": "12",
+			"viewBox": "0 0 12 12",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"id": "type-square"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"id": "Icon",
+							"d": "M4 3.5H8M6 3.5V8.5M3.9 10.5H8.1C8.94008 10.5 9.36012 10.5 9.68099 10.3365C9.96323 10.1927 10.1927 9.96323 10.3365 9.68099C10.5 9.36012 10.5 8.94008 10.5 8.1V3.9C10.5 3.05992 10.5 2.63988 10.3365 2.31901C10.1927 2.03677 9.96323 1.8073 9.68099 1.66349C9.36012 1.5 8.94008 1.5 8.1 1.5H3.9C3.05992 1.5 2.63988 1.5 2.31901 1.66349C2.03677 1.8073 1.8073 2.03677 1.66349 2.31901C1.5 2.63988 1.5 3.05992 1.5 3.9V8.1C1.5 8.94008 1.5 9.36012 1.66349 9.68099C1.8073 9.96323 2.03677 10.1927 2.31901 10.3365C2.63988 10.5 3.05992 10.5 3.9 10.5Z",
+							"stroke": "currentColor",
+							"stroke-linecap": "round",
+							"stroke-linejoin": "round"
+						},
+						"children": []
+					}
+				]
+			}
+		]
+	},
+	"name": "TypeSquare"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/line/editor/TypeSquare.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './TypeSquare.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'TypeSquare'
+
+export default Icon

+ 2 - 0
web/app/components/base/icons/src/vender/line/editor/index.ts

@@ -0,0 +1,2 @@
+export { default as BezierCurve03 } from './BezierCurve03'
+export { default as TypeSquare } from './TypeSquare'

+ 65 - 0
web/app/components/base/icons/src/vender/line/general/Target04.json

@@ -0,0 +1,65 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "12",
+			"height": "12",
+			"viewBox": "0 0 12 12",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"id": "Left Icon",
+					"clip-path": "url(#clip0_10386_42171)"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"id": "Icon",
+							"d": "M7.99998 4V2.5L9.49998 1L9.99998 2L11 2.5L9.49998 4H7.99998ZM7.99998 4L5.99999 5.99997M11 6C11 8.76142 8.76142 11 6 11C3.23858 11 1 8.76142 1 6C1 3.23858 3.23858 1 6 1M8.5 6C8.5 7.38071 7.38071 8.5 6 8.5C4.61929 8.5 3.5 7.38071 3.5 6C3.5 4.61929 4.61929 3.5 6 3.5",
+							"stroke": "currentColor",
+							"stroke-linecap": "round",
+							"stroke-linejoin": "round"
+						},
+						"children": []
+					}
+				]
+			},
+			{
+				"type": "element",
+				"name": "defs",
+				"attributes": {},
+				"children": [
+					{
+						"type": "element",
+						"name": "clipPath",
+						"attributes": {
+							"id": "clip0_10386_42171"
+						},
+						"children": [
+							{
+								"type": "element",
+								"name": "rect",
+								"attributes": {
+									"width": "12",
+									"height": "12",
+									"fill": "white"
+								},
+								"children": []
+							}
+						]
+					}
+				]
+			}
+		]
+	},
+	"name": "Target04"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/line/general/Target04.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Target04.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Target04'
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/line/general/index.ts

@@ -12,6 +12,7 @@ export { default as LogOut01 } from './LogOut01'
 export { default as Pin02 } from './Pin02'
 export { default as Plus } from './Plus'
 export { default as SearchLg } from './SearchLg'
+export { default as Target04 } from './Target04'
 export { default as Trash03 } from './Trash03'
 export { default as XClose } from './XClose'
 export { default as X } from './X'

+ 36 - 0
web/app/components/base/icons/src/vender/solid/editor/Citations.json

@@ -0,0 +1,36 @@
+{
+	"icon": {
+		"type": "element",
+		"isRootNode": true,
+		"name": "svg",
+		"attributes": {
+			"width": "16",
+			"height": "16",
+			"viewBox": "0 0 16 16",
+			"fill": "none",
+			"xmlns": "http://www.w3.org/2000/svg"
+		},
+		"children": [
+			{
+				"type": "element",
+				"name": "g",
+				"attributes": {
+					"id": "citations"
+				},
+				"children": [
+					{
+						"type": "element",
+						"name": "path",
+						"attributes": {
+							"id": "Subtract",
+							"d": "M0.666992 7.99996C0.666992 3.94987 3.95024 0.666626 8.00033 0.666626C12.0504 0.666626 15.3337 3.94987 15.3337 7.99996C15.3337 12.05 12.0504 15.3333 8.00033 15.3333C3.95024 15.3333 0.666992 12.05 0.666992 7.99996ZM4.66699 7.9801V9.97196H7.35742V7.48922H5.87533C5.85644 7.21231 5.90365 6.94484 6.01693 6.68681C6.2372 6.19592 6.66829 5.84979 7.31022 5.6484V4.66663C6.44803 4.83655 5.79036 5.19527 5.33724 5.7428C4.89041 6.29032 4.66699 7.03609 4.66699 7.9801ZM10.0264 6.70569C10.2466 6.19592 10.6746 5.84349 11.3102 5.6484V4.66663C10.4732 4.83655 9.82183 5.19212 9.35612 5.73336C8.8967 6.27459 8.66699 7.02351 8.66699 7.9801V9.97196H11.3574V7.48922H9.87533C9.85015 7.23748 9.9005 6.9763 10.0264 6.70569Z",
+							"fill": "currentColor"
+						},
+						"children": []
+					}
+				]
+			}
+		]
+	},
+	"name": "Citations"
+}

+ 16 - 0
web/app/components/base/icons/src/vender/solid/editor/Citations.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Citations.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Citations'
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/solid/editor/index.ts

@@ -1 +1,2 @@
 export { default as Brush01 } from './Brush01'
+export { default as Citations } from './Citations'

+ 2 - 2
web/app/components/base/portal-to-follow-elem/index.tsx

@@ -15,7 +15,7 @@ import {
   useRole,
 } from '@floating-ui/react'
 
-import type { Placement } from '@floating-ui/react'
+import type { OffsetOptions, Placement } from '@floating-ui/react'
 
 type PortalToFollowElemOptions = {
   /*
@@ -25,7 +25,7 @@ type PortalToFollowElemOptions = {
   */
   placement?: Placement
   open?: boolean
-  offset?: number
+  offset?: number | OffsetOptions
   onOpenChange?: (open: boolean) => void
 }
 

+ 1 - 1
web/app/components/explore/item-operation/index.tsx

@@ -11,7 +11,7 @@ import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigge
 
 export type IItemOperationProps = {
   className?: string
-  isItemHovering: boolean
+  isItemHovering?: boolean
   isPinned: boolean
   isShowRenameConversation?: boolean
   onRenameConversation?: () => void

+ 18 - 1
web/app/components/explore/universal-chat/index.tsx

@@ -199,6 +199,7 @@ const Main: FC<IMainProps> = () => {
 
   const [suggestedQuestionsAfterAnswerConfig, setSuggestedQuestionsAfterAnswerConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
   const [speechToTextConfig, setSpeechToTextConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
+  const [citationConfig, setCitationConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
 
   const [conversationIdChangeBecauseOfNew, setConversationIdChangeBecauseOfNew, getConversationIdChangeBecauseOfNew] = useGetState(false)
 
@@ -271,6 +272,7 @@ const Main: FC<IMainProps> = () => {
             content: item.answer,
             feedback: item.feedback,
             isAnswer: true,
+            citation: item.retriever_resources,
           })
         })
         setChatList(newChatList)
@@ -374,7 +376,7 @@ const Main: FC<IMainProps> = () => {
         const isNotNewConversation = allConversations.some(item => item.id === _conversationId)
         setAllConversationList(allConversations)
         // fetch new conversation info
-        const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text }: any = appParams
+        const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text, retriever_resource }: any = appParams
         const prompt_variables = userInputsFormToPromptVariables(user_input_form)
 
         setNewConversationInfo({
@@ -387,6 +389,7 @@ const Main: FC<IMainProps> = () => {
         } as PromptConfig)
         setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer)
         setSpeechToTextConfig(speech_to_text)
+        setCitationConfig(retriever_resource)
 
         if (isNotNewConversation)
           setCurrConversationId(_conversationId, APP_ID, false)
@@ -593,6 +596,19 @@ const Main: FC<IMainProps> = () => {
           })
         setChatList(newListWithAnswer)
       },
+      onMessageEnd: (messageEnd) => {
+        responseItem.citation = messageEnd.retriever_resources
+
+        const newListWithAnswer = produce(
+          getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
+          (draft) => {
+            if (!draft.find(item => item.id === questionId))
+              draft.push({ ...questionItem })
+
+            draft.push({ ...responseItem })
+          })
+        setChatList(newListWithAnswer)
+      },
       onError() {
         setErrorHappened(true)
         // role back placeholder answer
@@ -783,6 +799,7 @@ const Main: FC<IMainProps> = () => {
                 isShowSuggestion={doShowSuggestion}
                 suggestionList={suggestQuestions}
                 isShowSpeechToText={speechToTextConfig?.enabled}
+                isShowCitation={citationConfig?.enabled}
                 dataSets={dataSets}
               />
             </div>

+ 23 - 2
web/app/components/share/chat/index.tsx

@@ -167,6 +167,7 @@ const Main: FC<IMainProps> = ({
 
   const [suggestedQuestionsAfterAnswerConfig, setSuggestedQuestionsAfterAnswerConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
   const [speechToTextConfig, setSpeechToTextConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
+  const [citationConfig, setCitationConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
 
   const [conversationIdChangeBecauseOfNew, setConversationIdChangeBecauseOfNew, getConversationIdChangeBecauseOfNew] = useGetState(false)
   const [isChatStarted, { setTrue: setChatStarted, setFalse: setChatNotStarted }] = useBoolean(false)
@@ -249,6 +250,7 @@ const Main: FC<IMainProps> = ({
             content: item.answer,
             feedback: item.feedback,
             isAnswer: true,
+            citation: item.retriever_resources,
           })
         })
         setChatList(newChatList)
@@ -364,7 +366,7 @@ const Main: FC<IMainProps> = ({
         const isNotNewConversation = allConversations.some(item => item.id === _conversationId)
         setAllConversationList(allConversations)
         // fetch new conversation info
-        const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text }: any = appParams
+        const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text, retriever_resource }: any = appParams
         const prompt_variables = userInputsFormToPromptVariables(user_input_form)
         if (siteInfo.default_language)
           changeLanguage(siteInfo.default_language)
@@ -380,6 +382,7 @@ const Main: FC<IMainProps> = ({
         } as PromptConfig)
         setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer)
         setSpeechToTextConfig(speech_to_text)
+        setCitationConfig(retriever_resource)
 
         // setConversationList(conversations as ConversationItem[])
 
@@ -474,7 +477,7 @@ const Main: FC<IMainProps> = ({
     setChatList(newList)
 
     // answer
-    const responseItem = {
+    const responseItem: IChatItem = {
       id: `${Date.now()}`,
       content: '',
       isAnswer: true,
@@ -533,6 +536,23 @@ const Main: FC<IMainProps> = ({
           setIsShowSuggestion(true)
         }
       },
+      onMessageEnd: isInstalledApp
+        ? (messageEnd) => {
+          if (!isInstalledApp)
+            return
+          responseItem.citation = messageEnd.retriever_resources
+
+          const newListWithAnswer = produce(
+            getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
+            (draft) => {
+              if (!draft.find(item => item.id === questionId))
+                draft.push({ ...questionItem })
+
+              draft.push({ ...responseItem })
+            })
+          setChatList(newListWithAnswer)
+        }
+        : undefined,
       onError() {
         setResponsingFalse()
         // role back placeholder answer
@@ -678,6 +698,7 @@ const Main: FC<IMainProps> = ({
                     isShowSuggestion={doShowSuggestion}
                     suggestionList={suggestQuestions}
                     isShowSpeechToText={speechToTextConfig?.enabled}
+                    isShowCitation={citationConfig?.enabled && isInstalledApp}
                   />
                 </div>
               </div>)

+ 3 - 2
web/app/components/share/chatbot/index.tsx

@@ -188,6 +188,7 @@ const Main: FC<IMainProps> = ({
             content: item.answer,
             feedback: item.feedback,
             isAnswer: true,
+            citation: item.retriever_resources,
           })
         })
         setChatList(newChatList)
@@ -289,7 +290,7 @@ const Main: FC<IMainProps> = ({
         const isNotNewConversation = allConversations.some(item => item.id === _conversationId)
         setAllConversationList(allConversations)
         // fetch new conversation info
-        const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text }: any = appParams
+        const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text, retriever_resource }: any = appParams
         const prompt_variables = userInputsFormToPromptVariables(user_input_form)
         if (siteInfo.default_language)
           changeLanguage(siteInfo.default_language)
@@ -399,7 +400,7 @@ const Main: FC<IMainProps> = ({
     setChatList(newList)
 
     // answer
-    const responseItem = {
+    const responseItem: IChatItem = {
       id: `${Date.now()}`,
       content: '',
       isAnswer: true,

+ 7 - 1
web/context/debug-configuration.ts

@@ -1,5 +1,5 @@
 import { createContext } from 'use-context-selector'
-import type { CompletionParams, Inputs, ModelConfig, MoreLikeThisConfig, PromptConfig, SpeechToTextConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
+import type { CitationConfig, CompletionParams, Inputs, ModelConfig, MoreLikeThisConfig, PromptConfig, SpeechToTextConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
 import type { DataSet } from '@/models/datasets'
 
 type IDebugConfiguration = {
@@ -21,6 +21,8 @@ type IDebugConfiguration = {
   setSuggestedQuestionsAfterAnswerConfig: (suggestedQuestionsAfterAnswerConfig: SuggestedQuestionsAfterAnswerConfig) => void
   speechToTextConfig: SpeechToTextConfig
   setSpeechToTextConfig: (speechToTextConfig: SpeechToTextConfig) => void
+  citationConfig: CitationConfig
+  setCitationConfig: (citationConfig: CitationConfig) => void
   formattingChanged: boolean
   setFormattingChanged: (formattingChanged: boolean) => void
   inputs: Inputs
@@ -65,6 +67,10 @@ const DebugConfigurationContext = createContext<IDebugConfiguration>({
     enabled: false,
   },
   setSpeechToTextConfig: () => { },
+  citationConfig: {
+    enabled: false,
+  },
+  setCitationConfig: () => {},
   formattingChanged: false,
   setFormattingChanged: () => { },
   inputs: {},

+ 5 - 0
web/i18n/lang/app-debug.en.ts

@@ -51,6 +51,11 @@ const translation = {
       description: 'Once enabled, you can use voice input.',
       resDes: 'Voice input is enabled',
     },
+    citation: {
+      title: 'Citations and Attributions',
+      description: 'Once enabled, show source document and attributed section of the generated content.',
+      resDes: 'Citations and Attributions is enabled',
+    },
     dataSet: {
       title: 'Context',
       noData: 'You can import datasets as context',

+ 5 - 0
web/i18n/lang/app-debug.zh.ts

@@ -51,6 +51,11 @@ const translation = {
       description: '启用后,您可以使用语音输入。',
       resDes: '语音输入已启用',
     },
+    citation: {
+      title: '引用和归属',
+      description: '启用后,显示源文档和生成内容的归属部分。',
+      resDes: '引用和归属已启用',
+    },
     dataSet: {
       title: '上下文',
       noData: '您可以导入数据集作为上下文',

+ 8 - 0
web/i18n/lang/common.en.ts

@@ -343,6 +343,14 @@ const translation = {
     conversationName: 'Conversation name',
     conversationNamePlaceholder: 'Please input conversation name',
     conversationNameCanNotEmpty: 'Conversation name required',
+    citation: {
+      title: 'CITATIONS',
+      linkToDataset: 'Link to dataset',
+      characters: 'Characters:',
+      hitCount: 'Hit count:',
+      vectorHash: 'Vector hash:',
+      hitScore: 'Hit Score:',
+    },
   },
 }
 

+ 8 - 0
web/i18n/lang/common.zh.ts

@@ -343,6 +343,14 @@ const translation = {
     conversationName: '会话名称',
     conversationNamePlaceholder: '请输入会话名称',
     conversationNameCanNotEmpty: '会话名称必填',
+    citation: {
+      title: '引用',
+      linkToDataset: '去往数据集',
+      characters: '字符:',
+      hitCount: '命中次数:',
+      vectorHash: '向量哈希:',
+      hitScore: '命中得分:',
+    },
   },
 }
 

+ 5 - 0
web/models/debug.ts

@@ -33,6 +33,8 @@ export type SuggestedQuestionsAfterAnswerConfig = MoreLikeThisConfig
 
 export type SpeechToTextConfig = MoreLikeThisConfig
 
+export type CitationConfig = MoreLikeThisConfig
+
 // frontend use. Not the same as backend
 export type ModelConfig = {
   provider: string // LLM Provider: for example "OPENAI"
@@ -48,6 +50,9 @@ export type ModelConfig = {
   speech_to_text: {
     enabled: boolean
   } | null
+  retriever_resource: {
+    enabled: boolean
+  } | null
   dataSets: any[]
 }
 

+ 9 - 5
web/service/base.ts

@@ -1,7 +1,7 @@
 /* eslint-disable no-new, prefer-promise-reject-errors */
 import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config'
 import Toast from '@/app/components/base/toast'
-import type { ThoughtItem } from '@/app/components/app/chat/type'
+import type { MessageEnd, ThoughtItem } from '@/app/components/app/chat/type'
 
 const TIME_OUT = 100000
 
@@ -33,6 +33,7 @@ export type IOnDataMoreInfo = {
 
 export type IOnData = (message: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => void
 export type IOnThought = (though: ThoughtItem) => void
+export type IOnMessageEnd = (messageEnd: MessageEnd) => void
 export type IOnCompleted = (hasError?: boolean) => void
 export type IOnError = (msg: string, code?: string) => void
 
@@ -43,6 +44,7 @@ type IOtherOptions = {
   deleteContentType?: boolean
   onData?: IOnData // for stream
   onThought?: IOnThought
+  onMessageEnd?: IOnMessageEnd
   onError?: IOnError
   onCompleted?: IOnCompleted // for stream
   getAbortController?: (abortController: AbortController) => void
@@ -65,7 +67,7 @@ export function format(text: string) {
   return res.replaceAll('\n', '<br/>').replaceAll('```', '')
 }
 
-const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted, onThought?: IOnThought) => {
+const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted, onThought?: IOnThought, onMessageEnd?: IOnMessageEnd) => {
   if (!response.ok)
     throw new Error('Network response was not ok')
 
@@ -86,7 +88,6 @@ const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted
       try {
         lines.forEach((message) => {
           if (message.startsWith('data: ')) { // check if it starts with data:
-            // console.log(message);
             try {
               bufferObj = JSON.parse(message.substring(6)) // remove data: and parse as json
             }
@@ -121,6 +122,9 @@ const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted
             else if (bufferObj.event === 'agent_thought') {
               onThought?.(bufferObj as any)
             }
+            else if (bufferObj.event === 'message_end') {
+              onMessageEnd?.(bufferObj as any)
+            }
           }
         })
         buffer = lines[lines.length - 1]
@@ -311,7 +315,7 @@ export const upload = (options: any): Promise<any> => {
   })
 }
 
-export const ssePost = (url: string, fetchOptions: any, { isPublicAPI = false, onData, onCompleted, onThought, onError, getAbortController }: IOtherOptions) => {
+export const ssePost = (url: string, fetchOptions: any, { isPublicAPI = false, onData, onCompleted, onThought, onMessageEnd, onError, getAbortController }: IOtherOptions) => {
   const abortController = new AbortController()
 
   const options = Object.assign({}, baseOptions, {
@@ -353,7 +357,7 @@ export const ssePost = (url: string, fetchOptions: any, { isPublicAPI = false, o
           return
         }
         onData?.(str, isFirstMessage, moreInfo)
-      }, onCompleted, onThought)
+      }, onCompleted, onThought, onMessageEnd)
     }).catch((e) => {
       if (e.toString() !== 'AbortError: The user aborted a request.')
         Toast.notify({ type: 'error', message: e })

+ 4 - 3
web/service/debug.ts

@@ -1,9 +1,10 @@
-import type { IOnCompleted, IOnData, IOnError } from './base'
+import type { IOnCompleted, IOnData, IOnError, IOnMessageEnd } from './base'
 import { get, post, ssePost } from './base'
 
-export const sendChatMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onError, getAbortController }: {
+export const sendChatMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onError, getAbortController, onMessageEnd }: {
   onData: IOnData
   onCompleted: IOnCompleted
+  onMessageEnd: IOnMessageEnd
   onError: IOnError
   getAbortController?: (abortController: AbortController) => void
 }) => {
@@ -12,7 +13,7 @@ export const sendChatMessage = async (appId: string, body: Record<string, any>,
       ...body,
       response_mode: 'streaming',
     },
-  }, { onData, onCompleted, onError, getAbortController })
+  }, { onData, onCompleted, onError, getAbortController, onMessageEnd })
 }
 
 export const stopChatMessageResponding = async (appId: string, taskId: string) => {

+ 4 - 3
web/service/share.ts

@@ -1,4 +1,4 @@
-import type { IOnCompleted, IOnData, IOnError } from './base'
+import type { IOnCompleted, IOnData, IOnError, IOnMessageEnd } from './base'
 import {
   del as consoleDel, get as consoleGet, patch as consolePatch, post as consolePost,
   delPublic as del, getPublic as get, patchPublic as patch, postPublic as post, ssePost,
@@ -22,10 +22,11 @@ function getUrl(url: string, isInstalledApp: boolean, installedAppId: string) {
   return isInstalledApp ? `installed-apps/${installedAppId}/${url.startsWith('/') ? url.slice(1) : url}` : url
 }
 
-export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onError, getAbortController }: {
+export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onError, getAbortController, onMessageEnd }: {
   onData: IOnData
   onCompleted: IOnCompleted
   onError: IOnError
+  onMessageEnd?: IOnMessageEnd
   getAbortController?: (abortController: AbortController) => void
 }, isInstalledApp: boolean, installedAppId = '') => {
   return ssePost(getUrl('chat-messages', isInstalledApp, installedAppId), {
@@ -33,7 +34,7 @@ export const sendChatMessage = async (body: Record<string, any>, { onData, onCom
       ...body,
       response_mode: 'streaming',
     },
-  }, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, getAbortController })
+  }, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, getAbortController, onMessageEnd })
 }
 
 export const stopChatMessageResponding = async (appId: string, taskId: string, isInstalledApp: boolean, installedAppId = '') => {

+ 4 - 3
web/service/universal-chat.ts

@@ -1,4 +1,4 @@
-import type { IOnCompleted, IOnData, IOnError, IOnThought } from './base'
+import type { IOnCompleted, IOnData, IOnError, IOnMessageEnd, IOnThought } from './base'
 import {
   del, get, patch, post, ssePost,
 } from './base'
@@ -10,11 +10,12 @@ function getUrl(url: string) {
   return `${baseUrl}/${url.startsWith('/') ? url.slice(1) : url}`
 }
 
-export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onError, onThought, getAbortController }: {
+export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onError, onThought, onMessageEnd, getAbortController }: {
   onData: IOnData
   onCompleted: IOnCompleted
   onError: IOnError
   onThought: IOnThought
+  onMessageEnd: IOnMessageEnd
   getAbortController?: (abortController: AbortController) => void
 }) => {
   return ssePost(getUrl('messages'), {
@@ -22,7 +23,7 @@ export const sendChatMessage = async (body: Record<string, any>, { onData, onCom
       ...body,
       response_mode: 'streaming',
     },
-  }, { onData, onCompleted, onThought, onError, getAbortController })
+  }, { onData, onCompleted, onThought, onError, getAbortController, onMessageEnd })
 }
 
 export const stopChatMessageResponding = async (taskId: string) => {

+ 3 - 0
web/types/app.ts

@@ -99,6 +99,9 @@ export type ModelConfig = {
   speech_to_text: {
     enabled: boolean
   }
+  retriever_resource: {
+    enabled: boolean
+  }
   agent_mode: {
     enabled: boolean
     tools: ToolItem[]

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff