# S6: 消息编辑 + 重新生成 ## 目标 为 AI 聊天页面(aichat.html)增加两条交互能力: 1. **双击编辑用户消息**:双击用户气泡 → inline 编辑 → Enter 保存 → 重新调 LLM 2. **重新生成按钮**:AI 消息旁出现"重新生成"按钮 → 删除旧回复 → 重新调 LLM ## 涉及文件 1. `local_db.py` — 新增 `msg_get()`、`msg_update()`、`msg_delete_since()` 2. `app.py` — 新增 `PUT /api/conversations//messages/`、`POST /api/conversations//regenerate` 3. `templates/aichat.html` — 双击编辑 + 重新生成按钮 UI 4. 测试文件:`test_s6_edit_regenerate.py` ## 数据流 ``` 编辑: 双击用户气泡 → contenteditable → Enter → PUT /api/.../messages/ {"content":new} → 前端重新渲染 → 可选自动触发 regenerate 重新生成: 点击 ⟳ 按钮 → POST /api/.../regenerate → 后端删除最后一条 assistant 消息 → 重新调 LLM → 流式返回新回复 ``` ## 步骤 ### S6a: local_db 新增函数 - `msg_get(msg_id)` — 获取单条消息 - `msg_update(msg_id, content)` — 更新消息内容 - `msg_delete_since(conv_id, since_id)` — 删除指定 ID 之后的消息(用于 regenerate) ### S6b: API 路由 - `PUT /api/conversations//messages/` — 编辑消息,校验 role=user - `POST /api/conversations//regenerate` — 删除最后 AI 回复 → 重新调 LLM → 流式返回 ### S6c: 前端 UI - 用户消息增加 data-msgid 属性,双击触发 inline edit - AI 最后一条消息旁显示 ⟳ 重新生成按钮 - Enter 保存编辑,Escape 取消 ## 验证命令 ```bash # 单元测试 python3 test_s6_edit_regenerate.py # 页面回归 curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:5000/chat # smoketest python3 test_smoke.py ``` ## 验收标准(Sprint Contract) - [ ] TC1: `msg_get(id)` 返回正确消息,不存在时返回 None - [ ] TC2: `msg_update(id, content)` 更新后 `msg_get` 返回新内容 - [ ] TC3: `msg_delete_since(conv_id, since_id)` 删除指定 ID 之后的消息(不含 since_id) - [ ] TC4: `PUT /api/conversations//messages/` 编辑成功返回 200,校验非 user 消息返回 400 - [ ] TC5: `POST /api/conversations//regenerate` 删除最后 AI 消息 → 流式返回新回复 - [ ] TC6: 页面 `/chat` 返回 200,用户消息有 data-msgid 属性 - [ ] TC7: AI 消息区包含 regenerate 相关触发(函数名或按钮元素) - [ ] TC8: JS 无转义 bug(style=\\\\\\"、onclick=\\") - [ ] TC9: smoketest 全部通过(首页/articles/learn/reports 200) ## 风险 - 低风险:纯增量,不改现有路由 - 重新生成需要调用 Hermes:复用现有 `call_hermes_stream` 逻辑