diff --git a/web/src/App.tsx b/web/src/App.tsx index 69365a1..6390b4e 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -166,6 +166,7 @@ function App() { }) const [configPageOpen, setConfigPageOpen] = useState(false) + const [configInitialTab, setConfigInitialTab] = useState<'providers' | 'experts'>('providers') const handleSaveConnection = useCallback((host: string, port: number) => { setGatewaySettings({ host, port }) @@ -355,8 +356,18 @@ function App() { ) const handleExitSubAgentView = useCallback(() => { - exitSubAgentView() - }, [exitSubAgentView]) + const command = exitSubAgentView() + if (command) { + sendMessage({ type: 'command', payload: JSON.stringify(command) }) + } + }, [exitSubAgentView, sendMessage]) + + const handleNavigateToSubAgentLevel = useCallback((index: number) => { + const command = navigateToSubAgentLevel(index) + if (command) { + sendMessage({ type: 'command', payload: JSON.stringify(command) }) + } + }, [navigateToSubAgentLevel, sendMessage]) // 切换到定时任务 tab 时自动获取列表 useEffect(() => { @@ -567,7 +578,10 @@ function App() { {/* Breadcrumb: 主会话 */} + {error && ( + {error} + )} + + + {open && ( +
+ {listLoading && expertList.length === 0 ? ( +
+ 加载中... +
+ ) : ( + <> + {/* 无专家 option */} + + {expertList.length > 0 && ( +
+ {expertList.map(expert => { + const isSelected = selectedExpert?.name === expert.name + return ( + + ) + })} +
+ )} +
+ +
+ + )} +
+ )} + + ) +} diff --git a/web/src/components/Chat/MessageInput.tsx b/web/src/components/Chat/MessageInput.tsx index ce8506f..e572ee4 100644 --- a/web/src/components/Chat/MessageInput.tsx +++ b/web/src/components/Chat/MessageInput.tsx @@ -12,6 +12,7 @@ interface MessageInputProps { placeholder?: string isReadOnly?: boolean channelName?: string + selectedExpert?: { name: string; description: string } | null } interface FileAttachment { @@ -33,10 +34,13 @@ export function MessageInput({ onStop, disabled = false, isLoading = false, - placeholder = '输入消息...按 / 查看命令', + placeholder, isReadOnly = false, channelName, + selectedExpert, }: MessageInputProps) { + const effectivePlaceholder = placeholder + ?? (selectedExpert ? `以 ${selectedExpert.name} 专家身份对话...` : '输入消息...按 / 查看命令') const [content, setContent] = useState('') const [attachments, setAttachments] = useState([]) const [isDragging, setIsDragging] = useState(false) @@ -360,7 +364,7 @@ export function MessageInput({ onChange={(e) => setContent(e.target.value)} onKeyDown={handleKeyDown} onPaste={handlePaste} - placeholder={placeholder} + placeholder={effectivePlaceholder} disabled={disabled} rows={1} className="w-full resize-none rounded-xl border border-[var(--border-color)] bg-[var(--bg-tertiary)] px-4 py-3 pr-12 text-sm text-[var(--text-primary)] placeholder:text-[var(--text-muted)] focus:border-[var(--accent-cyan)]/50 focus:outline-none focus:ring-1 focus:ring-[var(--focus-ring)] disabled:opacity-50 transition-all self-center scrollbar-hide"