- 创建 devflow 项目档案(brief/evidence/decisions/acceptance) - 更新 devflow/index.md 索引 - 移动 OpenSpec 到 archive
5.7 KiB
5.7 KiB
会话存储 — 功能规格
Requirement 1:三张新表的 DDL
路径:src/main/resources/db/migration/V005__create_session_storage.sql
内容:
- 创建
diagnosis_session表(DDL 见 design.md) - 创建
agent_step表(DDL 见 design.md) - 创建
tool_invocation表(DDL 见 design.md) - 三条 DDL 写在同一个迁移文件中
验收标准:
- Flyway migrate 后三张表均存在
- 表结构字段类型、索引与设计一致
- JSON 列使用
JSON类型(MySQL 8+)
Requirement 2:JPA Entity + Repository
2.1 实体类
路径:
src/main/java/com/superbiz/agent/domain/entity/DiagnosisSession.javasrc/main/java/com/superbiz/agent/domain/entity/AgentStep.javasrc/main/java/com/superbiz/agent/domain/entity/ToolInvocation.java
要求:
- 使用
@Entity+@Table(name = "...")映射 - JSON 字段使用
@JdbcTypeCode(SqlTypes.JSON)(同现有DiagnosisRecord.toolCalls) @PrePersist自动填充createdAt- 使用 Lombok
@Data @Builder @NoArgsConstructor @AllArgsConstructor
2.2 Repository 接口
路径:
src/main/java/com/superbiz/agent/repository/DiagnosisSessionRepository.javasrc/main/java/com/superbiz/agent/repository/AgentStepRepository.javasrc/main/java/com/superbiz/agent/repository/ToolInvocationRepository.java
要求:
- 继承
JpaRepository DiagnosisSessionRepository:findBySessionId(String sessionId)AgentStepRepository:findBySessionIdOrderByStepIndex(String sessionId)、countBySessionId(String sessionId)ToolInvocationRepository:findBySessionId(String sessionId)、findByToolName(String toolName)
验收标准:
- 3 个 Entity 编译通过
- 3 个 Repository 编译通过
- 自定义查询方法命名符合 Spring Data JPA 规范
Requirement 3:AgentLoggingHook 改造为 Spring Bean
路径:src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java
变更:
- 类上加
@Component注解 - 不再通过 new 创建实例
- 构造注入
AgentStepRepository - beforeModel:创建
AgentStep记录,设置modelInput,记录开始时间到RunnableConfig - afterModel:更新对应
AgentStep,设置modelOutput、thought、hasToolCall、durationMs、tokenCount modelInput和modelOutput只存摘要(前 500 字符),不存完整消息体
session_id 传递机制:
- 调用方(ChatService/AiOpsService)通过
RunnableConfig.metadata()传入sessionId - Hook 从
config.getMetadata("sessionId")读取
验收标准:
- Hook 可注入 AgentStepRepository
- beforeModel 创建 agent_step 记录并写入 DB
- afterModel 更新对应 agent_step 记录
- model_input/output 摘要不超过 500 字符
- 从 RunnableConfig 正确读取 sessionId
- 原日志输出行为保持不变
Requirement 4:ChatService 集成
路径:src/main/java/com/superbiz/agent/service/ChatService.java
变更:
- 注入
DiagnosisSessionRepository executeChat()中:- 执行前:创建
DiagnosisSession(status=RUNNING),生成sessionId,生成agent_flow=CHAT - 通过
RunnableConfig将 sessionId 传给 Hook - 执行后:更新
DiagnosisSession(status=SUCCESS/FAILED,汇总 step_count、tool_call_count、total_duration_ms)
- 执行前:创建
- 不再通过
new AgentLoggingHook()创建 Hook,改为注入 Bean 的 Hook
验收标准:
- executeChat 执行前后分别创建和更新 diagnosis_session
- sessionId 通过 RunnableConfig 正确传递给 Hook
- 汇总指标(duration、step_count)正确写入
- 异常路径正确设置 status=FAILED
Requirement 5:AiOpsService 集成
路径:src/main/java/com/superbiz/agent/service/AiOpsService.java
变更:
- 注入
DiagnosisSessionRepository和AgentLoggingHook executeAiOpsAnalysis()中:- 执行前:创建
DiagnosisSession(status=RUNNING, agent_flow=AI_OPS) - 构建 Planner 和 Executor 时传入
AgentLoggingHook实例(使用注入的 Bean) - 通过
RunnableConfig将 sessionId 传给 Hook - 执行后:更新
DiagnosisSession(汇总指标)
- 执行前:创建
- Supervisor 不加 Hook
验收标准:
- AiOpsService 执行前后分别创建和更新 diagnosis_session
- Planner 和 Executor 各带 AgentLoggingHook
- 两个 Hook 使用相同的 sessionId
- Supervisor 不产生 agent_step 记录
Requirement 6:LookupKnowledgeTool 写入 tool_invocation
路径:src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java
变更:
- 注入
ToolInvocationRepository lookupKnowledge()执行后:- 创建
ToolInvocation记录 - 写入
toolName=lookup_knowledge、inputParams(query)、outputPreview(前 500 字符) - 写入检索质量:
retrievalLayer、l0MatchCount、l1MatchCount、isTruncated、retrievalDetails - 写入
durationMs、success
- 创建
sessionId和stepId如何获取需要方案设计(见开放问题)
验收标准:
- lookup_knowledge 每次调用后创建 tool_invocation 记录
- 检索质量字段(L0/L1 明细)正确写入
- 工具执行失败的场景正确记录
Requirement 7:构造注入适配(无 @Async)
路径:所有涉及新增 Repository 注入的类
要求:
- 所有新注入使用构造注入(
@RequiredArgsConstructor或显式构造器) - 不在 MV 阶段引入 @Async 异步基础设施
- Hook 中的 DB 写入是同步的,作为已知的技术债记录
验收标准:
- 没有使用 @Autowired 字段注入新 Repository(保持项目已有风格)
- 没有引入 @Async / @EnableAsync