%% REQ-坐席-010 AI回复三态开关 — 类图 %% 架构师 高见远(Gao) 2026-08-04 classDiagram class AiReplyMode { <> +str EMPLOYEE_ONLY$ = "employee_only" +str EMPLOYEE_AND_AGENT$ = "employee_and_agent" +str OFF$ = "off" +str DEFAULT$ = "employee_only" +frozenset ALL$ +frozenset PATH_B_ALLOWED_STATUS$ = {ai_handling, queued} } class Conversation { +str id +str employee_id +str status +str ai_reply_mode +str assigned_agent_id +dict tags +int ai_substantive_reply_count +__repr__() str } class AiReplyGate { <> +can_ai_auto_reply_path_a(conversation) bool +can_ai_auto_reply_path_b(conversation) bool +should_push_to_agent(conversation) bool } class AiReplyModeUpdate { <> +str mode +validate_mode(v) str } class AiReplyModeResponse { <> +str conversation_id +str ai_reply_mode } class ConversationResponse { <> +str id +str status +str ai_reply_mode } class MessageRouter { <> -AIHandler ai_handler -WecomService wecom_service +handle_employee_message(...) Conversation -_try_ai_reply(conversation, content, from_user_id) bool } class H5AiTask { <> +process_h5_ai_reply(...) None -_persist_and_push(...) None -_persist_and_push_structured(...) None -_handle_byod_query(...) None -_step_call_dify(...) AIReplyResult } class ConnectionManager { <> +Dict~str,WebSocket~ active_connections +Dict~str,WebSocket~ employee_connections +broadcast(data) None +send_to_agent(agent_id, data) None +broadcast_to_employees(ids, data) None } class ConversationsAPI { <> +update_ai_reply_mode(conversation_id, body, db) dict } AiReplyGate ..> AiReplyMode : 读常量 AiReplyGate ..> Conversation : 只读判定 AiReplyModeUpdate ..> AiReplyMode : 值校验 ConversationsAPI --> Conversation : 写 ai_reply_mode ConversationsAPI --> AiReplyModeUpdate : 请求体 ConversationsAPI --> AiReplyModeResponse : 响应体 ConversationsAPI --> ConnectionManager : broadcast(ai_reply_mode_changed) MessageRouter ..> AiReplyGate : 路径A门控 + 推坐席判定 MessageRouter --> ConnectionManager : 新增 employee_and_agent 时广播 H5AiTask ..> AiReplyGate : 推坐席判定 H5AiTask --> ConnectionManager : 条件广播 ConversationResponse ..> Conversation : from_attributes