import { ChatContentContext } from '@/pages/chat'; import { LoadingOutlined } from '@ant-design/icons'; import { Button, Input, Spin } from 'antd'; import classNames from 'classnames'; import { useSearchParams } from 'next/navigation'; import React, { forwardRef, useContext, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { UserChatContent } from '@/types/chat'; import { parseResourceValue } from '@/utils'; import { SlashCommand } from './CommandPopover'; import EnhancedChatInput, { ContentPart, EnhancedChatInputRef } from './EnhancedChatInput'; import ToolsBar from './ToolsBar'; const USE_ENHANCED_INPUT = false; const defaultCommands: SlashCommand[] = [ { id: 'clear', trigger: 'clear', title: 'Clear chat history', type: 'builtin' }, { id: 'help', trigger: 'help', title: 'Show available commands', type: 'builtin' }, { id: 'model', trigger: 'model', title: 'Switch AI model', type: 'builtin' }, ]; const ChatInputPanel: React.ForwardRefRenderFunction = ({ ctrl }, ref) => { const { t } = useTranslation(); const { replyLoading, handleChat, appInfo, currentDialogue, temperatureValue, maxNewTokensValue, resourceValue, knowledgeValue, setResourceValue, refreshDialogList, } = useContext(ChatContentContext); const searchParams = useSearchParams(); const scene = searchParams?.get('scene') ?? ''; const select_param = searchParams?.get('select_param') ?? ''; const [userInput, setUserInput] = useState(''); const [isFocus, setIsFocus] = useState(false); const [isZhInput, setIsZhInput] = useState(false); const enhancedInputRef = useRef(null); const submitCountRef = useRef(0); const paramKey: string[] = useMemo(() => { return appInfo.param_need?.map(i => i.type) || []; }, [appInfo.param_need]); const buildChatParams = () => ({ app_code: appInfo.app_code || '', ...(paramKey.includes('temperature') && { temperature: temperatureValue }), ...(paramKey.includes('max_new_tokens') && { max_new_tokens: maxNewTokensValue }), select_param, ...(paramKey.includes('resource') && { select_param: typeof resourceValue === 'string' ? resourceValue : JSON.stringify(resourceValue) || currentDialogue.select_param, }), // Include knowledge space in ext_info for RAG ...(knowledgeValue && { ext_info: { knowledge_space: knowledgeValue }, }), }); const handleEnhancedSubmit = async (text: string, parts: ContentPart[]) => { submitCountRef.current++; const resources = parseResourceValue(resourceValue); let newUserInput: UserChatContent; const imageParts = parts.filter(p => p.type === 'image'); const hasImages = imageParts.length > 0; const hasResources = resources.length > 0; if (hasResources || hasImages) { if (scene !== 'chat_excel') { setResourceValue(null); } const messages = [...resources]; imageParts.forEach(img => { if (img.dataUrl) { messages.push({ type: 'image_url', image_url: { url: img.dataUrl, fileName: img.filename || 'image', }, }); } }); messages.push({ type: 'text', text: text, }); newUserInput = { role: 'user', content: messages, }; } else { newUserInput = text; } const params = buildChatParams(); await handleChat(newUserInput, params); if (submitCountRef.current === 1) { await refreshDialogList(); } }; const onLegacySubmit = async () => { submitCountRef.current++; setUserInput(''); const resources = parseResourceValue(resourceValue); let newUserInput: UserChatContent; if (resources.length > 0) { if (scene !== 'chat_excel') { setResourceValue(null); } const messages = [...resources]; messages.push({ type: 'text', text: userInput, }); newUserInput = { role: 'user', content: messages, }; } else { newUserInput = userInput; } const params = buildChatParams(); await handleChat(newUserInput, params); if (submitCountRef.current === 1) { await refreshDialogList(); } }; const handleCommandSelect = (command: SlashCommand) => { console.log('Command selected:', command); }; useImperativeHandle(ref, () => ({ setUserInput: (value: string) => { if (USE_ENHANCED_INPUT) { enhancedInputRef.current?.setValue(value); } else { setUserInput(value); } }, })); if (USE_ENHANCED_INPUT) { return (
); } return (
{ if (e.key === 'Enter') { if (e.shiftKey) { return; } if (isZhInput) { return; } e.preventDefault(); if (!userInput.trim() || replyLoading) { return; } onLegacySubmit(); } }} onChange={e => { setUserInput(e.target.value); }} onFocus={() => { setIsFocus(true); }} onBlur={() => setIsFocus(false)} onCompositionStart={() => setIsZhInput(true)} onCompositionEnd={() => setIsZhInput(false)} />
); }; export default forwardRef(ChatInputPanel);