feat: 支持 AskUserQuestion 多问题和多选功能

- 新增 QuestionItem 类型支持单个问题配置(question/options/multiSelect)
   - AskUserEvent 改为 questions 数组支持多问题
   - AnswerRequest 新增 answers 字段支持多问题答案提交
   - 前端渲染支持单选按钮(radio)和多选复选框(checkbox)
   - 答案格式:{\"0\": [\"选项1\"], \"1\": [\"选项A\", \"选项B\"]}
   - 保持向后兼容旧的单问题格式
This commit is contained in:
Roe-xin
2026-03-05 16:58:59 +08:00
parent f6b1f5c45a
commit fa55e32153
7 changed files with 132 additions and 74 deletions

View File

@ -43,8 +43,7 @@ export interface MessageSegment {
toolResult?: string;
toolDescription?: string;
askId?: string;
question?: string;
options?: string[];
questions?: import("../types/api").QuestionItem[];
// 智能体相关字段
agentId?: string;
agentName?: string;
@ -97,7 +96,7 @@ export interface DialogCallbacks {
summary: string
) => void;
/** 显示问题ask_user */
onQuestion?: (askId: string, question: string, options: string[]) => void;
onQuestion?: (askId: string, questions: import("../types/api").QuestionItem[]) => void;
/** 实时更新段落(流式过程中) */
onSegmentUpdate?: (segments: MessageSegment[]) => void;
/** 对话完成,返回所有段落 */
@ -647,8 +646,11 @@ export class DialogSession {
this.segments.push({
type: "question",
askId: askId,
question: question,
options: ["确认执行", "取消"],
questions: [{
question: question,
options: ["确认执行", "取消"],
multiSelect: false
}],
});
// 实时发送段落更新
@ -666,8 +668,11 @@ export class DialogSession {
await userInteractionManager.handleAskUser(
{
askId: askId,
question: question,
options: ["确认执行", "取消"],
questions: [{
question: question,
options: ["确认执行", "取消"],
multiSelect: false
}]
} as AskUserEvent,
this.taskId
);
@ -714,8 +719,11 @@ export class DialogSession {
// 注册问题到前端(类似 askUser以便用户回答时能找到
const planEvent = {
askId: askId,
question: `请确认执行计划:${data.title}`,
options: ["确认执行", "修改计划", "取消"],
questions: [{
question: `请确认执行计划:${data.title}`,
options: ["确认执行", "修改计划", "取消"],
multiSelect: false
}]
};
try {
await userInteractionManager.handleAskUser(
@ -856,13 +864,12 @@ export class DialogSession {
this.segments.push({
type: "question",
askId: data.askId,
question: data.question,
options: data.options,
questions: data.questions,
});
// 实时发送段落更新(包含问题)
callbacks.onSegmentUpdate?.(this.segments);
// 同时调用 onQuestion 用于更新状态栏等
callbacks.onQuestion?.(data.askId, data.question, data.options);
callbacks.onQuestion?.(data.askId, data.questions);
try {
await userInteractionManager.handleAskUser(data, this.taskId);
} catch (error) {
@ -1110,7 +1117,8 @@ export class DialogSession {
async submitAnswer(
askId: string,
selected?: string[],
customInput?: string
customInput?: string,
answers?: { [questionIndex: string]: string[] }
): Promise<void> {
// 直接调用 receiveAnswer传递 taskId 作为 fallbackTaskId
// 如果 pendingQuestions 中有问题,走正常流程
@ -1119,6 +1127,7 @@ export class DialogSession {
askId,
selected,
customInput,
answers,
this.taskId
);
}