diff --git a/core/main_terminal.py b/core/main_terminal.py index 7b18cd1..b56eadc 100644 --- a/core/main_terminal.py +++ b/core/main_terminal.py @@ -283,8 +283,8 @@ class MainTerminal(MainTerminalCommandMixin, MainTerminalContextMixin, MainTermi }) return normalized - def apply_pending_runtime_mode_changes(self) -> List[str]: - notices: List[str] = [] + def apply_pending_runtime_mode_changes(self) -> List[Dict[str, str]]: + notices: List[Dict[str, str]] = [] updates: Dict[str, Any] = {} pending_permission = self.pending_permission_mode @@ -298,7 +298,7 @@ class MainTerminal(MainTerminalCommandMixin, MainTerminalContextMixin, MainTermi "auto_approval": "自动审核", "unrestricted": "无限制", }.get(pending_permission, pending_permission) - notices.append(f"权限模式修改为 {label}") + notices.append({"text": f"权限模式被用户修改为 {label}", "source": "权限变更"}) updates["permission_mode"] = pending_permission updates["pending_permission_mode"] = None self.pending_permission_mode = None @@ -309,7 +309,7 @@ class MainTerminal(MainTerminalCommandMixin, MainTerminalContextMixin, MainTermi if pending_execution != current_exec: self.set_execution_mode(pending_execution) label = {"sandbox": "沙箱", "direct": "完全访问权限"}.get(pending_execution, pending_execution) - notices.append(f"执行环境修改为 {label}") + notices.append({"text": f"执行环境被用户修改为 {label}", "source": "执行环境变更"}) updates["execution_mode"] = pending_execution updates["pending_execution_mode"] = None self.pending_execution_mode = None diff --git a/server/chat.py b/server/chat.py index 6d6f19a..458849e 100644 --- a/server/chat.py +++ b/server/chat.py @@ -52,7 +52,7 @@ PERMISSION_MODE_OPTIONS = ["readonly", "approval", "auto_approval", "unrestricte EXECUTION_MODE_OPTIONS = ["sandbox", "direct"] -def _dispatch_runtime_mode_notice(terminal: WebTerminal, username: str, text: str) -> None: +def _dispatch_runtime_mode_notice(terminal: WebTerminal, username: str, text: str, source: str = "notify") -> None: notice = str(text or "").strip() if not notice: return @@ -76,7 +76,7 @@ def _dispatch_runtime_mode_notice(terminal: WebTerminal, username: str, text: st username=username, task_id=target.task_id, message=notice, - source="notify", + source=source, ) if not result.get("success"): debug_log(f"[RuntimeMode] enqueue runtime guidance failed: {result}") @@ -714,7 +714,7 @@ def update_permission_mode(terminal: WebTerminal, workspace: UserWorkspace, user "auto_approval": "自动审核", "unrestricted": "无限制", }.get(applied_mode, applied_mode) - _dispatch_runtime_mode_notice(terminal, username, f"权限模式修改为 {permission_label}") + _dispatch_runtime_mode_notice(terminal, username, f"权限模式被用户修改为 {permission_label}", source="权限变更") status = terminal.get_status() socketio.emit('status_update', status, room=f"user_{username}") return jsonify({ @@ -772,7 +772,7 @@ def update_execution_mode(terminal: WebTerminal, workspace: UserWorkspace, usern current_mode = state.get("mode", target_mode) if current_mode != previous_mode: execution_label = {"sandbox": "沙箱", "direct": "完全访问权限"}.get(current_mode, current_mode) - _dispatch_runtime_mode_notice(terminal, username, f"执行环境修改为 {execution_label}") + _dispatch_runtime_mode_notice(terminal, username, f"执行环境被用户修改为 {execution_label}", source="执行环境变更") socketio.emit('status_update', status, room=f"user_{username}") return jsonify({ "success": True, diff --git a/server/chat_flow_tool_loop.py b/server/chat_flow_tool_loop.py index 2e748b8..ea8976a 100644 --- a/server/chat_flow_tool_loop.py +++ b/server/chat_flow_tool_loop.py @@ -182,6 +182,7 @@ def _inject_runtime_mode_notice( web_terminal, messages: List[Dict[str, Any]], content: str, + source: str = "notify", sender=None, conversation_id: Optional[str] = None, ) -> None: @@ -189,7 +190,7 @@ def _inject_runtime_mode_notice( web_terminal=web_terminal, messages=messages, text=content, - source="notify", + source=source, sender=sender, conversation_id=conversation_id, inline=True, @@ -1329,10 +1330,19 @@ async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, clie # 避免在 assistant.tool_calls 与对应 tool 消息之间插入 user 消息导致 API 报错。 if pending_runtime_mode_notices: for notice in pending_runtime_mode_notices: + if isinstance(notice, dict): + _text = str(notice.get("text") or "").strip() + _source = str(notice.get("source") or "notify").strip() or "notify" + else: + _text = str(notice or "").strip() + _source = "notify" + if not _text: + continue _inject_runtime_mode_notice( web_terminal=web_terminal, messages=messages, - content=notice, + content=_text, + source=_source, sender=sender, conversation_id=conversation_id, )