Merge branch 'feat/model-provider-refactor' into feat/model-plugins-implementing

This commit is contained in:
CodingOnStar
2026-03-06 17:33:38 +08:00
383 changed files with 8137 additions and 4153 deletions

View File

@ -10,7 +10,7 @@ vi.mock('next/navigation', () => ({
}))
const mockNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: {
Provider: ({ children }: { children: React.ReactNode }) => children,
},

View File

@ -24,7 +24,7 @@ import Divider from '@/app/components/base/divider'
import { SearchLinesSparkle } from '@/app/components/base/icons/src/vender/knowledge'
import CustomPopover from '@/app/components/base/popover'
import Switch from '@/app/components/base/switch'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import { IS_CE_EDITION } from '@/config'
import { DataSourceType, DocumentActionType } from '@/models/datasets'

View File

@ -9,7 +9,7 @@ const mockNotify = vi.fn()
const mockClose = vi.fn()
// Mock ToastContext with factory function
vi.mock('@/app/components/base/toast', async () => {
vi.mock('@/app/components/base/toast/context', async () => {
const { createContext, useContext } = await import('use-context-selector')
const context = createContext({ notify: mockNotify, close: mockClose })
return {
@ -87,7 +87,7 @@ vi.mock('@/service/base', () => ({
// Import after all mocks are set up
const { useLocalFileUpload } = await import('../use-local-file-upload')
const { ToastContext } = await import('@/app/components/base/toast')
const { ToastContext } = await import('@/app/components/base/toast/context')
const createWrapper = () => {
return ({ children }: { children: ReactNode }) => (

View File

@ -25,7 +25,7 @@ vi.mock('@/hooks/use-theme', () => ({
}))
const mockNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: {
Provider: ({ children }: { children: ReactNode }) => children,
Consumer: ({ children }: { children: (ctx: { notify: typeof mockNotify }) => ReactNode }) => children({ notify: mockNotify }),

View File

@ -12,7 +12,7 @@ import Button from '@/app/components/base/button'
import { getFileUploadErrorMessage } from '@/app/components/base/file-uploader/utils'
import { Csv as CSVIcon } from '@/app/components/base/icons/src/public/files'
import SimplePieChart from '@/app/components/base/simple-pie-chart'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import useTheme from '@/hooks/use-theme'
import { upload } from '@/service/base'
import { useFileUploadConfig } from '@/service/use-common'
@ -204,7 +204,7 @@ const CSVUploader: FC<Props> = ({
/>
<div ref={dropRef}>
{!file && (
<div className={cn('flex h-20 items-center rounded-xl border border-dashed border-components-panel-border bg-components-panel-bg-blur text-sm font-normal', dragging && 'border border-divider-subtle bg-components-panel-on-panel-item-bg-hover')}>
<div className={cn('flex h-20 items-center rounded-xl border border-dashed border-components-panel-border bg-components-panel-bg-blur text-sm font-normal', dragging && 'border border-divider-subtle bg-components-panel-on-panel-item-bg-hover')}>
<div className="flex w-full items-center justify-center space-x-2">
<CSVIcon className="shrink-0" />
<div className="text-text-secondary">

View File

@ -65,7 +65,7 @@ vi.mock('../../context', () => ({
},
}))
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: { Provider: ({ children }: { children: React.ReactNode }) => children, Consumer: () => null },
useToastContext: () => ({ notify: mockNotify }),
}))

View File

@ -1,7 +1,8 @@
import type { ReactNode } from 'react'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { EventEmitterContextProvider, useEventEmitterContextContext } from '@/context/event-emitter'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { EventEmitterContextProvider } from '@/context/event-emitter-provider'
import RegenerationModal from '../regeneration-modal'
// Store emit function for triggering events in tests

View File

@ -59,7 +59,7 @@ vi.mock('../../../context', () => ({
},
}))
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))

View File

@ -92,7 +92,7 @@ vi.mock('../../../context', () => ({
},
}))
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))

View File

@ -2,7 +2,7 @@ import type { ChildChunkDetail, ChildSegmentsResponse, SegmentDetailModel, Segme
import { useQueryClient } from '@tanstack/react-query'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useToastContext } from '@/app/components/base/toast'
import { useToastContext } from '@/app/components/base/toast/context'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import {
useChildSegmentList,

View File

@ -4,7 +4,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { usePathname } from 'next/navigation'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useToastContext } from '@/app/components/base/toast'
import { useToastContext } from '@/app/components/base/toast/context'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { ChunkingMode } from '@/models/datasets'
import {

View File

@ -8,7 +8,7 @@ import { useContext } from 'use-context-selector'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useAppStore } from '@/app/components/app/store'
import Divider from '@/app/components/base/divider'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import { ChunkingMode } from '@/models/datasets'
import { useAddChildSegment } from '@/service/knowledge/use-segment'
import { cn } from '@/utils/classnames'
@ -58,7 +58,7 @@ const NewChildSegmentModal: FC<NewChildSegmentModalProps> = ({
<Divider type="vertical" className="mx-1 h-3 bg-divider-regular" />
<button
type="button"
className="system-xs-semibold text-text-accent"
className="text-text-accent system-xs-semibold"
onClick={() => {
clearTimeout(refreshTimer.current)
viewNewlyAddedChildChunk?.()
@ -120,11 +120,11 @@ const NewChildSegmentModal: FC<NewChildSegmentModalProps> = ({
<div className="flex h-full flex-col">
<div className={cn('flex items-center justify-between', fullScreen ? 'border border-divider-subtle py-3 pl-6 pr-4' : 'pl-4 pr-3 pt-3')}>
<div className="flex flex-col">
<div className="system-xl-semibold text-text-primary">{t('segment.addChildChunk', { ns: 'datasetDocuments' })}</div>
<div className="text-text-primary system-xl-semibold">{t('segment.addChildChunk', { ns: 'datasetDocuments' })}</div>
<div className="flex items-center gap-x-2">
<SegmentIndexTag label={t('segment.newChildChunk', { ns: 'datasetDocuments' }) as string} />
<Dot />
<span className="system-xs-medium text-text-tertiary">{wordCountText}</span>
<span className="text-text-tertiary system-xs-medium">{wordCountText}</span>
</div>
</div>
<div className="flex items-center">

View File

@ -5,7 +5,7 @@ import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import { useProcessRule } from '@/service/knowledge/use-dataset'
import { useDocumentContext } from '../context'
import { ProgressBar, RuleDetail, SegmentProgress, StatusHeader } from './components'

View File

@ -3,7 +3,7 @@ import type { FullDocumentDetail } from '@/models/datasets'
import { act, renderHook } from '@testing-library/react'
import * as React from 'react'
import { describe, expect, it, vi } from 'vitest'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import { useMetadataState } from '../use-metadata-state'

View File

@ -4,7 +4,7 @@ import type { DocType, FullDocumentDetail } from '@/models/datasets'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import { modifyDocMetadata } from '@/service/datasets'
import { asyncRunSafe } from '@/utils'
import { useDocumentContext } from '../../context'

View File

@ -9,7 +9,7 @@ import { useContext } from 'use-context-selector'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useAppStore } from '@/app/components/app/store'
import Divider from '@/app/components/base/divider'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import ImageUploaderInChunk from '@/app/components/datasets/common/image-uploader/image-uploader-in-chunk'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { ChunkingMode } from '@/models/datasets'
@ -61,7 +61,7 @@ const NewSegmentModal: FC<NewSegmentModalProps> = ({
<Divider type="vertical" className="mx-1 h-3 bg-divider-regular" />
<button
type="button"
className="system-xs-semibold text-text-accent"
className="text-text-accent system-xs-semibold"
onClick={() => {
clearTimeout(refreshTimer.current)
viewNewlyAddedChunk()
@ -158,13 +158,13 @@ const NewSegmentModal: FC<NewSegmentModalProps> = ({
className={cn('flex items-center justify-between', fullScreen ? 'border border-divider-subtle py-3 pl-6 pr-4' : 'pl-4 pr-3 pt-3')}
>
<div className="flex flex-col">
<div className="system-xl-semibold text-text-primary">
<div className="text-text-primary system-xl-semibold">
{t('segment.addChunk', { ns: 'datasetDocuments' })}
</div>
<div className="flex items-center gap-x-2">
<SegmentIndexTag label={t('segment.newChunk', { ns: 'datasetDocuments' })!} />
<Dot />
<span className="system-xs-medium text-text-tertiary">{wordCountText}</span>
<span className="text-text-tertiary system-xs-medium">{wordCountText}</span>
</div>
</div>
<div className="flex items-center">

View File

@ -100,10 +100,10 @@ vi.mock('@/app/components/datasets/create/step-two', () => ({
}))
vi.mock('@/app/components/header/account-setting', () => ({
default: ({ activeTab, onCancel }: { activeTab?: string, onCancel?: () => void }) => (
default: ({ activeTab, onCancelAction }: { activeTab?: string, onCancelAction?: () => void }) => (
<div data-testid="account-setting">
<span data-testid="active-tab">{activeTab}</span>
<button onClick={onCancel} data-testid="close-setting">Close</button>
<button onClick={onCancelAction} data-testid="close-setting">Close</button>
</div>
),
}))

View File

@ -1,3 +1,4 @@
import type { AccountSettingTab } from '@/app/components/header/account-setting/constants'
import type { DataSourceProvider, NotionPage } from '@/models/common'
import type {
CrawlOptions,
@ -19,6 +20,7 @@ import AppUnavailable from '@/app/components/base/app-unavailable'
import Loading from '@/app/components/base/loading'
import StepTwo from '@/app/components/datasets/create/step-two'
import AccountSetting from '@/app/components/header/account-setting'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import DatasetDetailContext from '@/context/dataset-detail'
@ -33,8 +35,13 @@ const DocumentSettings = ({ datasetId, documentId }: DocumentSettingsProps) => {
const { t } = useTranslation()
const router = useRouter()
const [isShowSetAPIKey, { setTrue: showSetAPIKey, setFalse: hideSetAPIkey }] = useBoolean()
const [accountSettingTab, setAccountSettingTab] = React.useState<AccountSettingTab>(ACCOUNT_SETTING_TAB.PROVIDER)
const { indexingTechnique, dataset } = useContext(DatasetDetailContext)
const { data: embeddingsDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding)
const handleOpenAccountSetting = React.useCallback(() => {
setAccountSettingTab(ACCOUNT_SETTING_TAB.PROVIDER)
showSetAPIKey()
}, [showSetAPIKey])
const invalidDocumentList = useInvalidDocumentList(datasetId)
const invalidDocumentDetail = useInvalidDocumentDetail()
@ -135,7 +142,7 @@ const DocumentSettings = ({ datasetId, documentId }: DocumentSettingsProps) => {
{dataset && documentDetail && (
<StepTwo
isAPIKeySet={!!embeddingsDefaultModel}
onSetting={showSetAPIKey}
onSetting={handleOpenAccountSetting}
datasetId={datasetId}
dataSourceType={documentDetail.data_source_type as DataSourceType}
notionPages={currentPage ? [currentPage as unknown as NotionPage] : []}
@ -155,8 +162,9 @@ const DocumentSettings = ({ datasetId, documentId }: DocumentSettingsProps) => {
</div>
{isShowSetAPIKey && (
<AccountSetting
activeTab="provider"
onCancel={async () => {
activeTab={accountSettingTab}
onTabChangeAction={setAccountSettingTab}
onCancelAction={async () => {
hideSetAPIkey()
}}
/>

View File

@ -8,7 +8,7 @@ import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import Switch from '@/app/components/base/switch'
import { ToastContext } from '@/app/components/base/toast'
import { ToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import Indicator from '@/app/components/header/indicator'
import { useDocumentDelete, useDocumentDisable, useDocumentEnable } from '@/service/knowledge/use-document'