diff --git a/server/src/app/api/v1/router.py b/server/src/app/api/v1/router.py index 911ebb8..a7ccbc0 100644 --- a/server/src/app/api/v1/router.py +++ b/server/src/app/api/v1/router.py @@ -8,8 +8,10 @@ from app.api.v1.endpoints.bootstrap import router as bootstrap_router from app.api.v1.endpoints.employees import router as employees_router from app.api.v1.endpoints.health import router as health_router from app.api.v1.endpoints.knowledge import router as knowledge_router -from app.api.v1.endpoints.reimbursements import router as reimbursements_router -from app.api.v1.endpoints.settings import router as settings_router +from app.api.v1.endpoints.ontology import router as ontology_router +from app.api.v1.endpoints.orchestrator import router as orchestrator_router +from app.api.v1.endpoints.reimbursements import router as reimbursements_router +from app.api.v1.endpoints.settings import router as settings_router router = APIRouter() router.include_router(health_router, tags=["health"]) @@ -19,6 +21,8 @@ router.include_router(agent_assets_router, tags=["agent-assets"]) router.include_router(agent_runs_router, tags=["agent-runs"]) router.include_router(audit_logs_router, tags=["audit-logs"]) router.include_router(knowledge_router, tags=["knowledge"]) +router.include_router(ontology_router, tags=["ontology"]) +router.include_router(orchestrator_router, tags=["orchestrator"]) router.include_router(employees_router, prefix="/employees", tags=["employees"]) router.include_router(reimbursements_router, prefix="/reimbursements", tags=["reimbursements"]) router.include_router(settings_router, tags=["settings"]) diff --git a/server/src/app/core/openapi.py b/server/src/app/core/openapi.py index f5971c5..b5e97ce 100644 --- a/server/src/app/core/openapi.py +++ b/server/src/app/core/openapi.py @@ -27,6 +27,8 @@ X-Financial 后端 OpenAPI 文档。 - 员工目录 - 报销单 - 知识库与 ONLYOFFICE +- 语义本体解析 +- Orchestrator 统一调度 - 系统设置与模型连通性 - Agent 资产、运行日志、审计日志 """.strip() @@ -57,6 +59,14 @@ OPENAPI_TAGS = [ "name": "knowledge", "description": "知识库文件管理、内容访问与 ONLYOFFICE 集成接口。", }, + { + "name": "ontology", + "description": "Day 3 语义本体解析接口,把自然语言问题稳定转换为 8 个核心字段。", + }, + { + "name": "orchestrator", + "description": "Day 4 Orchestrator 统一入口,负责语义、权限、路由、工具调用和降级。", + }, { "name": "settings", "description": "系统设置、模型配置、模型连通性探测和 Hermes 运行时模型配置。", diff --git a/server/src/app/services/agent_runs.py b/server/src/app/services/agent_runs.py index 3f526a5..b34b70c 100644 --- a/server/src/app/services/agent_runs.py +++ b/server/src/app/services/agent_runs.py @@ -76,6 +76,45 @@ class AgentRunService: logger.info("Created agent run id=%s run_id=%s", created.id, created.run_id) return self._serialize_run(created) + def update_run( + self, + run_id: str, + *, + agent: str | None = None, + ontology_json: dict[str, Any] | None = None, + route_json: dict[str, Any] | None = None, + permission_level: str | None = None, + status: str | None = None, + result_summary: str | None = None, + error_message: str | None = None, + finished_at: datetime | None = None, + ) -> AgentRunRead: + self._ensure_ready() + run = self.repository.get_by_run_id(run_id) + if run is None: + raise LookupError("Run not found") + + if agent is not None: + run.agent = agent + if ontology_json is not None: + run.ontology_json = ontology_json + if route_json is not None: + run.route_json = route_json + if permission_level is not None: + run.permission_level = permission_level + if status is not None: + run.status = status + if result_summary is not None: + run.result_summary = result_summary + if error_message is not None: + run.error_message = error_message + if finished_at is not None: + run.finished_at = finished_at + + updated = self.repository.save_run(run) + logger.info("Updated agent run run_id=%s status=%s", updated.run_id, updated.status) + return self._serialize_run(updated) + def record_tool_call( self, *, diff --git a/server/tests/test_openapi_schema.py b/server/tests/test_openapi_schema.py index 21eabb8..e990cf9 100644 --- a/server/tests/test_openapi_schema.py +++ b/server/tests/test_openapi_schema.py @@ -10,6 +10,8 @@ def test_openapi_schema_includes_documented_backend_routes() -> None: assert schema["info"]["title"] == get_settings().app_name assert any(tag["name"] == "agent-assets" for tag in schema["tags"]) assert any(tag["name"] == "knowledge" for tag in schema["tags"]) + assert any(tag["name"] == "ontology" for tag in schema["tags"]) + assert any(tag["name"] == "orchestrator" for tag in schema["tags"]) agent_assets_post = schema["paths"]["/api/v1/agent-assets"]["post"] assert agent_assets_post["summary"] == "创建 Agent 资产" @@ -25,5 +27,13 @@ def test_openapi_schema_includes_documented_backend_routes() -> None: assert knowledge_callback_post["summary"] == "接收 ONLYOFFICE 回调" assert "application/json" in knowledge_callback_post["requestBody"]["content"] + ontology_parse_post = schema["paths"]["/api/v1/ontology/parse"]["post"] + assert ontology_parse_post["summary"] == "解析自然语言为语义本体" + assert "application/json" in ontology_parse_post["requestBody"]["content"] + + orchestrator_run_post = schema["paths"]["/api/v1/orchestrator/run"]["post"] + assert orchestrator_run_post["summary"] == "运行 Orchestrator 统一调度" + assert "application/json" in orchestrator_run_post["requestBody"]["content"] + root_get = schema["paths"]["/"]["get"] assert root_get["summary"] == "服务根检查"