diff --git a/modules/user_question_manager.py b/modules/user_question_manager.py index df5a1ba7..717286b0 100644 --- a/modules/user_question_manager.py +++ b/modules/user_question_manager.py @@ -105,10 +105,11 @@ class UserQuestionManager: username: str, selected_option_id: Optional[str] = None, text: Optional[str] = None, + dismissed: bool = False, ) -> Dict[str, Any]: clean_option_id = str(selected_option_id or "").strip() clean_text = str(text or "").strip() - if not clean_option_id and not clean_text: + if not dismissed and not clean_option_id and not clean_text: raise ValueError("回答不能为空") with self._lock: item = self._items.get(question_id) @@ -119,6 +120,13 @@ class UserQuestionManager: if item.get("status") != "pending": return dict(item) + # 用户主动选择不回答:标记为 dismissed,工具结果会提示模型改为在对话中提问 + if dismissed: + item["status"] = "answered" + item["answered_at"] = time.time() + item["answer"] = {"type": "dismissed", "text": ""} + return dict(item) + selected_option = None if clean_option_id: for opt in item.get("options") or []: @@ -152,6 +160,8 @@ def format_user_question_answer(item: Dict[str, Any]) -> str: answer = item.get("answer") if isinstance(item, dict) else None if not isinstance(answer, dict): return "用户未回答。" + if answer.get("type") == "dismissed": + return "用户没有回答或不想回答这个问题,请直接输出内容向用户提问" lines: List[str] = [] label = str(answer.get("selected_option_label") or "").strip() text = str(answer.get("text") or "").strip() diff --git a/server/chat/approval.py b/server/chat/approval.py index 6646e541..6abbb75c 100644 --- a/server/chat/approval.py +++ b/server/chat/approval.py @@ -72,6 +72,7 @@ def answer_user_question(terminal: WebTerminal, workspace: UserWorkspace, userna username=username, selected_option_id=data.get("selected_option_id"), text=data.get("text"), + dismissed=bool(data.get("dismissed")), ) except ValueError as exc: return jsonify({"success": False, "error": str(exc)}), 400 diff --git a/static/src/App.vue b/static/src/App.vue index b3a7fd95..36d3ebb3 100644 --- a/static/src/App.vue +++ b/static/src/App.vue @@ -520,6 +520,7 @@ @minimize="minimizeUserQuestionDialog" @update:active-index="userQuestionActiveIndex = $event" @submit="submitUserQuestionAnswers" + @dismiss="dismissUserQuestions" /> ({})); @@ -172,6 +173,15 @@ export const dialogMethods = { this.answeringUserQuestionIds = []; } }, + // 用户点击「不回答」:只将当前查看的这个问题标记为 dismissed,其余问题保持待回答。 + // 模型侧会收到「用户没有回答或不想回答」的工具结果并改为在对话中直接提问。 + async dismissUserQuestions(questionId) { + const id = String(questionId || '').trim(); + if (!id) { + return; + } + await this.submitUserQuestionAnswers([{ question_id: id, dismissed: true }]); + }, async answerUserQuestionFromComposer(text) { const clean = String(text || '').trim(); if (!clean || !Array.isArray(this.pendingUserQuestions) || !this.pendingUserQuestions.length) { diff --git a/static/src/components/overlay/UserQuestionDialog.vue b/static/src/components/overlay/UserQuestionDialog.vue index ba34973f..38bcacc8 100644 --- a/static/src/components/overlay/UserQuestionDialog.vue +++ b/static/src/components/overlay/UserQuestionDialog.vue @@ -57,6 +57,15 @@