feat(ui): 实现 ask_user_question 工具的前端支持

- 添加 AskUserQuestion 组件,支持单选/多选和自定义输入
- 添加 Question 相关类型定义 (QuestionOption, Question, QuestionMessagePart)
- 在 useChat 中处理 ask_user_question 工具完成事件,转换为问题 UI
- 添加 answerQuestion 回调用于提交用户回答
- 更新 ChatMessage 组件支持渲染问题类型的消息部分
This commit is contained in:
2025-12-16 23:14:25 +08:00
parent 791c4a4616
commit 3b170738ee
8 changed files with 556 additions and 12 deletions
+18 -2
View File
@@ -22,16 +22,19 @@ import { fadeInUp, smoothTransition } from '../utils/animations';
import { getAgentDisplayName } from '../utils/agent';
import { Markdown } from './Markdown';
import { FileMentionText } from './FileMentionTag';
import type { Message, ToolCallInfo, ToolStatus, ToolMessagePart } from '../api/types.js';
import type { Message, ToolCallInfo, ToolStatus, ToolMessagePart, QuestionMessagePart } from '../api/types.js';
import { AskUserQuestion } from './AskUserQuestion.js';
interface ChatMessageProps {
message: Message;
/** 是否为流式输出中(显示打字光标) */
isStreaming?: boolean;
/** 回答问题的回调(用于 ask_user_question 工具) */
onAnswerQuestion?: (questionPartId: string, answers: string[]) => void;
}
export const ChatMessage = forwardRef<HTMLDivElement, ChatMessageProps>(
({ message, isStreaming = false }, ref) => {
({ message, isStreaming = false, onAnswerQuestion }, ref) => {
const isUser = message.role === 'user';
const [copied, setCopied] = useState(false);
@@ -81,6 +84,19 @@ export const ChatMessage = forwardRef<HTMLDivElement, ChatMessageProps>(
);
case 'tool':
return <ToolPartItem key={part.id} part={part} />;
case 'question':
return (
<AskUserQuestion
key={part.id}
part={part as QuestionMessagePart}
onAnswer={
onAnswerQuestion
? (answers) => onAnswerQuestion(part.id, answers)
: undefined
}
disabled={isStreaming}
/>
);
case 'reasoning':
return (
<div key={part.id} className="text-fg-muted italic border-l-2 border-line pl-3">