- 将 /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% 达标
27 lines
2.9 KiB
Markdown
27 lines
2.9 KiB
Markdown
# Task 2 报告:agent 产出进度/错误时发射事件
|
||
|
||
## 状态
|
||
完成(2 passed)。
|
||
|
||
## 提交
|
||
- 提交短哈希:`8493bea`
|
||
- 提交信息:`feat(chat): agent 产出进度/错误时发射事件(保留持久化兜底)`
|
||
- 仅变更:`src/genesis/chat/agent.py`、`tests/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_error`,session_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”的要求。
|