From ca4bf17639efb5083493da60b3f08a289a7afcb2 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Tue, 9 Jun 2026 12:13:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(chat):=20=E8=BF=90=E8=A1=8C=E6=9C=9F?= =?UTF-8?q?=E9=97=B4=E6=9D=83=E9=99=90=E5=88=87=E6=8D=A2=E4=BD=BF=E7=94=A8?= =?UTF-8?q?pending=E6=9C=BA=E5=88=B6=EF=BC=8C=E9=81=BF=E5=85=8D=E6=9D=A5?= =?UTF-8?q?=E5=9B=9E=E5=88=87=E6=8D=A2=E6=8F=92=E5=85=A5=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - update_permission_mode / update_execution_mode 运行期间改用 queue 机制 - pending 值可被覆盖,最终若与当前相同则不通知 - 返回值直接返回 target_mode,前端立即更新 UI --- server/chat.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/server/chat.py b/server/chat.py index 458849e..ef1cc6c 100644 --- a/server/chat.py +++ b/server/chat.py @@ -689,6 +689,44 @@ def update_permission_mode(terminal: WebTerminal, workspace: UserWorkspace, user "success": False, "error": "无效权限模式,仅支持 readonly / approval / auto_approval / unrestricted" }), 400 + + # 判断当前是否在对话运行期间 + is_running = False + try: + from .tasks import task_manager + current_conv = getattr(getattr(terminal, "context_manager", None), "current_conversation_id", None) + running_tasks = [ + r for r in task_manager.list_tasks(username) if r.status in {"pending", "running", "cancel_requested"} + ] + if current_conv: + running_tasks.sort(key=lambda r: 0 if r.conversation_id == current_conv else 1) + is_running = bool(running_tasks) + except Exception: + pass + + if is_running: + # 运行期间:使用 pending 机制延迟到工具循环中统一处理, + # 避免「A→B→A」来回切换时中间值被覆盖后仍插入多余消息。 + try: + terminal.queue_permission_mode_change(target_mode) + except Exception as exc: + return jsonify({ + "success": False, + "error": str(exc), + "message": "更新权限模式失败" + }), 500 + status = terminal.get_status() + socketio.emit('status_update', status, room=f"user_{username}") + return jsonify({ + "success": True, + "mode": target_mode, + "pending_mode": target_mode, + "options": PERMISSION_MODE_OPTIONS, + "conversation_id": getattr(terminal.context_manager, "current_conversation_id", None), + "message": "权限模式将在当前工具执行完成后生效", + }) + + # 空闲期间:直接生效 previous_mode = terminal.get_permission_mode() if hasattr(terminal, "get_permission_mode") else None try: applied_mode = terminal.set_permission_mode(target_mode) @@ -756,6 +794,42 @@ def update_execution_mode(terminal: WebTerminal, workspace: UserWorkspace, usern target_mode = str(data.get("mode") or "").strip().lower() if target_mode not in EXECUTION_MODE_OPTIONS: return jsonify({"success": False, "error": "无效执行环境,仅支持 sandbox / direct"}), 400 + + # 判断当前是否在对话运行期间 + is_running = False + try: + from .tasks import task_manager + current_conv = getattr(getattr(terminal, "context_manager", None), "current_conversation_id", None) + running_tasks = [ + r for r in task_manager.list_tasks(username) if r.status in {"pending", "running", "cancel_requested"} + ] + if current_conv: + running_tasks.sort(key=lambda r: 0 if r.conversation_id == current_conv else 1) + is_running = bool(running_tasks) + except Exception: + pass + + if is_running: + # 运行期间:使用 pending 机制延迟到工具循环中统一处理, + # 避免「A→B→A」来回切换时中间值被覆盖后仍插入多余消息。 + try: + terminal.queue_execution_mode_change(target_mode) + except Exception as exc: + return jsonify({"success": False, "error": str(exc), "message": "更新执行环境失败"}), 500 + status = terminal.get_status() + socketio.emit('status_update', status, room=f"user_{username}") + return jsonify({ + "success": True, + "state": { + **(terminal.get_execution_mode_state() if hasattr(terminal, "get_execution_mode_state") else {"mode": target_mode}), + "mode": target_mode, + }, + "pending_mode": target_mode, + "options": EXECUTION_MODE_OPTIONS, + "message": "执行环境将在当前工具执行完成后生效", + }) + + # 空闲期间:直接生效 previous_mode = terminal.get_execution_mode() if hasattr(terminal, "get_execution_mode") else None try: state = terminal.set_execution_mode(target_mode)