生成代码工程
This commit is contained in:
parent
1dfee83f7d
commit
bc1d9974e9
121
README.md
121
README.md
|
|
@ -1,3 +1,120 @@
|
||||||
# 商城
|
# 多智能体协同研发辅助系统 - 底座平台
|
||||||
|
|
||||||
暂无描述
|
## 项目简介
|
||||||
|
|
||||||
|
本项目是一个基于 Spring Boot 3.x 构建的多智能体协同研发辅助系统底座平台,提供智能体注册与发现、执行流编排、任务调度、上下文管理等核心能力,支持第三方智能体快速接入。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- **Java 17**
|
||||||
|
- **Spring Boot 3.2.5**
|
||||||
|
- **Maven**
|
||||||
|
- **Knife4j / Swagger OpenAPI 3.0**(接口文档)
|
||||||
|
|
||||||
|
## 核心功能
|
||||||
|
|
||||||
|
| 模块 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 智能体管理 | 智能体注册、注销、查询、心跳检测、能力标签发现 |
|
||||||
|
| 执行流管理 | 执行流创建、查询、删除、触发执行 |
|
||||||
|
| 任务调度 | 执行流解析、依赖排序、节点状态跟踪(预留扩展) |
|
||||||
|
| 上下文管理 | 全局数据 + 节点输出 + 元信息分层传递(预留扩展) |
|
||||||
|
| 接口文档 | 集成 Knife4j + Swagger 3,提供可视化 API 调试页面 |
|
||||||
|
|
||||||
|
## 快速启动
|
||||||
|
|
||||||
|
### 前提条件
|
||||||
|
|
||||||
|
- JDK 17+
|
||||||
|
- Maven 3.6+
|
||||||
|
|
||||||
|
### 编译与运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆项目后进入目录
|
||||||
|
cd multi-agent-platform
|
||||||
|
|
||||||
|
# 编译打包
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
|
||||||
|
# 运行
|
||||||
|
java -jar target/demo-0.0.1-SNAPSHOT.jar
|
||||||
|
|
||||||
|
# 或者直接使用 Maven 运行
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
### 访问接口文档
|
||||||
|
|
||||||
|
启动后访问以下地址:
|
||||||
|
|
||||||
|
- **Knife4j UI**: http://localhost:8080/doc.html
|
||||||
|
- **Swagger UI**: http://localhost:8080/swagger-ui.html
|
||||||
|
- **OpenAPI JSON**: http://localhost:8080/v3/api-docs
|
||||||
|
|
||||||
|
## 健康检查
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8080/health
|
||||||
|
# 返回: {"status":"UP","timestamp":"...","service":"multi-agent-platform"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 概览
|
||||||
|
|
||||||
|
| 接口 | 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 健康检查 | GET | `/health` | 系统健康状态 |
|
||||||
|
| 注册智能体 | POST | `/api/v1/agent/register` | 注册新智能体 |
|
||||||
|
| 注销智能体 | DELETE | `/api/v1/agent/unregister?id=xxx` | 注销指定智能体 |
|
||||||
|
| 查询智能体列表 | GET | `/api/v1/agent/list?capability=xxx` | 按能力标签或查询全部 |
|
||||||
|
| 查询智能体详情 | GET | `/api/v1/agent/{id}` | 查询单个智能体 |
|
||||||
|
| 更新心跳 | PUT | `/api/v1/agent/{id}/heartbeat` | 更新智能体心跳 |
|
||||||
|
| 创建执行流 | POST | `/api/v1/flow` | 创建执行流配置 |
|
||||||
|
| 获取执行流 | GET | `/api/v1/flow/{id}` | 获取执行流详情 |
|
||||||
|
| 查询所有执行流 | GET | `/api/v1/flow` | 获取全部执行流 |
|
||||||
|
| 删除执行流 | DELETE | `/api/v1/flow/{id}` | 删除执行流 |
|
||||||
|
| 触发执行流 | POST | `/api/v1/flow/execute` | 触发执行流运行 |
|
||||||
|
| 查询执行状态 | GET | `/api/v1/flow/execution/{executionId}` | 查询执行进度 |
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/java/com/example/demo/
|
||||||
|
├── DemoApplication.java # 启动类
|
||||||
|
├── config/
|
||||||
|
│ └── OpenApiConfig.java # Swagger/Knife4j 配置
|
||||||
|
├── controller/
|
||||||
|
│ ├── HealthController.java # 健康检查
|
||||||
|
│ ├── BusinessController.java # 智能体管理 API
|
||||||
|
│ └── FlowController.java # 执行流管理 API
|
||||||
|
├── model/
|
||||||
|
│ ├── BusinessItem.java # 智能体元数据模型
|
||||||
|
│ ├── ExecutionFlow.java # 执行流配置模型
|
||||||
|
│ └── dto/
|
||||||
|
│ ├── ApiResponse.java # 统一响应封装
|
||||||
|
│ ├── AgentRegisterRequest.java # 注册请求
|
||||||
|
│ └── FlowExecuteRequest.java # 执行触发请求
|
||||||
|
├── service/
|
||||||
|
│ ├── BusinessService.java # 智能体服务接口
|
||||||
|
│ ├── BusinessServiceImpl.java # 智能体服务实现(内存)
|
||||||
|
│ ├── FlowService.java # 执行流服务接口
|
||||||
|
│ └── FlowServiceImpl.java # 执行流服务实现(内存)
|
||||||
|
src/test/java/com/example/demo/
|
||||||
|
├── DemoApplicationTests.java # 应用启动测试
|
||||||
|
└── BusinessServiceTest.java # 智能体服务单元测试
|
||||||
|
```
|
||||||
|
|
||||||
|
## 设计说明
|
||||||
|
|
||||||
|
### 当前实现(内存存储)
|
||||||
|
|
||||||
|
所有业务数据基于 `ConcurrentHashMap` 存储在内存中,无需安装任何外部中间件即可启动运行。适用于功能验证、开发调试与接口联调。
|
||||||
|
|
||||||
|
### 后续扩展预留
|
||||||
|
|
||||||
|
- **Repository 层**:当前 Service 直接操作内存 Map,后续可抽取 Repository 接口,对接 MySQL/PostgreSQL
|
||||||
|
- **缓存层**:可引入 Redis 实现分布式缓存与心跳检测
|
||||||
|
- **消息队列**:可引入 MQ 实现异步任务调度与事件通知
|
||||||
|
- **调度引擎**:当前 `executeFlow` 为模拟实现,后续可对接真正的拓扑排序 + 线程池调度
|
||||||
|
- **认证授权**:可集成 Spring Security + JWT + RBAC
|
||||||
|
- **智能体 SDK**:可提供标准 SDK 封装注册、心跳、执行等流程
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.2.5</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.example</groupId>
|
||||||
|
<artifactId>demo</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>multi-agent-platform</name>
|
||||||
|
<description>多智能体协同研发辅助系统 - 底座平台</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<knife4j.version>4.4.0</knife4j.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Spring Boot Web -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Knife4j / Swagger OpenAPI (Spring Boot 3.x Jakarta) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
|
<version>${knife4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.example.demo;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多智能体协同研发辅助系统 - 底座平台启动类。
|
||||||
|
* <p>
|
||||||
|
* 负责初始化 Spring 应用上下文,启动嵌入式 Web 服务器,
|
||||||
|
* 并提供智能体注册、执行流编排与任务调度等核心能力。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
public class DemoApplication {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用主入口。
|
||||||
|
*
|
||||||
|
* @param args 命令行参数
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(DemoApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.example.demo.config;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.info.Contact;
|
||||||
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenAPI / Knife4j 接口文档自动配置类。
|
||||||
|
* <p>
|
||||||
|
* 提供标准化的 API 文档元信息,包括标题、版本、描述和联系方式,
|
||||||
|
* 集成 Knife4j 增强 UI 以提升接口调试体验。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class OpenApiConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建自定义 OpenAPI 实例。
|
||||||
|
*
|
||||||
|
* @return 包含文档元信息的 OpenAPI 对象
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public OpenAPI customOpenAPI() {
|
||||||
|
return new OpenAPI()
|
||||||
|
.info(new Info()
|
||||||
|
.title("多智能体协同研发辅助系统 API")
|
||||||
|
.version("1.0.0")
|
||||||
|
.description("底座平台接口文档,支持智能体注册、执行流编排与任务调度")
|
||||||
|
.contact(new Contact()
|
||||||
|
.name("开发团队")
|
||||||
|
.email("dev@example.com")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.example.demo.controller;
|
||||||
|
|
||||||
|
import com.example.demo.model.BusinessItem;
|
||||||
|
import com.example.demo.model.dto.AgentRegisterRequest;
|
||||||
|
import com.example.demo.model.dto.ApiResponse;
|
||||||
|
import com.example.demo.service.BusinessService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体管理控制器。
|
||||||
|
* <p>
|
||||||
|
* 提供智能体注册、注销、查询与心跳检测的 RESTful 接口。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Tag(name = "智能体管理", description = "智能体注册、注销、查询与心跳检测")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/agent")
|
||||||
|
public class BusinessController {
|
||||||
|
|
||||||
|
private final BusinessService businessService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造注入智能体管理服务。
|
||||||
|
*
|
||||||
|
* @param businessService 智能体管理服务
|
||||||
|
*/
|
||||||
|
public BusinessController(BusinessService businessService) {
|
||||||
|
this.businessService = businessService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册新的智能体。
|
||||||
|
*
|
||||||
|
* @param request 注册请求 DTO
|
||||||
|
* @return 注册成功的智能体元数据
|
||||||
|
*/
|
||||||
|
@Operation(summary = "注册智能体", description = "向底座注册一个新的智能体实例")
|
||||||
|
@PostMapping("/register")
|
||||||
|
public ResponseEntity<ApiResponse<BusinessItem>> register(@RequestBody AgentRegisterRequest request) {
|
||||||
|
BusinessItem item = new BusinessItem(
|
||||||
|
request.getId(),
|
||||||
|
request.getName(),
|
||||||
|
request.getVersion(),
|
||||||
|
request.getServiceUrl(),
|
||||||
|
request.getCapabilities(),
|
||||||
|
request.getInputSchema(),
|
||||||
|
request.getOutputSchema(),
|
||||||
|
request.isStreamingSupport(),
|
||||||
|
request.getHealthCheckEndpoint(),
|
||||||
|
"active"
|
||||||
|
);
|
||||||
|
BusinessItem registered = businessService.register(item);
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("注册成功", registered));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销指定智能体。
|
||||||
|
*
|
||||||
|
* @param id 智能体唯一标识
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "注销智能体", description = "根据 ID 注销已注册的智能体")
|
||||||
|
@DeleteMapping("/unregister")
|
||||||
|
public ResponseEntity<ApiResponse<Void>> unregister(
|
||||||
|
@Parameter(description = "智能体 ID") @RequestParam String id) {
|
||||||
|
boolean removed = businessService.unregister(id);
|
||||||
|
if (removed) {
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("注销成功", null));
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(ApiResponse.error(404, "智能体未找到: " + id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询智能体列表。
|
||||||
|
*
|
||||||
|
* @param capability 可选的能力标签过滤
|
||||||
|
* @return 智能体列表
|
||||||
|
*/
|
||||||
|
@Operation(summary = "查询智能体列表", description = "按能力标签查询或查询全部已注册智能体")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public ResponseEntity<ApiResponse<List<BusinessItem>>> list(
|
||||||
|
@Parameter(description = "能力标签(可选)") @RequestParam(required = false) String capability) {
|
||||||
|
List<BusinessItem> agents;
|
||||||
|
if (capability != null && !capability.isBlank()) {
|
||||||
|
agents = businessService.findByCapability(capability);
|
||||||
|
} else {
|
||||||
|
agents = businessService.findAll();
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(ApiResponse.success(agents));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询单个智能体详情。
|
||||||
|
*
|
||||||
|
* @param id 智能体 ID
|
||||||
|
* @return 智能体详情
|
||||||
|
*/
|
||||||
|
@Operation(summary = "查询智能体详情", description = "根据 ID 查询单个智能体详细信息")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<ApiResponse<BusinessItem>> getById(
|
||||||
|
@Parameter(description = "智能体 ID") @PathVariable String id) {
|
||||||
|
return businessService.findById(id)
|
||||||
|
.map(agent -> ResponseEntity.ok(ApiResponse.success(agent)))
|
||||||
|
.orElse(ResponseEntity.ok(ApiResponse.error(404, "智能体未找到: " + id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新指定智能体的心跳时间。
|
||||||
|
*
|
||||||
|
* @param id 智能体 ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "更新心跳", description = "更新指定智能体的最近心跳时间戳")
|
||||||
|
@PutMapping("/{id}/heartbeat")
|
||||||
|
public ResponseEntity<ApiResponse<Void>> heartbeat(
|
||||||
|
@Parameter(description = "智能体 ID") @PathVariable String id) {
|
||||||
|
boolean updated = businessService.updateHeartbeat(id);
|
||||||
|
if (updated) {
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("心跳更新成功", null));
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(ApiResponse.error(404, "智能体未找到: " + id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
package com.example.demo.controller;
|
||||||
|
|
||||||
|
import com.example.demo.model.ExecutionFlow;
|
||||||
|
import com.example.demo.model.dto.ApiResponse;
|
||||||
|
import com.example.demo.model.dto.ExecutionResult;
|
||||||
|
import com.example.demo.model.dto.FlowExecuteRequest;
|
||||||
|
import com.example.demo.service.FlowService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流管理控制器。
|
||||||
|
* <p>
|
||||||
|
* 提供执行流的创建、查询、删除、触发执行与状态查询的 RESTful 接口。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Tag(name = "执行流管理", description = "执行流的创建、查询、删除、触发执行与状态跟踪")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/flow")
|
||||||
|
public class FlowController {
|
||||||
|
|
||||||
|
private final FlowService flowService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造注入执行流管理服务。
|
||||||
|
*
|
||||||
|
* @param flowService 执行流服务
|
||||||
|
*/
|
||||||
|
public FlowController(FlowService flowService) {
|
||||||
|
this.flowService = flowService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的执行流配置。
|
||||||
|
*
|
||||||
|
* @param flow 执行流配置 JSON
|
||||||
|
* @return 创建成功的执行流
|
||||||
|
*/
|
||||||
|
@Operation(summary = "创建执行流", description = "创建新的执行流配置,包含节点、边关系和上下文映射")
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<ApiResponse<ExecutionFlow>> createFlow(@RequestBody ExecutionFlow flow) {
|
||||||
|
ExecutionFlow created = flowService.createFlow(flow);
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("创建成功", created));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定执行流详情。
|
||||||
|
*
|
||||||
|
* @param id 执行流 ID
|
||||||
|
* @return 执行流详情
|
||||||
|
*/
|
||||||
|
@Operation(summary = "获取执行流", description = "根据 ID 获取执行流配置详情")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<ApiResponse<ExecutionFlow>> getFlow(
|
||||||
|
@Parameter(description = "执行流 ID") @PathVariable String id) {
|
||||||
|
return flowService.getFlow(id)
|
||||||
|
.map(flow -> ResponseEntity.ok(ApiResponse.success(flow)))
|
||||||
|
.orElse(ResponseEntity.ok(ApiResponse.error(404, "执行流未找到: " + id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有执行流。
|
||||||
|
*
|
||||||
|
* @return 执行流列表
|
||||||
|
*/
|
||||||
|
@Operation(summary = "查询所有执行流", description = "获取全部已创建的执行流配置列表")
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<ApiResponse<List<ExecutionFlow>>> listFlows() {
|
||||||
|
List<ExecutionFlow> flows = flowService.listFlows();
|
||||||
|
return ResponseEntity.ok(ApiResponse.success(flows));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定执行流。
|
||||||
|
*
|
||||||
|
* @param id 执行流 ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "删除执行流", description = "根据 ID 删除指定的执行流配置")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ResponseEntity<ApiResponse<Void>> deleteFlow(
|
||||||
|
@Parameter(description = "执行流 ID") @PathVariable String id) {
|
||||||
|
boolean deleted = flowService.deleteFlow(id);
|
||||||
|
if (deleted) {
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("删除成功", null));
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(ApiResponse.error(404, "执行流未找到: " + id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发执行流运行。
|
||||||
|
*
|
||||||
|
* @param request 执行触发请求
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "触发执行流", description = "手动触发指定执行流运行,返回执行记录 ID 和状态")
|
||||||
|
@PostMapping("/execute")
|
||||||
|
public ResponseEntity<ApiResponse<ExecutionResult>> executeFlow(@RequestBody FlowExecuteRequest request) {
|
||||||
|
ExecutionResult result = flowService.executeFlow(
|
||||||
|
request.getFlowId(),
|
||||||
|
request.getTriggeredBy(),
|
||||||
|
request.getTriggerMode());
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("执行已触发", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定执行记录的状态与结果。
|
||||||
|
*
|
||||||
|
* @param executionId 执行记录 ID
|
||||||
|
* @return 执行详情
|
||||||
|
*/
|
||||||
|
@Operation(summary = "查询执行状态", description = "根据执行记录 ID 查询执行进度与结果详情")
|
||||||
|
@GetMapping("/execution/{executionId}")
|
||||||
|
public ResponseEntity<ApiResponse<ExecutionResult>> getExecution(
|
||||||
|
@Parameter(description = "执行记录 ID") @PathVariable String executionId) {
|
||||||
|
return flowService.getExecutionResult(executionId)
|
||||||
|
.map(result -> ResponseEntity.ok(ApiResponse.success(result)))
|
||||||
|
.orElse(ResponseEntity.ok(ApiResponse.error(404, "执行记录未找到: " + executionId)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.example.demo.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统健康检查控制器。
|
||||||
|
* <p>
|
||||||
|
* 提供系统运行状态检查接口,可用于 Kubernetes 存活/就绪探针。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Tag(name = "系统管理", description = "系统健康检查等基础管理接口")
|
||||||
|
@RestController
|
||||||
|
public class HealthController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 健康检查接口。
|
||||||
|
*
|
||||||
|
* @return 包含状态、时间戳和服务名称的健康信息
|
||||||
|
*/
|
||||||
|
@Operation(summary = "健康检查", description = "返回系统当前运行状态")
|
||||||
|
@GetMapping("/health")
|
||||||
|
public ResponseEntity<Map<String, Object>> health() {
|
||||||
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
|
result.put("status", "UP");
|
||||||
|
result.put("timestamp", LocalDateTime.now().toString());
|
||||||
|
result.put("service", "multi-agent-platform");
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
package com.example.demo.model;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体元数据模型。
|
||||||
|
* <p>
|
||||||
|
* 表示一个已注册的智能体实例,包含智能体的唯一标识、名称、版本、
|
||||||
|
* 服务地址、能力标签列表、输入输出 Schema、流式支持状态、健康检查端点、
|
||||||
|
* 当前状态以及生命周期时间戳等信息。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class BusinessItem {
|
||||||
|
|
||||||
|
/** 智能体唯一标识 */
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/** 智能体名称 */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** 智能体版本号 */
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/** 智能体 Web 服务地址 */
|
||||||
|
private String serviceUrl;
|
||||||
|
|
||||||
|
/** 智能体能力标签列表 */
|
||||||
|
private List<String> capabilities;
|
||||||
|
|
||||||
|
/** 输入 Schema(JSON Schema 格式) */
|
||||||
|
private Map<String, Object> inputSchema;
|
||||||
|
|
||||||
|
/** 输出 Schema(JSON Schema 格式) */
|
||||||
|
private Map<String, Object> outputSchema;
|
||||||
|
|
||||||
|
/** 是否支持流式输出(SSE) */
|
||||||
|
private boolean streamingSupport;
|
||||||
|
|
||||||
|
/** 健康检查接口路径 */
|
||||||
|
private String healthCheckEndpoint;
|
||||||
|
|
||||||
|
/** 智能体状态:active / inactive / pending_review */
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/** 最近一次心跳时间 */
|
||||||
|
private LocalDateTime lastHeartbeat;
|
||||||
|
|
||||||
|
/** 注册时间 */
|
||||||
|
private LocalDateTime registeredAt;
|
||||||
|
|
||||||
|
public BusinessItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全参构造器。
|
||||||
|
*
|
||||||
|
* @param id 智能体 ID
|
||||||
|
* @param name 名称
|
||||||
|
* @param version 版本
|
||||||
|
* @param serviceUrl 服务地址
|
||||||
|
* @param capabilities 能力标签
|
||||||
|
* @param inputSchema 输入 Schema
|
||||||
|
* @param outputSchema 输出 Schema
|
||||||
|
* @param streamingSupport 是否支持流式
|
||||||
|
* @param healthCheckEndpoint 健康检查端点
|
||||||
|
* @param status 状态
|
||||||
|
*/
|
||||||
|
public BusinessItem(String id, String name, String version, String serviceUrl,
|
||||||
|
List<String> capabilities, Map<String, Object> inputSchema,
|
||||||
|
Map<String, Object> outputSchema, boolean streamingSupport,
|
||||||
|
String healthCheckEndpoint, String status) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.version = version;
|
||||||
|
this.serviceUrl = serviceUrl;
|
||||||
|
this.capabilities = capabilities;
|
||||||
|
this.inputSchema = inputSchema;
|
||||||
|
this.outputSchema = outputSchema;
|
||||||
|
this.streamingSupport = streamingSupport;
|
||||||
|
this.healthCheckEndpoint = healthCheckEndpoint;
|
||||||
|
this.status = status;
|
||||||
|
this.registeredAt = LocalDateTime.now();
|
||||||
|
this.lastHeartbeat = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Getters / Setters ----------
|
||||||
|
|
||||||
|
public String getId() { return id; }
|
||||||
|
|
||||||
|
public void setId(String id) { this.id = id; }
|
||||||
|
|
||||||
|
public String getName() { return name; }
|
||||||
|
|
||||||
|
public void setName(String name) { this.name = name; }
|
||||||
|
|
||||||
|
public String getVersion() { return version; }
|
||||||
|
|
||||||
|
public void setVersion(String version) { this.version = version; }
|
||||||
|
|
||||||
|
public String getServiceUrl() { return serviceUrl; }
|
||||||
|
|
||||||
|
public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; }
|
||||||
|
|
||||||
|
public List<String> getCapabilities() { return capabilities; }
|
||||||
|
|
||||||
|
public void setCapabilities(List<String> capabilities) { this.capabilities = capabilities; }
|
||||||
|
|
||||||
|
public Map<String, Object> getInputSchema() { return inputSchema; }
|
||||||
|
|
||||||
|
public void setInputSchema(Map<String, Object> inputSchema) { this.inputSchema = inputSchema; }
|
||||||
|
|
||||||
|
public Map<String, Object> getOutputSchema() { return outputSchema; }
|
||||||
|
|
||||||
|
public void setOutputSchema(Map<String, Object> outputSchema) { this.outputSchema = outputSchema; }
|
||||||
|
|
||||||
|
public boolean isStreamingSupport() { return streamingSupport; }
|
||||||
|
|
||||||
|
public void setStreamingSupport(boolean streamingSupport) { this.streamingSupport = streamingSupport; }
|
||||||
|
|
||||||
|
public String getHealthCheckEndpoint() { return healthCheckEndpoint; }
|
||||||
|
|
||||||
|
public void setHealthCheckEndpoint(String healthCheckEndpoint) { this.healthCheckEndpoint = healthCheckEndpoint; }
|
||||||
|
|
||||||
|
public String getStatus() { return status; }
|
||||||
|
|
||||||
|
public void setStatus(String status) { this.status = status; }
|
||||||
|
|
||||||
|
public LocalDateTime getLastHeartbeat() { return lastHeartbeat; }
|
||||||
|
|
||||||
|
public void setLastHeartbeat(LocalDateTime lastHeartbeat) { this.lastHeartbeat = lastHeartbeat; }
|
||||||
|
|
||||||
|
public LocalDateTime getRegisteredAt() { return registeredAt; }
|
||||||
|
|
||||||
|
public void setRegisteredAt(LocalDateTime registeredAt) { this.registeredAt = registeredAt; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
package com.example.demo.model;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流配置模型。
|
||||||
|
* <p>
|
||||||
|
* 表示一个完整的执行流定义,包含节点列表、边关系、上下文映射配置
|
||||||
|
* 以及执行流的基本元信息(如名称、描述、创建时间等)。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class ExecutionFlow {
|
||||||
|
|
||||||
|
/** 执行流唯一标识 */
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/** 执行流名称 */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** 执行流描述 */
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/** 关联项目 ID(预留) */
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
/** 节点列表 */
|
||||||
|
private List<FlowNode> nodes;
|
||||||
|
|
||||||
|
/** 边关系列表 */
|
||||||
|
private List<FlowEdge> edges;
|
||||||
|
|
||||||
|
/** 上下文映射配置 */
|
||||||
|
private Map<String, ContextMapping> contextMapping;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public ExecutionFlow() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全参构造器。
|
||||||
|
*
|
||||||
|
* @param id 执行流 ID
|
||||||
|
* @param name 名称
|
||||||
|
* @param description 描述
|
||||||
|
* @param nodes 节点列表
|
||||||
|
* @param edges 边关系列表
|
||||||
|
* @param contextMapping 上下文映射
|
||||||
|
*/
|
||||||
|
public ExecutionFlow(String id, String name, String description,
|
||||||
|
List<FlowNode> nodes, List<FlowEdge> edges,
|
||||||
|
Map<String, ContextMapping> contextMapping) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.nodes = nodes;
|
||||||
|
this.edges = edges;
|
||||||
|
this.contextMapping = contextMapping;
|
||||||
|
this.createdAt = LocalDateTime.now();
|
||||||
|
this.updatedAt = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Getters / Setters ----------
|
||||||
|
|
||||||
|
public String getId() { return id; }
|
||||||
|
|
||||||
|
public void setId(String id) { this.id = id; }
|
||||||
|
|
||||||
|
public String getName() { return name; }
|
||||||
|
|
||||||
|
public void setName(String name) { this.name = name; }
|
||||||
|
|
||||||
|
public String getDescription() { return description; }
|
||||||
|
|
||||||
|
public void setDescription(String description) { this.description = description; }
|
||||||
|
|
||||||
|
public String getProjectId() { return projectId; }
|
||||||
|
|
||||||
|
public void setProjectId(String projectId) { this.projectId = projectId; }
|
||||||
|
|
||||||
|
public List<FlowNode> getNodes() { return nodes; }
|
||||||
|
|
||||||
|
public void setNodes(List<FlowNode> nodes) { this.nodes = nodes; }
|
||||||
|
|
||||||
|
public List<FlowEdge> getEdges() { return edges; }
|
||||||
|
|
||||||
|
public void setEdges(List<FlowEdge> edges) { this.edges = edges; }
|
||||||
|
|
||||||
|
public Map<String, ContextMapping> getContextMapping() { return contextMapping; }
|
||||||
|
|
||||||
|
public void setContextMapping(Map<String, ContextMapping> contextMapping) { this.contextMapping = contextMapping; }
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||||
|
|
||||||
|
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||||
|
|
||||||
|
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||||
|
|
||||||
|
// ---------- 内部嵌套类 ----------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流节点定义。
|
||||||
|
*/
|
||||||
|
public static class FlowNode {
|
||||||
|
private String nodeId;
|
||||||
|
private String type; // agent_call, condition, merge
|
||||||
|
private String agentId;
|
||||||
|
private Map<String, Object> config;
|
||||||
|
private Position position;
|
||||||
|
|
||||||
|
public FlowNode() {}
|
||||||
|
|
||||||
|
public FlowNode(String nodeId, String type, String agentId, Map<String, Object> config) {
|
||||||
|
this.nodeId = nodeId;
|
||||||
|
this.type = type;
|
||||||
|
this.agentId = agentId;
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeId() { return nodeId; }
|
||||||
|
public void setNodeId(String nodeId) { this.nodeId = nodeId; }
|
||||||
|
public String getType() { return type; }
|
||||||
|
public void setType(String type) { this.type = type; }
|
||||||
|
public String getAgentId() { return agentId; }
|
||||||
|
public void setAgentId(String agentId) { this.agentId = agentId; }
|
||||||
|
public Map<String, Object> getConfig() { return config; }
|
||||||
|
public void setConfig(Map<String, Object> config) { this.config = config; }
|
||||||
|
public Position getPosition() { return position; }
|
||||||
|
public void setPosition(Position position) { this.position = position; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点位置坐标。
|
||||||
|
*/
|
||||||
|
public static class Position {
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
public Position() {}
|
||||||
|
|
||||||
|
public Position(double x, double y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() { return x; }
|
||||||
|
public void setX(double x) { this.x = x; }
|
||||||
|
public double getY() { return y; }
|
||||||
|
public void setY(double y) { this.y = y; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流边关系定义。
|
||||||
|
*/
|
||||||
|
public static class FlowEdge {
|
||||||
|
private String source;
|
||||||
|
private String target;
|
||||||
|
|
||||||
|
public FlowEdge() {}
|
||||||
|
|
||||||
|
public FlowEdge(String source, String target) {
|
||||||
|
this.source = source;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() { return source; }
|
||||||
|
public void setSource(String source) { this.source = source; }
|
||||||
|
public String getTarget() { return target; }
|
||||||
|
public void setTarget(String target) { this.target = target; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点上下文映射配置。
|
||||||
|
*/
|
||||||
|
public static class ContextMapping {
|
||||||
|
private String inputFrom;
|
||||||
|
|
||||||
|
public ContextMapping() {}
|
||||||
|
|
||||||
|
public ContextMapping(String inputFrom) {
|
||||||
|
this.inputFrom = inputFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInputFrom() { return inputFrom; }
|
||||||
|
public void setInputFrom(String inputFrom) { this.inputFrom = inputFrom; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.example.demo.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体注册请求 DTO。
|
||||||
|
*/
|
||||||
|
@Schema(description = "智能体注册请求")
|
||||||
|
public class AgentRegisterRequest {
|
||||||
|
|
||||||
|
@Schema(description = "智能体唯一标识", example = "agent-code-gen-001")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "智能体名称", example = "代码生成智能体")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "版本号", example = "1.0.0")
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
@Schema(description = "Web 服务地址", example = "http://service-host:8080")
|
||||||
|
private String serviceUrl;
|
||||||
|
|
||||||
|
@Schema(description = "能力标签列表", example = "[\"代码生成\", \"代码补全\"]")
|
||||||
|
private List<String> capabilities;
|
||||||
|
|
||||||
|
@Schema(description = "输入 Schema(JSON Schema)")
|
||||||
|
private Map<String, Object> inputSchema;
|
||||||
|
|
||||||
|
@Schema(description = "输出 Schema(JSON Schema)")
|
||||||
|
private Map<String, Object> outputSchema;
|
||||||
|
|
||||||
|
@Schema(description = "是否支持流式输出", example = "true")
|
||||||
|
private boolean streamingSupport;
|
||||||
|
|
||||||
|
@Schema(description = "健康检查端点", example = "/health")
|
||||||
|
private String healthCheckEndpoint;
|
||||||
|
|
||||||
|
// ---------- Getters / Setters ----------
|
||||||
|
|
||||||
|
public String getId() { return id; }
|
||||||
|
public void setId(String id) { this.id = id; }
|
||||||
|
public String getName() { return name; }
|
||||||
|
public void setName(String name) { this.name = name; }
|
||||||
|
public String getVersion() { return version; }
|
||||||
|
public void setVersion(String version) { this.version = version; }
|
||||||
|
public String getServiceUrl() { return serviceUrl; }
|
||||||
|
public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; }
|
||||||
|
public List<String> getCapabilities() { return capabilities; }
|
||||||
|
public void setCapabilities(List<String> capabilities) { this.capabilities = capabilities; }
|
||||||
|
public Map<String, Object> getInputSchema() { return inputSchema; }
|
||||||
|
public void setInputSchema(Map<String, Object> inputSchema) { this.inputSchema = inputSchema; }
|
||||||
|
public Map<String, Object> getOutputSchema() { return outputSchema; }
|
||||||
|
public void setOutputSchema(Map<String, Object> outputSchema) { this.outputSchema = outputSchema; }
|
||||||
|
public boolean isStreamingSupport() { return streamingSupport; }
|
||||||
|
public void setStreamingSupport(boolean streamingSupport) { this.streamingSupport = streamingSupport; }
|
||||||
|
public String getHealthCheckEndpoint() { return healthCheckEndpoint; }
|
||||||
|
public void setHealthCheckEndpoint(String healthCheckEndpoint) { this.healthCheckEndpoint = healthCheckEndpoint; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
package com.example.demo.model.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一 API 响应封装。
|
||||||
|
* <p>
|
||||||
|
* 所有接口返回的统一数据格式,包含状态码、消息、时间戳和具体数据。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param <T> 数据类型
|
||||||
|
*/
|
||||||
|
public class ApiResponse<T> {
|
||||||
|
|
||||||
|
/** 状态码,200 表示成功 */
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
/** 提示消息 */
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/** 返回数据 */
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
/** 响应时间戳 */
|
||||||
|
private LocalDateTime timestamp;
|
||||||
|
|
||||||
|
private ApiResponse() {
|
||||||
|
this.timestamp = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建成功响应。
|
||||||
|
*
|
||||||
|
* @param data 数据对象
|
||||||
|
* @param <T> 数据类型
|
||||||
|
* @return 成功响应实例
|
||||||
|
*/
|
||||||
|
public static <T> ApiResponse<T> success(T data) {
|
||||||
|
ApiResponse<T> resp = new ApiResponse<>();
|
||||||
|
resp.code = 200;
|
||||||
|
resp.message = "success";
|
||||||
|
resp.data = data;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建成功响应(自定义消息)。
|
||||||
|
*
|
||||||
|
* @param message 自定义消息
|
||||||
|
* @param data 数据对象
|
||||||
|
* @param <T> 数据类型
|
||||||
|
* @return 成功响应实例
|
||||||
|
*/
|
||||||
|
public static <T> ApiResponse<T> success(String message, T data) {
|
||||||
|
ApiResponse<T> resp = new ApiResponse<>();
|
||||||
|
resp.code = 200;
|
||||||
|
resp.message = message;
|
||||||
|
resp.data = data;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建失败响应。
|
||||||
|
*
|
||||||
|
* @param code 错误码
|
||||||
|
* @param message 错误消息
|
||||||
|
* @param <T> 数据类型
|
||||||
|
* @return 失败响应实例
|
||||||
|
*/
|
||||||
|
public static <T> ApiResponse<T> error(int code, String message) {
|
||||||
|
ApiResponse<T> resp = new ApiResponse<>();
|
||||||
|
resp.code = code;
|
||||||
|
resp.message = message;
|
||||||
|
resp.data = null;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Getters ----------
|
||||||
|
|
||||||
|
public int getCode() { return code; }
|
||||||
|
|
||||||
|
public String getMessage() { return message; }
|
||||||
|
|
||||||
|
public T getData() { return data; }
|
||||||
|
|
||||||
|
public LocalDateTime getTimestamp() { return timestamp; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.example.demo.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流执行结果 DTO。
|
||||||
|
*/
|
||||||
|
@Schema(description = "执行结果")
|
||||||
|
public class ExecutionResult {
|
||||||
|
|
||||||
|
@Schema(description = "执行记录 ID", example = "exec-20260101-001")
|
||||||
|
private String executionId;
|
||||||
|
|
||||||
|
@Schema(description = "执行流 ID")
|
||||||
|
private String flowId;
|
||||||
|
|
||||||
|
@Schema(description = "执行状态", example = "running / completed / failed")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "当前执行节点")
|
||||||
|
private String currentNode;
|
||||||
|
|
||||||
|
@Schema(description = "开始时间")
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@Schema(description = "结束时间")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
@Schema(description = "节点输出数据")
|
||||||
|
private Map<String, Object> nodeOutputs;
|
||||||
|
|
||||||
|
@Schema(description = "错误信息")
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
public ExecutionResult() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建执行中的结果。
|
||||||
|
*
|
||||||
|
* @param executionId 执行 ID
|
||||||
|
* @param flowId 执行流 ID
|
||||||
|
* @param currentNode 当前节点
|
||||||
|
*/
|
||||||
|
public ExecutionResult(String executionId, String flowId, String currentNode) {
|
||||||
|
this.executionId = executionId;
|
||||||
|
this.flowId = flowId;
|
||||||
|
this.status = "running";
|
||||||
|
this.currentNode = currentNode;
|
||||||
|
this.startTime = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Getters / Setters ----------
|
||||||
|
|
||||||
|
public String getExecutionId() { return executionId; }
|
||||||
|
public void setExecutionId(String executionId) { this.executionId = executionId; }
|
||||||
|
public String getFlowId() { return flowId; }
|
||||||
|
public void setFlowId(String flowId) { this.flowId = flowId; }
|
||||||
|
public String getStatus() { return status; }
|
||||||
|
public void setStatus(String status) { this.status = status; }
|
||||||
|
public String getCurrentNode() { return currentNode; }
|
||||||
|
public void setCurrentNode(String currentNode) { this.currentNode = currentNode; }
|
||||||
|
public LocalDateTime getStartTime() { return startTime; }
|
||||||
|
public void setStartTime(LocalDateTime startTime) { this.startTime = startTime; }
|
||||||
|
public LocalDateTime getEndTime() { return endTime; }
|
||||||
|
public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; }
|
||||||
|
public Map<String, Object> getNodeOutputs() { return nodeOutputs; }
|
||||||
|
public void setNodeOutputs(Map<String, Object> nodeOutputs) { this.nodeOutputs = nodeOutputs; }
|
||||||
|
public String getErrorMessage() { return errorMessage; }
|
||||||
|
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.example.demo.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流触发请求 DTO。
|
||||||
|
*/
|
||||||
|
@Schema(description = "执行流触发请求")
|
||||||
|
public class FlowExecuteRequest {
|
||||||
|
|
||||||
|
@Schema(description = "执行流 ID", example = "flow-001")
|
||||||
|
private String flowId;
|
||||||
|
|
||||||
|
@Schema(description = "触发模式", example = "manual")
|
||||||
|
private String triggerMode;
|
||||||
|
|
||||||
|
@Schema(description = "触发人", example = "user-001")
|
||||||
|
private String triggeredBy;
|
||||||
|
|
||||||
|
// ---------- Getters / Setters ----------
|
||||||
|
|
||||||
|
public String getFlowId() { return flowId; }
|
||||||
|
public void setFlowId(String flowId) { this.flowId = flowId; }
|
||||||
|
public String getTriggerMode() { return triggerMode; }
|
||||||
|
public void setTriggerMode(String triggerMode) { this.triggerMode = triggerMode; }
|
||||||
|
public String getTriggeredBy() { return triggeredBy; }
|
||||||
|
public void setTriggeredBy(String triggeredBy) { this.triggeredBy = triggeredBy; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.example.demo.service;
|
||||||
|
|
||||||
|
import com.example.demo.model.BusinessItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体管理服务接口。
|
||||||
|
* <p>
|
||||||
|
* 提供智能体的注册、注销、查询、心跳更新等核心操作。
|
||||||
|
* 后续可扩展为对接数据库或远程注册中心的实现。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface BusinessService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册一个新的智能体。
|
||||||
|
*
|
||||||
|
* @param item 智能体元数据
|
||||||
|
* @return 注册成功的智能体
|
||||||
|
*/
|
||||||
|
BusinessItem register(BusinessItem item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销指定 ID 的智能体。
|
||||||
|
*
|
||||||
|
* @param id 智能体唯一标识
|
||||||
|
* @return 如果找到并注销返回 true,否则 false
|
||||||
|
*/
|
||||||
|
boolean unregister(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 ID 查询智能体。
|
||||||
|
*
|
||||||
|
* @param id 智能体唯一标识
|
||||||
|
* @return 包含智能体的 Optional
|
||||||
|
*/
|
||||||
|
Optional<BusinessItem> findById(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有已注册的智能体。
|
||||||
|
*
|
||||||
|
* @return 智能体列表
|
||||||
|
*/
|
||||||
|
List<BusinessItem> findAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据能力标签查询智能体。
|
||||||
|
*
|
||||||
|
* @param capability 能力标签
|
||||||
|
* @return 匹配的智能体列表
|
||||||
|
*/
|
||||||
|
List<BusinessItem> findByCapability(String capability);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新指定智能体的心跳时间。
|
||||||
|
*
|
||||||
|
* @param id 智能体唯一标识
|
||||||
|
* @return 更新成功返回 true,否则 false
|
||||||
|
*/
|
||||||
|
boolean updateHeartbeat(String id);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.example.demo.service;
|
||||||
|
|
||||||
|
import com.example.demo.model.BusinessItem;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体管理服务实现(基于内存存储)。
|
||||||
|
* <p>
|
||||||
|
* 使用 {@link ConcurrentHashMap} 在内存中维护智能体注册信息,
|
||||||
|
* 适用于功能验证与开发阶段。后续可扩展为基于数据库或注册中心的实现。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class BusinessServiceImpl implements BusinessService {
|
||||||
|
|
||||||
|
/** 内存存储:key = 智能体 ID, value = 智能体元数据 */
|
||||||
|
private final ConcurrentHashMap<String, BusinessItem> agentStore = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BusinessItem register(BusinessItem item) {
|
||||||
|
item.setStatus("active");
|
||||||
|
item.setRegisteredAt(LocalDateTime.now());
|
||||||
|
item.setLastHeartbeat(LocalDateTime.now());
|
||||||
|
agentStore.put(item.getId(), item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unregister(String id) {
|
||||||
|
return agentStore.remove(id) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<BusinessItem> findById(String id) {
|
||||||
|
return Optional.ofNullable(agentStore.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BusinessItem> findAll() {
|
||||||
|
return new ArrayList<>(agentStore.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BusinessItem> findByCapability(String capability) {
|
||||||
|
return agentStore.values().stream()
|
||||||
|
.filter(agent -> agent.getCapabilities() != null
|
||||||
|
&& agent.getCapabilities().stream()
|
||||||
|
.anyMatch(cap -> cap.equalsIgnoreCase(capability)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateHeartbeat(String id) {
|
||||||
|
BusinessItem agent = agentStore.get(id);
|
||||||
|
if (agent == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
agent.setLastHeartbeat(LocalDateTime.now());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.example.demo.service;
|
||||||
|
|
||||||
|
import com.example.demo.model.ExecutionFlow;
|
||||||
|
import com.example.demo.model.dto.ExecutionResult;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流管理服务接口。
|
||||||
|
* <p>
|
||||||
|
* 提供执行流的创建、查询、删除以及执行触发等核心操作。
|
||||||
|
* 后续可扩展为支持持久化存储与分布式调度引擎。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface FlowService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的执行流配置。
|
||||||
|
*
|
||||||
|
* @param flow 执行流配置
|
||||||
|
* @return 创建成功的执行流
|
||||||
|
*/
|
||||||
|
ExecutionFlow createFlow(ExecutionFlow flow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 ID 查询执行流。
|
||||||
|
*
|
||||||
|
* @param id 执行流 ID
|
||||||
|
* @return 包含执行流的 Optional
|
||||||
|
*/
|
||||||
|
Optional<ExecutionFlow> getFlow(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有执行流。
|
||||||
|
*
|
||||||
|
* @return 执行流列表
|
||||||
|
*/
|
||||||
|
List<ExecutionFlow> listFlows();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定 ID 的执行流。
|
||||||
|
*
|
||||||
|
* @param id 执行流 ID
|
||||||
|
* @return 如果找到并删除返回 true,否则 false
|
||||||
|
*/
|
||||||
|
boolean deleteFlow(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发执行流运行。
|
||||||
|
* <p>
|
||||||
|
* 当前为模拟实现,返回执行中的结果;
|
||||||
|
* 后续将对接拓扑排序 + 线程池调度引擎进行真实执行。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param flowId 执行流 ID
|
||||||
|
* @param triggeredBy 触发人
|
||||||
|
* @param triggerMode 触发模式
|
||||||
|
* @return 执行结果(包含执行 ID 与状态)
|
||||||
|
*/
|
||||||
|
ExecutionResult executeFlow(String flowId, String triggeredBy, String triggerMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询执行结果。
|
||||||
|
*
|
||||||
|
* @param executionId 执行记录 ID
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
Optional<ExecutionResult> getExecutionResult(String executionId);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.example.demo.service;
|
||||||
|
|
||||||
|
import com.example.demo.model.ExecutionFlow;
|
||||||
|
import com.example.demo.model.dto.ExecutionResult;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流管理服务实现(基于内存存储)。
|
||||||
|
* <p>
|
||||||
|
* 使用 {@link ConcurrentHashMap} 在内存中维护执行流配置与执行记录。
|
||||||
|
* 当前 executeFlow 为模拟实现,仅演示执行流触发流程。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FlowServiceImpl implements FlowService {
|
||||||
|
|
||||||
|
/** 执行流存储:key = flow ID */
|
||||||
|
private final ConcurrentHashMap<String, ExecutionFlow> flowStore = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/** 执行结果存储:key = execution ID */
|
||||||
|
private final ConcurrentHashMap<String, ExecutionResult> executionStore = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/** 自增执行计数器 */
|
||||||
|
private final AtomicInteger execCounter = new AtomicInteger(0);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecutionFlow createFlow(ExecutionFlow flow) {
|
||||||
|
flow.setCreatedAt(LocalDateTime.now());
|
||||||
|
flow.setUpdatedAt(LocalDateTime.now());
|
||||||
|
flowStore.put(flow.getId(), flow);
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ExecutionFlow> getFlow(String id) {
|
||||||
|
return Optional.ofNullable(flowStore.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ExecutionFlow> listFlows() {
|
||||||
|
return new ArrayList<>(flowStore.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFlow(String id) {
|
||||||
|
return flowStore.remove(id) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecutionResult executeFlow(String flowId, String triggeredBy, String triggerMode) {
|
||||||
|
ExecutionFlow flow = flowStore.get(flowId);
|
||||||
|
if (flow == null) {
|
||||||
|
ExecutionResult err = new ExecutionResult();
|
||||||
|
err.setExecutionId("err-" + execCounter.incrementAndGet());
|
||||||
|
err.setFlowId(flowId);
|
||||||
|
err.setStatus("failed");
|
||||||
|
err.setErrorMessage("执行流未找到: " + flowId);
|
||||||
|
err.setStartTime(LocalDateTime.now());
|
||||||
|
err.setEndTime(LocalDateTime.now());
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟执行过程
|
||||||
|
String execId = "exec-" + System.currentTimeMillis();
|
||||||
|
ExecutionResult result = new ExecutionResult(execId, flowId,
|
||||||
|
flow.getNodes() != null && !flow.getNodes().isEmpty()
|
||||||
|
? flow.getNodes().get(0).getNodeId()
|
||||||
|
: null);
|
||||||
|
|
||||||
|
// 模拟:短暂延迟后标记为完成
|
||||||
|
// 真实场景应异步执行,此处同步模拟
|
||||||
|
Map<String, Object> mockOutputs = new LinkedHashMap<>();
|
||||||
|
if (flow.getNodes() != null) {
|
||||||
|
for (ExecutionFlow.FlowNode node : flow.getNodes()) {
|
||||||
|
Map<String, Object> nodeResult = new LinkedHashMap<>();
|
||||||
|
nodeResult.put("status", "simulated_ok");
|
||||||
|
nodeResult.put("message", "节点 " + node.getNodeId() + " 模拟执行完成");
|
||||||
|
mockOutputs.put(node.getNodeId(), nodeResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.setNodeOutputs(mockOutputs);
|
||||||
|
result.setStatus("completed");
|
||||||
|
result.setEndTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
executionStore.put(execId, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ExecutionResult> getExecutionResult(String executionId) {
|
||||||
|
return Optional.ofNullable(executionStore.get(executionId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: multi-agent-platform
|
||||||
|
|
||||||
|
springdoc:
|
||||||
|
swagger-ui:
|
||||||
|
path: /swagger-ui.html
|
||||||
|
api-docs:
|
||||||
|
path: /v3/api-docs
|
||||||
|
|
||||||
|
knife4j:
|
||||||
|
enable: true
|
||||||
|
setting:
|
||||||
|
language: zh-CN
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.example.demo;
|
||||||
|
|
||||||
|
import com.example.demo.model.BusinessItem;
|
||||||
|
import com.example.demo.service.BusinessService;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体管理服务单元测试。
|
||||||
|
* <p>
|
||||||
|
* 验证 BusinessService 的注册、注销、查询和心跳更新等核心功能。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
class BusinessServiceTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessService businessService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每个测试前清理数据(由于是内存存储,重建上下文即可)。
|
||||||
|
*/
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
// 当前内存实现在 Spring 上下文重启后自动清空
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRegisterAndFindById() {
|
||||||
|
BusinessItem item = createTestAgent("agent-test-001", "测试智能体", "代码生成");
|
||||||
|
BusinessItem registered = businessService.register(item);
|
||||||
|
assertNotNull(registered);
|
||||||
|
assertEquals("active", registered.getStatus());
|
||||||
|
|
||||||
|
Optional<BusinessItem> found = businessService.findById("agent-test-001");
|
||||||
|
assertTrue(found.isPresent());
|
||||||
|
assertEquals("测试智能体", found.get().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUnregister() {
|
||||||
|
BusinessItem item = createTestAgent("agent-test-002", "临时智能体", "文档生成");
|
||||||
|
businessService.register(item);
|
||||||
|
|
||||||
|
boolean removed = businessService.unregister("agent-test-002");
|
||||||
|
assertTrue(removed);
|
||||||
|
|
||||||
|
Optional<BusinessItem> found = businessService.findById("agent-test-002");
|
||||||
|
assertFalse(found.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFindAll() {
|
||||||
|
businessService.register(createTestAgent("agent-test-003", "智能体A", "代码生成"));
|
||||||
|
businessService.register(createTestAgent("agent-test-004", "智能体B", "测试验证"));
|
||||||
|
|
||||||
|
List<BusinessItem> all = businessService.findAll();
|
||||||
|
assertTrue(all.size() >= 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFindByCapability() {
|
||||||
|
businessService.register(createTestAgent("agent-test-005", "代码生成器", "代码生成"));
|
||||||
|
businessService.register(createTestAgent("agent-test-006", "测试验证器", "测试验证"));
|
||||||
|
|
||||||
|
List<BusinessItem> result = businessService.findByCapability("代码生成");
|
||||||
|
assertTrue(result.stream().anyMatch(a -> a.getName().equals("代码生成器")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateHeartbeat() {
|
||||||
|
businessService.register(createTestAgent("agent-test-007", "心跳测试", "通用"));
|
||||||
|
|
||||||
|
boolean updated = businessService.updateHeartbeat("agent-test-007");
|
||||||
|
assertTrue(updated);
|
||||||
|
|
||||||
|
boolean notFound = businessService.updateHeartbeat("non-existent");
|
||||||
|
assertFalse(notFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建测试用的智能体对象。
|
||||||
|
*/
|
||||||
|
private BusinessItem createTestAgent(String id, String name, String capability) {
|
||||||
|
return new BusinessItem(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
"1.0.0",
|
||||||
|
"http://localhost:8081",
|
||||||
|
List.of(capability),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
"/health",
|
||||||
|
"active"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.example.demo;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用启动测试。
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
class DemoApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
// 验证 Spring 上下文能正常加载
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue