Files
lhl 80daadcd31 fix(websocket): 修复 app.py 不可导入并新增真实链路验证
- 将 /api/sessions/{sid}/ws 端点移入 create_app(此前置于模块级导致整模块 import NameError,回归被验证拦截)
- register_loop + subscribe 调整至 accept 之前,缩小连接已开但未订阅期间的进度丢失窗口
- 新增 tests/test_verify_ws_real_flow.py:驱动真实 HTTP 聊天流程断言 WS 收到 agent 实际发射的 parse/impact 进度
- 同步 WebSocket 计划文档 Task 3 代码片段(标注端点必须位于 create_app 内)
- 全量 pytest 实测 583 passed / 99.03% 达标
2026-08-29 14:36:12 +08:00

2.9 KiB
Raw Permalink Blame History

Task 2 报告:agent 产出进度/错误时发射事件

状态

完成(2 passed)。

提交

  • 提交短哈希:8493bea
  • 提交信息:feat(chat): agent 产出进度/错误时发射事件(保留持久化兜底)
  • 仅变更:src/genesis/chat/agent.pytests/test_chat_agent_ws.py

测试输出摘要

  • python -m pytest tests/test_chat_agent_ws.py -q -o addopts=""2 passed
  • python -m pytest tests/test_chat_agent.py tests/test_server_chat_api.py -q -o addopts=""43 passed(既有聊天测试全绿,未破坏)

实现要点

  1. 顶部新增导入 from genesis.server.hub import hub as _progress_hub(原文件无 hub 局部变量/导入,故直接用 _progress_hub 别名,无冲突)。
  2. ChatAgent.__init__ 新增可选参数 progress_sink: Callable[[dict], None] | None = None,保存为 self.progress_sink
  3. 新增 _emit_progress(session_id, item)_emit_error(session_id, reply, action):优先 progress_sink 回调,否则经 _progress_hub.emit 发射。
  4. 在全部 progress.append(item) 之后紧接着调用 self._emit_progress(session_id, progress[-1])(覆盖 _handle_confirmation 确认成功、_parse_and_confirm 中 parse/impact、_run_impact 的 impact、_run_generate 的 generate/qa ok/qa warn、_run_qa 的 qa ok 共 8 处)。
  5. 在全部错误分支调用 _store_error(...) 之前先调用 self._emit_error(session_id, reply, action)(共 6 处:confirm/generate(解析)/parse/impact/生成失败/qa)。
  6. 既有 _persist_progress / _store_error 数据库持久化保持不变(重载兜底)。

疑虑与偏离

  • 测试偏离说明(重要):任务给定的测试模板使用 SessionStore(db_path=":memory:")。但本仓库 SessionStore_conn() 每次都新建连接,而 :memory: 每次连接是独立空库,_init_db() 建表对后续 create_session 不可见,导致 no such table: sessions。实测按原样 :memory: 两个测试均 OperationalError 失败。为达到「2 passed」目标,将测试中的 :memory: 改为临时目录下的真实文件(tempfile.mkdtemp + 固定文件名),其余断言完全照抄。功能验证不受影响(两个测试仅直接调用 _emit_progress/_emit_errorsession_id 仅作占位)。建议后续评估 SessionStore:memory: 的兼容性,或仓库统一测试约定。
  • 旧错误回复写法:核查确认原 agent.py 所有错误分支均已使用 self._store_error(...)(无 self.store.add_message(..., "assistant", ...) 旧写法),故未改动错误回复的持久化写法,仅在每处 _store_error 前插入 _emit_error
  • progress.append 位置:已逐处确认 8 个 progress.append 均位于实际流程产出点;其中 _parse_and_confirm 内 emit 在 if rec.status == "impact_running" 分支的 impact append 之后,符合“每处 append 后 emit”的要求。