diff --git a/web/app/components/app/configuration/toolbox/annotation/config-param.tsx b/web/app/components/app/configuration/toolbox/annotation/config-param.tsx deleted file mode 100644 index e418a76c34..0000000000 --- a/web/app/components/app/configuration/toolbox/annotation/config-param.tsx +++ /dev/null @@ -1,124 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import { useContext } from 'use-context-selector' -import { usePathname, useRouter } from 'next/navigation' -import ConfigParamModal from './config-param-modal' -import Panel from '@/app/components/app/configuration/base/feature-panel' -import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' -import Tooltip from '@/app/components/base/tooltip' -import { LinkExternal02, Settings04 } from '@/app/components/base/icons/src/vender/line/general' -import ConfigContext from '@/context/debug-configuration' -import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type' -import { fetchAnnotationConfig, updateAnnotationScore } from '@/service/annotation' -import type { AnnotationReplyConfig as AnnotationReplyConfigType } from '@/models/debug' - -type Props = { - onEmbeddingChange: (embeddingModel: EmbeddingModelConfig) => void - onScoreChange: (score: number, embeddingModel?: EmbeddingModelConfig) => void -} - -export const Item: FC<{ title: string; tooltip: string; children: JSX.Element }> = ({ - title, - tooltip, - children, -}) => { - return ( -
-
-
{title}
- {tooltip}
- } - /> -
-
{children}
- - ) -} - -const AnnotationReplyConfig: FC = ({ - onEmbeddingChange, - onScoreChange, -}) => { - const { t } = useTranslation() - const router = useRouter() - const pathname = usePathname() - const matched = pathname.match(/\/app\/([^/]+)/) - const appId = (matched?.length && matched[1]) ? matched[1] : '' - const { - annotationConfig, - } = useContext(ConfigContext) - - const [isShowEdit, setIsShowEdit] = React.useState(false) - - return ( - <> - - } - title={t('appDebug.feature.annotation.title')} - headerRight={ -
-
{ setIsShowEdit(true) }} - > - -
- - {t('common.operation.params')} -
-
-
{ - router.push(`/app/${appId}/annotations`) - }}> -
{t('appDebug.feature.annotation.cacheManagement')}
- -
-
- } - noBodySpacing - /> - {isShowEdit && ( - { - setIsShowEdit(false) - }} - onSave={async (embeddingModel, score) => { - const annotationConfig = await fetchAnnotationConfig(appId) as AnnotationReplyConfigType - let isEmbeddingModelChanged = false - if ( - embeddingModel.embedding_model_name !== annotationConfig.embedding_model.embedding_model_name - || embeddingModel.embedding_provider_name !== annotationConfig.embedding_model.embedding_provider_name - ) { - await onEmbeddingChange(embeddingModel) - isEmbeddingModelChanged = true - } - - if (score !== annotationConfig.score_threshold) { - await updateAnnotationScore(appId, annotationConfig.id, score) - if (isEmbeddingModelChanged) - onScoreChange(score, embeddingModel) - - else - onScoreChange(score) - } - - setIsShowEdit(false) - }} - annotationConfig={annotationConfig} - /> - )} - - ) -} -export default React.memo(AnnotationReplyConfig) diff --git a/web/app/components/app/configuration/toolbox/index.tsx b/web/app/components/app/configuration/toolbox/index.tsx deleted file mode 100644 index 00ea301a42..0000000000 --- a/web/app/components/app/configuration/toolbox/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -'use client' - -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import GroupName from '../base/group-name' -import Moderation from './moderation' -import Annotation from './annotation/config-param' -import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type' - -export type ToolboxProps = { - showModerationSettings: boolean - showAnnotation: boolean - onEmbeddingChange: (embeddingModel: EmbeddingModelConfig) => void - onScoreChange: (score: number, embeddingModel?: EmbeddingModelConfig) => void -} - -const Toolbox: FC = ({ - showModerationSettings, - showAnnotation, - onEmbeddingChange, - onScoreChange, -}) => { - const { t } = useTranslation() - - return ( -
- - { - showModerationSettings && ( - - ) - } - { - showAnnotation && ( - - ) - } -
- ) -} -export default React.memo(Toolbox) diff --git a/web/app/components/base/features/feature-panel/opening-statement/index.tsx b/web/app/components/base/features/feature-panel/opening-statement/index.tsx deleted file mode 100644 index 5d742f8bff..0000000000 --- a/web/app/components/base/features/feature-panel/opening-statement/index.tsx +++ /dev/null @@ -1,327 +0,0 @@ -'use client' -import type { FC } from 'react' -import React, { useEffect, useRef, useState } from 'react' -import produce from 'immer' -import { - RiAddLine, - RiDeleteBinLine, -} from '@remixicon/react' -import { useTranslation } from 'react-i18next' -import { useBoolean } from 'ahooks' -import { ReactSortable } from 'react-sortablejs' -import { - useFeatures, - useFeaturesStore, -} from '../../hooks' -import type { OnFeaturesChange } from '../../types' -import cn from '@/utils/classnames' -import Panel from '@/app/components/app/configuration/base/feature-panel' -import Button from '@/app/components/base/button' -import OperationBtn from '@/app/components/app/configuration/base/operation-btn' -import { getInputKeys } from '@/app/components/base/block-input' -import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var' -import { getNewVar } from '@/utils/var' -import { varHighlightHTML } from '@/app/components/app/configuration/base/var-highlight' -import type { PromptVariable } from '@/models/debug' -import type { InputVar } from '@/app/components/workflow/types' - -const MAX_QUESTION_NUM = 5 - -export type OpeningStatementProps = { - onChange?: OnFeaturesChange - readonly?: boolean - promptVariables?: PromptVariable[] - onAutoAddPromptVariable: (variable: PromptVariable[]) => void - workflowVariables?: InputVar[] -} - -// regex to match the {{}} and replace it with a span -const regex = /\{\{([^}]+)\}\}/g - -const OpeningStatement: FC = ({ - onChange, - readonly, - promptVariables = [], - onAutoAddPromptVariable, - workflowVariables = [], -}) => { - const { t } = useTranslation() - const featureStore = useFeaturesStore() - const openingStatement = useFeatures(s => s.features.opening) - const value = openingStatement?.opening_statement || '' - const suggestedQuestions = openingStatement?.suggested_questions || [] - const [notIncludeKeys, setNotIncludeKeys] = useState([]) - - const hasValue = !!(value || '').trim() - const inputRef = useRef(null) - - const [isFocus, { setTrue: didSetFocus, setFalse: setBlur }] = useBoolean(false) - - const setFocus = () => { - didSetFocus() - setTimeout(() => { - const input = inputRef.current - if (input) { - input.focus() - input.setSelectionRange(input.value.length, input.value.length) - } - }, 0) - } - - const [tempValue, setTempValue] = useState(value) - useEffect(() => { - setTempValue(value || '') - }, [value]) - - const [tempSuggestedQuestions, setTempSuggestedQuestions] = useState(suggestedQuestions || []) - const notEmptyQuestions = tempSuggestedQuestions.filter(question => !!question && question.trim()) - const coloredContent = (tempValue || '') - .replace(//g, '>') - .replace(regex, varHighlightHTML({ name: '$1' })) // `{{$1}}` - .replace(/\n/g, '
') - - const handleEdit = () => { - if (readonly) - return - setFocus() - } - - const [isShowConfirmAddVar, { setTrue: showConfirmAddVar, setFalse: hideConfirmAddVar }] = useBoolean(false) - - const handleCancel = () => { - setBlur() - setTempValue(value) - setTempSuggestedQuestions(suggestedQuestions) - } - - const handleConfirm = () => { - const keys = getInputKeys(tempValue) - const promptKeys = promptVariables.map(item => item.key) - const workflowVariableKeys = workflowVariables.map(item => item.variable) - let notIncludeKeys: string[] = [] - - if (promptKeys.length === 0 && workflowVariables.length === 0) { - if (keys.length > 0) - notIncludeKeys = keys - } - else { - if (workflowVariables.length > 0) - notIncludeKeys = keys.filter(key => !workflowVariableKeys.includes(key)) - - else notIncludeKeys = keys.filter(key => !promptKeys.includes(key)) - } - - if (notIncludeKeys.length > 0) { - setNotIncludeKeys(notIncludeKeys) - showConfirmAddVar() - return - } - setBlur() - const { getState } = featureStore! - const { - features, - setFeatures, - } = getState() - - const newFeatures = produce(features, (draft) => { - if (draft.opening) { - draft.opening.opening_statement = tempValue - draft.opening.suggested_questions = tempSuggestedQuestions - } - }) - setFeatures(newFeatures) - - if (onChange) - onChange(newFeatures) - } - - const cancelAutoAddVar = () => { - const { getState } = featureStore! - const { - features, - setFeatures, - } = getState() - - const newFeatures = produce(features, (draft) => { - if (draft.opening) - draft.opening.opening_statement = tempValue - }) - setFeatures(newFeatures) - - if (onChange) - onChange(newFeatures) - hideConfirmAddVar() - setBlur() - } - - const autoAddVar = () => { - const { getState } = featureStore! - const { - features, - setFeatures, - } = getState() - - const newFeatures = produce(features, (draft) => { - if (draft.opening) - draft.opening.opening_statement = tempValue - }) - setFeatures(newFeatures) - if (onChange) - onChange(newFeatures) - onAutoAddPromptVariable([...notIncludeKeys.map(key => getNewVar(key, 'string'))]) - hideConfirmAddVar() - setBlur() - } - - const headerRight = !readonly ? ( - isFocus ? ( -
- - -
- ) : ( - - ) - ) : null - - const renderQuestions = () => { - return isFocus ? ( -
-
-
-
{t('appDebug.openingStatement.openingQuestion')}
-
·
-
{tempSuggestedQuestions.length}/{MAX_QUESTION_NUM}
-
-
-
- { - return { - id: index, - name, - } - })} - setList={list => setTempSuggestedQuestions(list.map(item => item.name))} - handle='.handle' - ghostClass="opacity-50" - animation={150} - > - {tempSuggestedQuestions.map((question, index) => { - return ( -
-
- - - -
- { - const value = e.target.value - setTempSuggestedQuestions(tempSuggestedQuestions.map((item, i) => { - if (index === i) - return value - - return item - })) - }} - className={'w-full overflow-x-auto pl-1.5 pr-8 text-sm leading-9 text-gray-900 border-0 grow h-9 bg-transparent focus:outline-none cursor-pointer rounded-lg'} - /> - -
{ - setTempSuggestedQuestions(tempSuggestedQuestions.filter((_, i) => index !== i)) - }} - > - -
-
- ) - })}
- {tempSuggestedQuestions.length < MAX_QUESTION_NUM && ( -
{ setTempSuggestedQuestions([...tempSuggestedQuestions, '']) }} - className='mt-1 flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-gray-400 bg-gray-100 hover:bg-gray-200'> - -
{t('appDebug.variableConfig.addOption')}
-
- )} -
- ) : ( -
- {notEmptyQuestions.map((question, index) => { - return ( -
- {question} -
- ) - })} -
- ) - } - - return ( - - - - } - headerRight={headerRight} - hasHeaderBottomBorder={!hasValue} - isFocus={isFocus} - > -
- {(hasValue || (!hasValue && isFocus)) ? ( - <> - {isFocus - ? ( -
- -
- ) - : ( -
- )} - {renderQuestions()} - ) : ( -
{t('appDebug.openingStatement.noDataPlaceHolder')}
- )} - - {isShowConfirmAddVar && ( - - )} - -
-
- ) -} -export default React.memo(OpeningStatement) diff --git a/web/hooks/use-pay.tsx b/web/hooks/use-pay.tsx index 344f03955c..3ba23b6763 100644 --- a/web/hooks/use-pay.tsx +++ b/web/hooks/use-pay.tsx @@ -4,11 +4,8 @@ import { useCallback, useEffect, useState } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import { useTranslation } from 'react-i18next' import useSWR from 'swr' -import { useContext } from 'use-context-selector' -import I18n from '@/context/i18n' import { fetchDataSourceNotionBinding, - fetchFreeQuotaVerify, } from '@/service/common' import type { IConfirm } from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm' @@ -53,66 +50,6 @@ export const useBillingPay = () => { return confirm } -const QUOTA_RECEIVE_STATUS: Record = { - spark: { - success: { - 'en': 'Successful collection, the quota will be automatically increased after 5 minutes.', - 'zh-Hans': '领取成功,将在 5 分钟后自动增加配额', - }, - fail: { - 'en': 'Failure to collect', - 'zh-Hans': '领取失败', - }, - }, - zhipuai: { - success: { - 'en': 'Successful collection', - 'zh-Hans': '领取成功', - }, - fail: { - 'en': 'Failure to collect', - 'zh-Hans': '领取失败', - }, - }, -} - -const FREE_CHECK_PROVIDER = ['spark', 'zhipuai'] -export const useCheckFreeQuota = () => { - const { locale } = useContext(I18n) - const router = useRouter() - const [shouldVerify, setShouldVerify] = useState(false) - const searchParams = useSearchParams() - const type = searchParams.get('type') - const provider = searchParams.get('provider') - const result = searchParams.get('result') - const token = searchParams.get('token') - - const { data, error } = useSWR( - shouldVerify - ? `/workspaces/current/model-providers/${provider}/free-quota-qualification-verify?token=${token}` - : null, - fetchFreeQuotaVerify, - ) - - useEffect(() => { - if (error) - router.replace('/') - }, [error, router]) - - useEffect(() => { - if (type === 'provider_apply_callback' && FREE_CHECK_PROVIDER.includes(provider as string) && result === 'success') - setShouldVerify(true) - }, [type, provider, result]) - - return (data && provider) - ? { - type: data.flag ? 'info' : 'warning', - title: data.flag ? QUOTA_RECEIVE_STATUS[provider as string].success[locale] : QUOTA_RECEIVE_STATUS[provider].fail[locale], - desc: !data.flag ? data.reason : undefined, - } - : null -} - export const useCheckNotion = () => { const router = useRouter() const [confirm, setConfirm] = useState(null) @@ -154,7 +91,6 @@ export const CheckModal = () => { const { t } = useTranslation() const [showPayStatusModal, setShowPayStatusModal] = useState(true) const anthropicConfirmInfo = useAnthropicCheckPay() - const freeQuotaConfirmInfo = useCheckFreeQuota() const notionConfirmInfo = useCheckNotion() const billingConfirmInfo = useBillingPay() @@ -163,7 +99,7 @@ export const CheckModal = () => { router.replace('/') }, [router]) - const confirmInfo = anthropicConfirmInfo || freeQuotaConfirmInfo || notionConfirmInfo || billingConfirmInfo + const confirmInfo = anthropicConfirmInfo || notionConfirmInfo || billingConfirmInfo if (!confirmInfo || !showPayStatusModal) return null @@ -176,7 +112,7 @@ export const CheckModal = () => { showCancel={false} type={confirmInfo.type === 'info' ? 'info' : 'warning' } title={confirmInfo.title} - content={(confirmInfo as { desc: string }).desc || ''} + content={(confirmInfo as unknown as { desc: string }).desc || ''} confirmText={(confirmInfo.type === 'info' && t('common.operation.ok')) || ''} /> ) diff --git a/web/service/common.ts b/web/service/common.ts index d3c07f3c1d..70586b6ff6 100644 --- a/web/service/common.ts +++ b/web/service/common.ts @@ -38,11 +38,11 @@ import type { import type { RETRIEVE_METHOD } from '@/types/app' import type { SystemFeatures } from '@/types/feature' -interface LoginSuccess { +type LoginSuccess = { result: 'success' data: { access_token: string;refresh_token: string } } -interface LoginFail { +type LoginFail = { result: 'fail' data: string code: string @@ -183,7 +183,7 @@ export const fetchModelProviders: Fetcher<{ data: ModelProvider[] }, string> = ( return get<{ data: ModelProvider[] }>(url) } -export interface ModelProviderCredentials { +export type ModelProviderCredentials = { credentials?: Record load_balancing: ModelLoadBalancingConfig } @@ -257,10 +257,6 @@ export const fetchFileUploadConfig: Fetcher(url) } -export const fetchFreeQuotaVerify: Fetcher<{ result: string; flag: boolean; reason: string }, string> = (url) => { - return get(url) as Promise<{ result: string; flag: boolean; reason: string }> -} - export const fetchNotionConnection: Fetcher<{ data: string }, string> = (url) => { return get(url) as Promise<{ data: string }> } @@ -297,7 +293,7 @@ export const moderate = (url: string, body: { app_id: string; text: string }) => return post(url, { body }) as Promise } -interface RetrievalMethodsRes { +type RetrievalMethodsRes = { retrieval_method: RETRIEVE_METHOD[] } export const fetchSupportRetrievalMethods: Fetcher = (url) => {