83 lines
4.9 KiB
Markdown
83 lines
4.9 KiB
Markdown
# ISS-013 Chat 入口解耦与真正 SSE 收敛
|
||
|
||
**状态**:已被 ISS-014 吸收并归档(2026-07-22)
|
||
**吸收结果**:唯一 `/api/chat` named SSE、Chat Application Use Case、bounded executor、exact Run cancel 和前端单 consumer 已由 ISS-014 阶段 6A/6B 完成,最终 E2E 归入阶段 7。
|
||
**严重程度**:高
|
||
**发现时间**:2026-07-20
|
||
**关联**:ISS-011、ISS-012
|
||
|
||
---
|
||
|
||
## 背景
|
||
|
||
当前 Chat 入口同时提供 `/api/chat` 和 `/api/chat_stream`。`ChatController` 不仅处理 HTTP/SSE 协议,还直接承担会话创建、历史读取与回写、模型和工具获取、执行策略调用以及异常响应组装,入口职责已经明显超出协议适配层。
|
||
|
||
现有 `/api/chat_stream` 会等待完整答案生成后再按固定长度切片发送,并不是真正的流式生成。同步和伪流式入口还复制了大部分业务流程,增加了维护成本和行为不一致风险。
|
||
|
||
## 已确认问题
|
||
|
||
1. Chat 的会话、历史、模型、工具、执行和结果回写功能耦合在 `ChatController` 中,HTTP 层与应用用例边界不清晰。
|
||
2. `/api/chat` 与 `/api/chat_stream` 重复编排同一套 Chat 流程。
|
||
3. `/api/chat_stream` 只是对完整答案做事后分块,不具备模型生成过程中的真实增量输出能力。
|
||
4. Controller 直接获取 `ChatModel` 和 `ToolCallbackProvider`,将模型基础设施细节暴露到入口层。
|
||
5. SSE 使用 Controller 自建的无界缓存线程池,缺少统一生命周期和容量治理。
|
||
6. 当前入口错误响应存在 HTTP 状态、外层 `ApiResponse` 与内层 `ChatResponse` 状态不一致的问题。
|
||
|
||
## 目标
|
||
|
||
1. 将会话生命周期、历史管理、执行调用和结果回写从 Controller 分离,形成单一 Chat 应用用例入口。
|
||
2. 只保留一个 `/api/chat` 接口,并将其协议改为真正的 SSE。
|
||
3. SSE 在模型或诊断链路产生内容时增量发送,而不是等待完整答案后再切片。
|
||
4. 保留 `sessionId + runId` 作为一次 Chat Run 的稳定关联契约。
|
||
5. 在满足入口职责分离的前提下使用最少组件,不引入没有实际职责的接口、工厂或适配层。
|
||
|
||
## 设计约束
|
||
|
||
- Controller 只负责请求校验、协议转换和 SSE 生命周期,不负责选择模型、组装工具、管理历史或编排诊断流程。
|
||
- 同一次请求只能进入一个应用用例入口,禁止同步和流式路径各自维护一套业务逻辑。
|
||
- 真正 SSE 至少需要区分元数据、内容增量、完成和错误事件。
|
||
- `sessionId`、`runId` 必须在内容事件之前可获得,并用于日志、数据库和 Trace 对齐。
|
||
- 客户端断开、超时和执行失败必须显式终止后台执行并完成 Run 状态记录。
|
||
- 不保留旧 `/api/chat_stream` 或同步 `/api/chat` 的兼容分支,直接以新协议为准。
|
||
- 优先使用 Spring 管理的执行设施和现有服务能力,不创建无界线程池。
|
||
|
||
## 建议的最小边界
|
||
|
||
```text
|
||
POST /api/chat (SSE)
|
||
-> ChatController:请求与 SSE 协议
|
||
-> Chat 应用用例:会话、Run、历史和执行生命周期
|
||
-> 现有 Chat 执行能力:简单回答或诊断编排
|
||
```
|
||
|
||
这里的“应用用例”是职责边界,不要求预先拆出多层接口。只有出现独立变化原因或明确复用需求时才增加新组件。
|
||
|
||
## 验收标准
|
||
|
||
- [ ] 对外只保留一个 `POST /api/chat`,响应类型为 `text/event-stream`。
|
||
- [ ] 删除 `/api/chat_stream` 及同步 Chat 兼容路径。
|
||
- [ ] 首个内容事件在完整答案生成完成前发送,禁止通过固定字符切片伪造流式输出。
|
||
- [ ] SSE 事件包含稳定的 metadata、content、error、done 契约。
|
||
- [ ] Controller 不再直接依赖 `ChatModel`、`ToolCallbackProvider`,也不管理会话历史和 Run 持久化。
|
||
- [ ] 同一请求的 `sessionId + runId` 在 SSE、应用日志、`diagnosis_run`、`agent_step` 和 `tool_invocation` 中一致。
|
||
- [ ] 客户端断开、超时、模型失败和工具失败都有明确的资源清理与 Run 终态。
|
||
- [ ] 不存在 Controller 自建的无界线程池。
|
||
- [ ] 单元测试覆盖入口校验和 SSE 事件契约;端到端测试验证真实增量输出、断开清理及 Trace 对齐。
|
||
|
||
## 非目标
|
||
|
||
- 不在本 Issue 中重新设计 StateGraph 节点、Gatekeeper、Verifier 或证据协议。
|
||
- 不为未来可能出现的其他传输协议预建通用框架。
|
||
- 不引入多套 Command、Handler、Adapter、Factory 只为形式上的分层。
|
||
- 不保留旧同步接口或 `/api/chat_stream` 的兼容逻辑。
|
||
- 不以“完整答案分块发送”作为 SSE 验收通过条件。
|
||
|
||
## 相关文件
|
||
|
||
- `src/main/java/com/superbiz/agent/controller/ChatController.java`
|
||
- `src/main/java/com/superbiz/agent/service/ChatService.java`
|
||
- `src/main/java/com/superbiz/agent/service/session/SessionManager.java`
|
||
- `src/test/java/com/superbiz/agent/controller/ChatControllerTest.java`
|
||
- `src/test/java/com/superbiz/agent/service/ChatServiceGraphIntegrationTest.java`
|
||
- `mvp/architecture/current-mvp-architecture.md`
|