diff --git a/common-agent-rag/src/main/java/com/bruce/rag/controller/IngestionRunController.java b/common-agent-rag/src/main/java/com/bruce/rag/controller/IngestionRunController.java index 4c77298..a3137a8 100644 --- a/common-agent-rag/src/main/java/com/bruce/rag/controller/IngestionRunController.java +++ b/common-agent-rag/src/main/java/com/bruce/rag/controller/IngestionRunController.java @@ -1,14 +1,18 @@ package com.bruce.rag.controller; import com.bruce.common.domain.model.RequestResult; +import com.bruce.rag.dto.request.IngestionRunCreateRequest; import com.bruce.rag.service.IIngestionRunService; import com.bruce.rag.vo.IngestionRunVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -25,6 +29,16 @@ public class IngestionRunController { private final IIngestionRunService ingestionRunService; + @Operation(summary = "创建文件解析管道聚合视图") + @PostMapping + public RequestResult create(@Valid @RequestBody IngestionRunCreateRequest request) { + log.info("文件解析管道创建开始,storeId={}, documentId={}", request.getStoreId(), request.getDocumentId()); + IngestionRunVO view = ingestionRunService.createRun(request); + log.info("文件解析管道创建结束,runId={}, storeId={}, documentId={}", + view.getRunId(), view.getStoreId(), view.getDocumentId()); + return RequestResult.success(view); + } + @Operation(summary = "查询文件解析管道聚合视图") @GetMapping("/{runId}") public RequestResult detail(@PathVariable("runId") String runId, diff --git a/common-agent-rag/src/main/java/com/bruce/rag/dto/request/IngestionRunCreateRequest.java b/common-agent-rag/src/main/java/com/bruce/rag/dto/request/IngestionRunCreateRequest.java new file mode 100644 index 0000000..f86a0da --- /dev/null +++ b/common-agent-rag/src/main/java/com/bruce/rag/dto/request/IngestionRunCreateRequest.java @@ -0,0 +1,24 @@ +package com.bruce.rag.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 文件解析管道创建请求。 + *

+ * 首轮实现不额外落摄取运行表,而是基于知识库与文档主数据生成可追踪的聚合 runId, + * 让前端能够按统一入口进入管道详情页。 + */ +@Data +@Schema(description = "文件解析管道创建请求") +public class IngestionRunCreateRequest { + + @NotNull(message = "知识库ID不能为空") + @Schema(description = "知识库ID") + private Long storeId; + + @NotNull(message = "文档ID不能为空") + @Schema(description = "文档ID") + private Long documentId; +} diff --git a/common-agent-rag/src/main/java/com/bruce/rag/service/IIngestionRunService.java b/common-agent-rag/src/main/java/com/bruce/rag/service/IIngestionRunService.java index 11563a8..3e0c531 100644 --- a/common-agent-rag/src/main/java/com/bruce/rag/service/IIngestionRunService.java +++ b/common-agent-rag/src/main/java/com/bruce/rag/service/IIngestionRunService.java @@ -1,5 +1,6 @@ package com.bruce.rag.service; +import com.bruce.rag.dto.request.IngestionRunCreateRequest; import com.bruce.rag.vo.IngestionRunVO; /** @@ -7,6 +8,11 @@ import com.bruce.rag.vo.IngestionRunVO; */ public interface IIngestionRunService { + /** + * 创建文件解析管道视图入口。 + */ + IngestionRunVO createRun(IngestionRunCreateRequest request); + /** * 按知识库和文档聚合摄取流水线视图。 */ diff --git a/common-agent-rag/src/main/java/com/bruce/rag/service/impl/IngestionRunServiceImpl.java b/common-agent-rag/src/main/java/com/bruce/rag/service/impl/IngestionRunServiceImpl.java index d81d7d6..4d9f611 100644 --- a/common-agent-rag/src/main/java/com/bruce/rag/service/impl/IngestionRunServiceImpl.java +++ b/common-agent-rag/src/main/java/com/bruce/rag/service/impl/IngestionRunServiceImpl.java @@ -3,6 +3,7 @@ package com.bruce.rag.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.bruce.modelprovider.dto.response.RagStoreModelConfigResponse; import com.bruce.modelprovider.service.IRagStoreModelConfigService; +import com.bruce.rag.dto.request.IngestionRunCreateRequest; import com.bruce.rag.dto.response.RagDocumentResponse; import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.entity.RagChunk; @@ -53,6 +54,19 @@ public class IngestionRunServiceImpl implements IIngestionRunService { private final IRagChunkEmbeddingService ragChunkEmbeddingService; private final IRagStoreModelConfigService ragStoreModelConfigService; + @Override + public IngestionRunVO createRun(IngestionRunCreateRequest request) { + if (request == null) { + throw new IllegalArgumentException("文件解析管道创建请求不能为空"); + } + log.info("文件解析管道创建聚合开始,storeId={}, documentId={}", request.getStoreId(), request.getDocumentId()); + IngestionRunVO view = getRun(request.getStoreId(), request.getDocumentId()); + view.setRunId(buildRunId(request.getStoreId(), request.getDocumentId())); + log.info("文件解析管道创建聚合结束,runId={}, storeId={}, documentId={}", + view.getRunId(), view.getStoreId(), view.getDocumentId()); + return view; + } + @Override public IngestionRunVO getRun(Long storeId, Long documentId) { log.info("文件解析管道聚合开始,storeId={}, documentId={}", storeId, documentId); @@ -104,6 +118,10 @@ public class IngestionRunServiceImpl implements IIngestionRunService { return view; } + private String buildRunId(Long storeId, Long documentId) { + return "ingestion-" + safeNumber(storeId) + "-" + safeNumber(documentId); + } + private IngestionRunFileVO toFileVO(RagDocumentResponse document) { IngestionRunFileVO file = new IngestionRunFileVO(); file.setDocumentId(document.getId()); diff --git a/common-agent-rag/src/test/java/com/bruce/rag/controller/IngestionRunControllerTests.java b/common-agent-rag/src/test/java/com/bruce/rag/controller/IngestionRunControllerTests.java new file mode 100644 index 0000000..45d89e8 --- /dev/null +++ b/common-agent-rag/src/test/java/com/bruce/rag/controller/IngestionRunControllerTests.java @@ -0,0 +1,86 @@ +package com.bruce.rag.controller; + +import com.bruce.common.handler.GlobalExceptionHandler; +import com.bruce.rag.service.IIngestionRunService; +import com.bruce.rag.vo.IngestionRunVO; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * 验证文件解析管道聚合接口的请求绑定与响应结构。 + */ +@ExtendWith(MockitoExtension.class) +class IngestionRunControllerTests { + + private MockMvc mockMvc; + + @Mock + private IIngestionRunService ingestionRunService; + + @InjectMocks + private IngestionRunController ingestionRunController; + + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.standaloneSetup(ingestionRunController) + .setControllerAdvice(new GlobalExceptionHandler()) + .build(); + } + + @Test + void createShouldReturnStructuredRunView() throws Exception { + IngestionRunVO run = new IngestionRunVO(); + run.setRunId("ingestion-1001-11"); + run.setStoreId(1001L); + run.setDocumentId(11L); + + when(ingestionRunService.createRun(any())).thenReturn(run); + + mockMvc.perform(post("/api/knowledge/ingestion-runs") + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "storeId": 1001, + "documentId": 11 + } + """)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.resultcode").value("0")) + .andExpect(jsonPath("$.data.runId").value("ingestion-1001-11")) + .andExpect(jsonPath("$.data.storeId").value("1001")) + .andExpect(jsonPath("$.data.documentId").value("11")); + } + + @Test + void detailShouldReturnStructuredRunView() throws Exception { + IngestionRunVO run = new IngestionRunVO(); + run.setRunId("run-20260601"); + run.setStoreId(1001L); + run.setDocumentId(11L); + + when(ingestionRunService.getRun(1001L, 11L)).thenReturn(run); + + mockMvc.perform(get("/api/knowledge/ingestion-runs/run-20260601") + .param("storeId", "1001") + .param("documentId", "11")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.resultcode").value("0")) + .andExpect(jsonPath("$.data.runId").value("run-20260601")) + .andExpect(jsonPath("$.data.storeId").value("1001")) + .andExpect(jsonPath("$.data.documentId").value("11")); + } +} diff --git a/common-agent-rag/src/test/java/com/bruce/rag/ingestion/IngestionRunServiceTests.java b/common-agent-rag/src/test/java/com/bruce/rag/ingestion/IngestionRunServiceTests.java index 54657c3..e4350cb 100644 --- a/common-agent-rag/src/test/java/com/bruce/rag/ingestion/IngestionRunServiceTests.java +++ b/common-agent-rag/src/test/java/com/bruce/rag/ingestion/IngestionRunServiceTests.java @@ -2,6 +2,7 @@ package com.bruce.rag.ingestion; import com.bruce.modelprovider.dto.response.RagStoreModelConfigResponse; import com.bruce.modelprovider.service.IRagStoreModelConfigService; +import com.bruce.rag.dto.request.IngestionRunCreateRequest; import com.bruce.rag.dto.response.RagDocumentResponse; import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.entity.RagChunk; @@ -51,6 +52,43 @@ class IngestionRunServiceTests { @InjectMocks private IngestionRunServiceImpl ingestionRunService; + @Test + void createRunShouldGenerateStableRunId() { + RagStoreResponse store = new RagStoreResponse(); + store.setId(1001L); + store.setStoreCode("PROD_DOC"); + store.setStoreName("产品制度库"); + + RagDocumentResponse document = new RagDocumentResponse(); + document.setId(11L); + document.setStoreId(1001L); + document.setDocumentTitle("售前方案模板.pdf"); + document.setParseStatus("PARSED"); + document.setIndexStatus("INDEXED"); + document.setCreateTime(new Date(1748780000000L)); + document.setUpdateTime(new Date(1748780300000L)); + + when(ragStoreService.getResponseById(1001L)).thenReturn(store); + when(ragDocumentService.getResponseById(11L)).thenReturn(document); + when(ragDocumentParseResultService.getByDocumentId(11L)).thenReturn(null); + when(ragChunkService.list(org.mockito.ArgumentMatchers.>any())) + .thenReturn(List.of()); + when(ragChunkEmbeddingService.list(org.mockito.ArgumentMatchers.>any())) + .thenReturn(List.of()); + when(ragStoreModelConfigService.getByStoreId(1001L)).thenReturn(null); + + IngestionRunCreateRequest request = new IngestionRunCreateRequest(); + request.setStoreId(1001L); + request.setDocumentId(11L); + + IngestionRunVO view = ingestionRunService.createRun(request); + + assertNotNull(view); + assertEquals("ingestion-1001-11", view.getRunId()); + assertEquals(1001L, view.getStoreId()); + assertEquals(11L, view.getDocumentId()); + } + @Test void getRunShouldAggregatePipelinePreviewAndLogs() { RagStoreResponse store = new RagStoreResponse(); diff --git a/common-agent-workflow/src/main/java/com/bruce/workflow/controller/WorkflowWorkspaceController.java b/common-agent-workflow/src/main/java/com/bruce/workflow/controller/WorkflowWorkspaceController.java index 25b675c..b0e2f9c 100644 --- a/common-agent-workflow/src/main/java/com/bruce/workflow/controller/WorkflowWorkspaceController.java +++ b/common-agent-workflow/src/main/java/com/bruce/workflow/controller/WorkflowWorkspaceController.java @@ -4,11 +4,19 @@ import com.bruce.common.domain.model.RequestResult; import com.bruce.workflow.service.IWorkflowWorkspaceService; import com.bruce.workflow.vo.WorkflowWorkspaceVO; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +/** + * Workflow 工作台聚合接口。 + *

+ * 该接口面向前端原型页面,负责把项目、流程、版本与最近运行记录收口成单一视图, + * 避免页面自行拼接多个底层管理接口。 + */ +@Slf4j @RestController @RequestMapping("/api/workflow-workspace") @RequiredArgsConstructor @@ -19,6 +27,14 @@ public class WorkflowWorkspaceController { @GetMapping("/detail") public RequestResult detail(@RequestParam("projectId") Long projectId, @RequestParam(value = "workflowId", required = false) Long workflowId) { - return RequestResult.success(workflowWorkspaceService.getWorkspace(projectId, workflowId)); + log.info("Workflow工作台查询开始,projectId={}, workflowId={}", projectId, workflowId); + WorkflowWorkspaceVO workspace = workflowWorkspaceService.getWorkspace(projectId, workflowId); + log.info("Workflow工作台查询结束,projectId={}, workflowId={}, workflowCount={}, versionCount={}, recentRunCount={}", + projectId, + workflowId, + workspace.getWorkflows() == null ? 0 : workspace.getWorkflows().size(), + workspace.getVersions() == null ? 0 : workspace.getVersions().size(), + workspace.getRecentRuns() == null ? 0 : workspace.getRecentRuns().size()); + return RequestResult.success(workspace); } } diff --git a/docs/模块完成度审计.md b/docs/模块完成度审计.md new file mode 100644 index 0000000..c041d5b --- /dev/null +++ b/docs/模块完成度审计.md @@ -0,0 +1,275 @@ +# Common Agent Studio 模块完成度审计 + +## 1. 审计范围 + +本次审计以当前仓库最新状态为准,核对以下资料与实现是否一致: + +- `docs/需求分析/*` +- `docs/设计文档/*` +- `docs/数据库设计/*` +- `docs/后端实现文档/*` +- `docs/前端实现文档/*` +- `script/sql/*.sql` + +审计目标不是重复设计方案,而是确认当前代码、接口、测试与文档约束之间的对应关系,并标记仍需持续关注的风险点。 + +## 2. 总体结论 + +- Maven 多模块单体骨架已落地,根 `pom.xml` 已拆分 `common-agent-boot`、`common-agent-common`、`common-agent-rag`、`common-agent-modelprovider`、`common-agent-agent`、`common-agent-workflow`、`common-agent-mcp`、`common-agent-skill`、`common-agent-observability`。 +- 后端已按业务域拆分模块,每个业务模块均已形成 `controller / service / service/impl / mapper / entity / dto / vo / factory` 主体结构。 +- `sys_enum`、整型枚举协议、`PersistableSysEnumDefinition` 契约、`BaseEntity` 审计习惯均保持不变。 +- 前端 Studio 九个工作台页面均已对接真实 API,API 层与页面单测已覆盖主要聚合接口。 +- 旧管理接口继续兼容;Studio 原型新增聚合接口用于支撑工作台页面,不替代低层 CRUD 接口。 + +## 3. 模块核对 + +### 3.1 common + +已核对内容: + +- 实体与 SQL 对应: + - `sys_enum` -> `common-agent-common/src/main/java/com/bruce/common/domain/entity/SysEnum.java` + - `sys_attachment` -> `common-agent-common/src/main/java/com/bruce/common/domain/entity/SysAttachment.java` +- 基础模型: + - `BaseEntity`、`RequestResult`、全局异常、审计配置均位于 `com.bruce.common` +- 接口: + - `POST /api/sys-enum/list` + - `POST /api/sys-enum/query` + - `POST /api/sys-enum/queryForManagement` + - `GET /api/sys-enum/detail` + - `POST /api/sys-enum/save` + - `POST /api/sys-enum/batchSave` + - `POST /api/sys-enum/delete` + - `POST /api/attachments/upload` +- 文档解析: + - `document/parse` 与 `document/parse/impl` 已提供解析抽象和解析器工厂 + +证据: + +- 代码:`common-agent-common/src/main/java/com/bruce/common/controller/*` +- 测试: + - `common-agent-common/src/test/java/com/bruce/common/controller/SysEnumControllerTests.java` + - `common-agent-common/src/test/java/com/bruce/common/factory/*` + - `common-agent-common/src/test/java/com/bruce/common/document/parse/*` + - `common-agent-common/src/test/java/com/bruce/common/handler/GlobalExceptionHandlerTests.java` + +### 3.2 rag + +已核对内容: + +- 实体已覆盖: + - `rag_store` + - `rag_document` + - `rag_document_parse_result` + - `rag_chunk` + - `rag_chunk_embedding` +- 旧接口保持兼容: + - `/api/rag/store/*` + - `/api/rag/documents/*` +- 聚合接口已提供: + - `GET /api/knowledge/workspaces/{storeId}` + - `POST /api/knowledge/ingestion-runs` + - `GET /api/knowledge/ingestion-runs/{runId}` +- 受控最小运行链路已落地: + - 批量上传 + - 手动解析 + - 手动切片 + - 向量化记录聚合查询 + +本轮补充: + +- 新增 `POST /api/knowledge/ingestion-runs`,与前端实现文档草案保持一致。 + +证据: + +- 代码: + - `common-agent-rag/src/main/java/com/bruce/rag/controller/*` + - `common-agent-rag/src/main/java/com/bruce/rag/service/impl/IngestionRunServiceImpl.java` +- 测试: + - `common-agent-rag/src/test/java/com/bruce/rag/controller/IngestionRunControllerTests.java` + - `common-agent-rag/src/test/java/com/bruce/rag/ingestion/IngestionRunServiceTests.java` + - `common-agent-rag/src/test/java/com/bruce/rag/workspace/KnowledgeWorkspaceServiceTests.java` + - 其余 `Rag*Tests` + +### 3.3 modelprovider + +已核对内容: + +- 实体已覆盖: + - `model_provider` + - `model_config` + - `model_route_rule` + - `rag_store_model_config` + - `model_call_log` +- 控制器已覆盖: + - `ModelProviderController` + - `ModelConfigController` + - `ModelRouteRuleController` + - `RagStoreModelConfigController` + - `ModelCallLogController` + - `ModelWorkspaceController` +- 网关抽象已位于 `gateway` + +证据: + +- 代码:`common-agent-modelprovider/src/main/java/com/bruce/modelprovider/**/*` +- 测试: + - `common-agent-modelprovider/src/test/java/com/bruce/modelprovider/controller/ModelWorkspaceControllerTests.java` + - `common-agent-modelprovider/src/test/java/com/bruce/modelprovider/workspace/ModelWorkspaceServiceTests.java` + - `common-agent-modelprovider/src/test/java/com/bruce/modelprovider/factory/ModelProviderFactoryTests.java` + +### 3.4 agent + +已核对内容: + +- 实体已覆盖: + - `agent_definition` + - `agent_session` + - `agent_message` + - `agent_capability_binding` +- 兼容接口与会话接口并存: + - Agent 定义管理 + - `/api/agents/{agentId}/chat` + - `/api/agent-sessions/*` + - 工作台聚合接口 + +证据: + +- 代码:`common-agent-agent/src/main/java/com/bruce/agent/**/*` +- 测试: + - `common-agent-agent/src/test/java/com/bruce/agent/controller/AgentSessionControllerTests.java` + - `common-agent-agent/src/test/java/com/bruce/agent/session/AgentSessionServiceTests.java` + - `common-agent-agent/src/test/java/com/bruce/agent/workspace/AgentWorkspaceServiceTests.java` + +### 3.5 workflow + +已核对内容: + +- 实体已覆盖: + - `studio_project` + - `workflow_definition` + - `workflow_version` + - `workflow_run` + - `workflow_run_step` +- 控制器已覆盖: + - `ProjectController` + - `WorkflowDefinitionController` + - `WorkflowVersionController` + - `WorkflowRunController` + - `WorkflowWorkspaceController` +- 前端工作台聚合使用 `GET /api/workflow-workspace/detail`; + 旧管理接口继续承担定义、版本与运行管理能力。 + +说明: + +- 前端实现文档中的 REST 草案与当前聚合接口命名不完全一致,但职责已由 `WorkflowWorkspaceController` 承接,且不影响旧接口兼容。 + +证据: + +- 代码:`common-agent-workflow/src/main/java/com/bruce/workflow/**/*` +- 测试: + - `common-agent-workflow/src/test/java/com/bruce/workflow/controller/WorkflowWorkspaceControllerTests.java` + - `common-agent-workflow/src/test/java/com/bruce/workflow/workspace/WorkflowWorkspaceServiceTests.java` + - `common-agent-workflow/src/test/java/com/bruce/workflow/version/WorkflowVersionServiceTests.java` + - `common-agent-workflow/src/test/java/com/bruce/workflow/WorkflowComponentStructureTests.java` + +### 3.6 mcp + +已核对内容: + +- 实体已覆盖: + - `mcp_server` + - `mcp_capability` +- 接口已覆盖: + - `POST /api/mcp/import` + - `GET /api/mcp/servers` + - `GET /api/mcp/servers/{serverId}/capabilities` + - `GET /api/mcp/servers/code/{serverCode}/capabilities` + - `POST /api/mcp/capabilities/save` + - `GET /api/mcp/workspace` + +证据: + +- 代码:`common-agent-mcp/src/main/java/com/bruce/mcp/**/*` +- 测试: + - `common-agent-mcp/src/test/java/com/bruce/mcp/controller/McpImportControllerTests.java` + - `common-agent-mcp/src/test/java/com/bruce/mcp/importing/McpImportServiceTests.java` + - `common-agent-mcp/src/test/java/com/bruce/mcp/workspace/McpWorkspaceServiceTests.java` + +### 3.7 skill + +已核对内容: + +- 实体已覆盖: + - `skill_definition` + - `skill_version` +- 工作台接口已覆盖: + - `GET /api/skills/{skillCode}` + - `POST /api/skills/{skillCode}/draft` + - `POST /api/skills/{skillCode}/test` + - `POST /api/skills/{skillCode}/publish` + - `POST /api/skills/{skillCode}/archive` + +证据: + +- 代码:`common-agent-skill/src/main/java/com/bruce/skill/**/*` +- 测试: + - `common-agent-skill/src/test/java/com/bruce/skill/controller/SkillWorkspaceControllerTests.java` + - `common-agent-skill/src/test/java/com/bruce/skill/version/SkillVersionServiceTests.java` + - `common-agent-skill/src/test/java/com/bruce/skill/workspace/SkillWorkspaceServiceTests.java` + +### 3.8 observability + +已核对内容: + +- 聚合来源已复用: + - `workflow_run` + - `workflow_run_step` + - `model_call_log` + - `agent_session` + - `agent_message` +- 接口已覆盖: + - `GET /api/observability/runs` + - `GET /api/observability/runs/{requestId}` + - `GET /api/observability/model-calls` + - `GET /api/observability/runs/{requestId}/export` +- 导出接口返回脱敏摘要对象 + +证据: + +- 代码:`common-agent-observability/src/main/java/com/bruce/observability/**/*` +- 测试: + - `common-agent-observability/src/test/java/com/bruce/observability/controller/ObservabilityTraceControllerTests.java` + - `common-agent-observability/src/test/java/com/bruce/observability/trace/ObservabilityTraceServiceTests.java` + +## 4. 前端对接核对 + +已核对内容: + +- Studio 页面: + - `frontend/src/pages/studio/StudioDashboardPage.vue` + - `frontend/src/pages/studio/KnowledgeWorkspacePage.vue` + - `frontend/src/pages/studio/IngestionPipelinePage.vue` + - `frontend/src/pages/studio/ModelWorkspacePage.vue` + - `frontend/src/pages/studio/WorkflowBuilderPage.vue` + - `frontend/src/pages/studio/AgentWorkspacePage.vue` + - `frontend/src/pages/studio/McpImportPage.vue` + - `frontend/src/pages/studio/SkillWorkspacePage.vue` + - `frontend/src/pages/studio/ObservabilityPage.vue` +- API 封装已覆盖: + - `frontend/src/api/*.ts` +- 页面/API 单测已覆盖: + - `frontend/src/pages/studio/__tests__/*` + - `frontend/src/api/__tests__/*` + +## 5. 当前仍需持续关注的风险 + +- 当前多数“mapper / repository 验证”仍以结构契约测试为主,真实数据库集成测试覆盖度有限。 +- 部分前端实现文档中的接口命名是草案,当前实现更多采用“旧管理接口 + Studio 聚合接口”的双轨方式;职责已覆盖,但验收时需要按“能力是否已落地”而非“路径字面一致”判断。 +- 现有运行链路以“主数据优先 + 最小可运行”实现为主,复杂分支调度、远程 MCP 实时执行编排、重型运行器能力仍适合后续继续增强。 + +## 6. 本次审计后的新增变更 + +- 新增 `POST /api/knowledge/ingestion-runs`,补齐前端实现文档中的摄取运行创建入口。 +- 补充 `IngestionRunControllerTests` 与前端 `ingestion.spec.ts` 创建接口测试。 +- 补充 `WorkflowWorkspaceController` 中文注释与标准化业务日志。 diff --git a/frontend/src/api/__tests__/ingestion.spec.ts b/frontend/src/api/__tests__/ingestion.spec.ts index 5ab62f3..78cbf78 100644 --- a/frontend/src/api/__tests__/ingestion.spec.ts +++ b/frontend/src/api/__tests__/ingestion.spec.ts @@ -1,14 +1,33 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; const getMock = vi.fn(); +const postMock = vi.fn(); vi.mock('../request', () => ({ get: getMock, + post: postMock, })); describe('ingestion api', () => { afterEach(() => { getMock.mockReset(); + postMock.mockReset(); + }); + + it('creates ingestion run aggregate with store and document payload', async () => { + postMock.mockResolvedValue({ + resultcode: '0', + message: null, + data: { runId: 'ingestion-1001-11' }, + }); + + const { createIngestionRun } = await import('../ingestion'); + await createIngestionRun('1001', '11'); + + expect(postMock).toHaveBeenCalledWith('/knowledge/ingestion-runs', { + storeId: '1001', + documentId: '11', + }); }); it('requests ingestion run aggregate with store and document params', async () => { diff --git a/frontend/src/api/ingestion.ts b/frontend/src/api/ingestion.ts index 17995ed..3f17ccb 100644 --- a/frontend/src/api/ingestion.ts +++ b/frontend/src/api/ingestion.ts @@ -1,4 +1,4 @@ -import { get } from './request'; +import { get, post } from './request'; export interface IngestionRunFile { documentId: string; @@ -39,6 +39,13 @@ export interface IngestionRun { logs: IngestionRunLog[]; } +export function createIngestionRun(storeId: string, documentId: string) { + return post('/knowledge/ingestion-runs', { + storeId, + documentId, + }); +} + export function getIngestionRun(runId: string, storeId: string, documentId: string) { return get(`/knowledge/ingestion-runs/${runId}`, { params: {