Files

102 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

# AI 回复三态开关(REQ-坐席-010)— 工程师续载清单
> 创建于 2026-08-04 18:5x
> 用途:寇豆码在 429 重启后无需重读架构文档,直接据此清单补完剩余 3 件。
## 权威需求/设计(先读)
- PRD`docs/01-产品文档/04-坐席工作台/PRD-REQ-坐席-010-AI回复三态开关.md`
- 技术方案(含 5 任务、行号、Mermaid):`docs/02-技术文档/技术方案-REQ-坐席-010-AI回复三态开关.md`
- Mermaid 图:`docs/02-技术文档/architecture/REQ-坐席-010-{class-diagram,sequence-diagram}.mermaid`
## 已落盘(**不要重写**
### T01 数据层
-`src/backend/app/constants/ai_reply_mode.py`62 行)
-`src/backend/app/models/conversation.py` line 231 新增 `ai_reply_mode: Mapped[str]`
-`src/backend/app/schemas/conversation.py` line 359 ConversationResponse 加 `ai_reply_mode`
### T02 门控内核
-`src/backend/app/services/ai_reply_gate.py`163 行,6 函数:resolve_mode / conversation_mode / _normalize_status / can_ai_auto_reply_path_a / can_ai_auto_reply_path_b / agent_mirror_enabled / agent_dedicated_message
-`src/backend/tests/test_ai_reply_gate.py`(51 项参数化断言全过 2026-08-04 18:59
### T03 路径 A
-`src/backend/app/services/message_router.py` line 187 接入 `can_ai_auto_reply_path_a`
- ✓ L399 `_push_agent_dedicated_message` + L567 调用(b 态专属推送)
- ✓ imports constants/ai_reply_gate
### T02.5 设置 API
-`src/backend/app/api/conversations.py` line 400 PUT `/api/conversations/{conversation_id}/ai-reply-mode`
- ✓ 含广播 `ai_reply_mode_changed` WS 事件
-`src/backend/app/services/session_service.py` 已加 `set_ai_reply_mode`
### T04 路径 B**含接单后停 AI 缺口修复**)
-`src/backend/app/api/h5.py` line 946 接 `can_ai_auto_reply_path_b`(门控在 create_task 之前 ✅)
-`src/backend/app/api/ws.py` line 478 同上
-`src/backend/app/tasks/h5_ai_task.py` 4 处坐席广播点(L540/817/970/1684)已接 `agent_mirror_enabled`
- ✓ 2 处 `_push_agent_dedicated_message` 调用(L567/855
## 仍需补完(3 件)
### 1. Alembic 058 迁移(最简单,可立刻做)
- 文件:`src/backend/alembic/versions/058_add_ai_reply_mode.py`(仿 057 幂等写法:`sa.inspect(bind)` 守卫)
- `down_revision = '057_troubleshooting_templates'`
- 字段:`ai_reply_mode = sa.Column("ai_reply_mode", sa.String(20), nullable=False, server_default="employee_only")`
- 存量自动套用 server_default,无需数据回填
### 2. 前端 T055 子项)
#### 2a. `src/frontend-agent/src/components/chat/ai-assist/AiReplyModeSwitch.vue`
- 🤖 图标按钮(复用 `.tb-btn` 样式)+ `el-popover``el-radio-group` 三态单选
- 三个值:`employee_only` / `employee_and_agent` / `off`,显示中文文案
- 选中即调 `setAiReplyMode` API
- 当前态高亮(a 正常色 / b 高亮 / off 置灰)
#### 2b. `src/frontend-agent/src/components/chat/ReplyBox.vue`
-`.toolbar-left` 之后、`.tb-sep` 之后、`<AiAssistToolbar />` 之前插入 `<AiReplyModeSwitch />`
- 与 4 个主动 AI 按钮(💡🎚️🖌️🔄)以 `.tb-sep` 分隔,视觉独立
#### 2c. `src/frontend-agent/src/api/`(或现有 api 模块)
- `setAiReplyMode(conversationId, mode)` → PUT `/api/conversations/{conversation_id}/ai-reply-mode`
#### 2d. conversation store(找已有 conversation store,按 conversationId 存当前 mode
- action 存 + getter 取;切会话读各自值
#### 2e. WS 监听 `ai_reply_mode_changed`**不复用** `conversation_updated`,新增独立 handler
- payload: `{conversation_id, ai_reply_mode}`
- 多端同步:收到事件 → 更新 store
### 3. 修正技术方案文档(按 B 口径)
**用户最终澄清**2026-08-04 15:47):
> a 态(employee_only= AI 只对员工消息/选择作进一步回复;坐席端**仍按现状能看到 AI 回复员工的消息**。
> 即:a 维持现状镜像;b 在 a 基础上**额外**推专属;off 全关。
修正 `docs/02-技术文档/技术方案-REQ-坐席-010-AI回复三态开关.md`
- "推坐席"小节:明确 `agent_mirror_enabled = (mode != "off")`a/b 都镜像)
- "专属坐席消息"小节:`agent_dedicated_message = (mode == "employee_and_agent")`(仅 b 推)
- 说明当前实现(h5_ai_task.py + message_router.py 的 _push_agent_dedicated_message)已与本修正口径一致
## 完成后自测
1. 跑后端:`pytest tests/test_ai_reply_gate.py` → 期望 51/51
2. 跑前端:`pnpm vue-tsc --noEmit`(仅 AiReplyModeSwitch.vue 范围无新增错)
3. **全局一致性审查 IS_PASS: YES/NO** 重点核对:
- 字段 `ai_reply_mode`(不要写成 aiReplyMode / reply_scope
- WS 事件 `ai_reply_mode_changed`(不要复用 conversation_updated
- 端点路径 `/api/conversations/{conversation_id}/ai-reply-mode`
- 4 个广播点全部已接 `agent_mirror_enabled`grep 确认)
- 不动的 4 个 `broadcast_to_employees` 未被误改
## 提交
```
git add ... && git commit -m "feat(ai-reply-mode): REQ-坐席-010 三态开关完工
- T01 数据层 + alembic 058
- T02 门控内核 + 单测
- T03 路径 A + 坐席专属推送
- T04 路径 B + h5_ai_task 4 广播点收紧 + 接单后停 AI 缺口修复
- T05 前端 AiReplyModeSwitch + 集成 + WS 监听
- 修正技术方案文档'推坐席'小节按 B 口径"
```
把 commit hash + 改动文件清单 + IS_PASS 结果回传主理人。