diff --git a/server/chat.py b/server/chat.py index 458849e2..ef1cc6ce 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)