'use client' import React, { FC, useEffect, useRef, useState } from 'react' import cn from 'classnames' import { useContext } from 'use-context-selector' import ConfigContext from '@/context/debug-configuration' import produce from 'immer' import { useTranslation } from 'react-i18next' import { useBoolean } from 'ahooks' 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' export interface IOpeningStatementProps { promptTemplate: string value: string onChange: (value: string) => void } // regex to match the {{}} and replace it with a span const regex = /\{\{([^}]+)\}\}/g const OpeningStatement: FC = ({ value = '', onChange }) => { const { t } = useTranslation() const { modelConfig, setModelConfig, } = useContext(ConfigContext) const promptVariables = modelConfig.configs.prompt_variables 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 coloredContent = (tempValue || '') .replace(regex, varHighlightHTML({ name: '$1' })) // `{{$1}}` .replace(/\n/g, '
') .replace(//g, '>') const handleEdit = () => { setFocus() } const [isShowConfirmAddVar, { setTrue: showConfirmAddVar, setFalse: hideConfirmAddVar }] = useBoolean(false) const handleCancel = () => { setBlur() setTempValue(value) } const handleConfirm = () => { const keys = getInputKeys(tempValue) const promptKeys = promptVariables.map((item) => item.key) let notIncludeKeys: string[] = [] if (promptKeys.length === 0) { if (keys.length > 0) { notIncludeKeys = keys } } else { notIncludeKeys = keys.filter((key) => !promptKeys.includes(key)) } if (notIncludeKeys.length > 0) { setNotIncludeKeys(notIncludeKeys) showConfirmAddVar() return } setBlur() onChange(tempValue) } const cancelAutoAddVar = () => { onChange(tempValue) hideConfirmAddVar() setBlur() } const autoAddVar = () => { const newModelConfig = produce(modelConfig, (draft) => { draft.configs.prompt_variables = [...draft.configs.prompt_variables, ...notIncludeKeys.map((key) => getNewVar(key))] }) onChange(tempValue) setModelConfig(newModelConfig) hideConfirmAddVar() setBlur() } const headerRight = ( ) return ( } headerRight={headerRight} hasHeaderBottomBorder={!hasValue} isFocus={isFocus} >
{(hasValue || (!hasValue && isFocus)) ? ( <> {isFocus ? ( ) : (
)} {/* Operation Bar */} {isFocus && (
{t('appDebug.openingStatement.varTip')}
)} ) : (
{t('appDebug.openingStatement.noDataPlaceHolder')}
)} {isShowConfirmAddVar && ( )}
) } export default React.memo(OpeningStatement)