extensions = ObjectUtils.cast(result.get("extensions"));
- assertEquals(list1, extensions.get("k1"));
- assertEquals(list2, extensions.get("k2"));
- }
-}
\ No newline at end of file
diff --git a/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json b/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json
new file mode 100644
index 00000000..278ca967
--- /dev/null
+++ b/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json
@@ -0,0 +1,240 @@
+{
+ "version" : "1.0.0",
+ "definitionGroups" : [ {
+ "name" : "defGroup_weather_Rain",
+ "summary" : "雨天",
+ "description" : "下雨的定义组",
+ "extensions" : { },
+ "definitions" : [ {
+ "schema" : {
+ "name" : "rain_today",
+ "description" : "该方法获取今天的下雨信息",
+ "parameters" : {
+ "type" : "object",
+ "properties" : {
+ "location" : {
+ "defaultValue" : "",
+ "description" : "查询地点",
+ "name" : "location",
+ "type" : "string",
+ "examples" : "",
+ "required" : true
+ },
+ "date" : {
+ "defaultValue" : "",
+ "description" : "查询日期",
+ "name" : "date",
+ "type" : "string",
+ "examples" : "",
+ "required" : true
+ }
+ },
+ "required" : [ "location", "date" ]
+ },
+ "order" : [ "location", "date" ],
+ "return" : {
+ "type" : "string",
+ "convertor" : ""
+ }
+ }
+ }, {
+ "schema" : {
+ "name" : "rain_tomorrow",
+ "description" : "该方法获取明天的下雨信息",
+ "parameters" : {
+ "type" : "object",
+ "properties" : {
+ "location" : {
+ "name" : "location",
+ "type" : "string",
+ "required" : false
+ },
+ "date" : {
+ "name" : "date",
+ "type" : "string",
+ "required" : false
+ }
+ },
+ "required" : [ ]
+ },
+ "order" : [ "location", "date" ],
+ "return" : {
+ "type" : "string",
+ "convertor" : ""
+ }
+ }
+ } ]
+ } ],
+ "toolGroups" : [ {
+ "name" : "implGroup_weather_rain_city_a",
+ "summary" : "",
+ "description" : "",
+ "extensions" : {
+ "owner" : [ "测试" ],
+ "language" : [ "english" ]
+ },
+ "definitionGroupName" : "defGroup_weather_Rain",
+ "tools" : [ {
+ "namespace" : "Common",
+ "schema" : {
+ "name" : "city_a_rain_today",
+ "description" : "城市A提供的今日下雨信息",
+ "parameters" : {
+ "type" : "object",
+ "properties" : {
+ "location" : {
+ "name" : "location",
+ "type" : "string",
+ "required" : false
+ },
+ "date" : {
+ "name" : "date",
+ "type" : "string",
+ "required" : false
+ }
+ },
+ "required" : [ ]
+ },
+ "order" : [ "location", "date" ],
+ "return" : {
+ "name" : "",
+ "description" : "获取今日下雨信息的结果",
+ "type" : "string",
+ "convertor" : "",
+ "examples" : ""
+ }
+ },
+ "runnables" : {
+ "FIT" : {
+ "genericableId" : "genericable_weather_rain_today",
+ "fitableId" : "weather_rain_city_a"
+ }
+ },
+ "extensions" : {
+ "tags" : [ "FIT", "TEST" ]
+ },
+ "definitionName" : "rain_today"
+ }, {
+ "namespace" : "Common",
+ "schema" : {
+ "name" : "city_a_rain_tomorrow",
+ "description" : "城市A提供的明日下雨信息",
+ "parameters" : {
+ "type" : "object",
+ "properties" : {
+ "location" : {
+ "name" : "location",
+ "type" : "string",
+ "required" : false
+ },
+ "date" : {
+ "name" : "date",
+ "type" : "string",
+ "required" : false
+ }
+ },
+ "required" : [ ]
+ },
+ "order" : [ "location", "date" ],
+ "return" : {
+ "name" : "",
+ "description" : "获取明日下雨信息的结果",
+ "type" : "string",
+ "convertor" : "",
+ "examples" : ""
+ }
+ },
+ "runnables" : {
+ "FIT" : {
+ "genericableId" : "genericable_weather_rain_tomorrow",
+ "fitableId" : "weather_rain_city_a"
+ }
+ },
+ "extensions" : {
+ "tags" : [ "FIT", "TEST" ]
+ },
+ "definitionName" : "rain_tomorrow"
+ } ]
+ }, {
+ "name" : "implGroup_weather_rain_city_b",
+ "summary" : "",
+ "description" : "",
+ "extensions" : { },
+ "definitionGroupName" : "defGroup_weather_Rain",
+ "tools" : [ {
+ "namespace" : "Common",
+ "schema" : {
+ "name" : "city_b_rain_today",
+ "description" : "城市B提供的今日下雨信息",
+ "parameters" : {
+ "type" : "object",
+ "properties" : {
+ "location" : {
+ "name" : "location",
+ "type" : "string",
+ "required" : false
+ },
+ "date" : {
+ "name" : "date",
+ "type" : "string",
+ "required" : false
+ }
+ },
+ "required" : [ ]
+ },
+ "order" : [ "location", "date" ],
+ "return" : {
+ "type" : "string",
+ "convertor" : ""
+ }
+ },
+ "runnables" : {
+ "FIT" : {
+ "genericableId" : "genericable_weather_rain_today",
+ "fitableId" : "weather_rain_city_b"
+ }
+ },
+ "extensions" : {
+ "tags" : [ "FIT", "TEST" ]
+ },
+ "definitionName" : "rain_today"
+ }, {
+ "namespace" : "Common",
+ "schema" : {
+ "name" : "city_b_rain_tomorrow",
+ "description" : "城市B提供的明日下雨信息",
+ "parameters" : {
+ "type" : "object",
+ "properties" : {
+ "location" : {
+ "name" : "location",
+ "type" : "string",
+ "required" : false
+ },
+ "date" : {
+ "name" : "date",
+ "type" : "string",
+ "required" : false
+ }
+ },
+ "required" : [ ]
+ },
+ "order" : [ "location", "date" ],
+ "return" : {
+ "type" : "string",
+ "convertor" : ""
+ }
+ },
+ "runnables" : {
+ "FIT" : {
+ "genericableId" : "genericable_weather_rain_tomorrow",
+ "fitableId" : "weather_rain_city_b"
+ }
+ },
+ "extensions" : {
+ "tags" : [ "FIT", "TEST" ]
+ },
+ "definitionName" : "rain_tomorrow"
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/framework/fel/java/plugins/tool-discoverer/src/main/java/modelengine/fel/tool/support/DefaultToolDiscoverer.java b/framework/fel/java/plugins/tool-discoverer/src/main/java/modelengine/fel/tool/support/DefaultToolDiscoverer.java
index ec52d4cc..74d586ab 100644
--- a/framework/fel/java/plugins/tool-discoverer/src/main/java/modelengine/fel/tool/support/DefaultToolDiscoverer.java
+++ b/framework/fel/java/plugins/tool-discoverer/src/main/java/modelengine/fel/tool/support/DefaultToolDiscoverer.java
@@ -9,8 +9,11 @@
import static modelengine.fitframework.inspection.Validation.isTrue;
import static modelengine.fitframework.inspection.Validation.notNull;
-import modelengine.fel.tool.ToolEntity;
+import modelengine.fel.tool.ToolInfoEntity;
+import modelengine.fel.tool.info.entity.ToolEntity;
import modelengine.fel.tool.ToolSchema;
+import modelengine.fel.tool.info.entity.ToolGroupEntity;
+import modelengine.fel.tool.info.entity.ToolJsonEntity;
import modelengine.fel.tool.service.ToolRepository;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Value;
@@ -20,15 +23,13 @@
import modelengine.fitframework.resource.Resource;
import modelengine.fitframework.serialization.ObjectSerializer;
import modelengine.fitframework.util.ArrayUtils;
-import modelengine.fitframework.util.TypeUtils;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
/**
@@ -36,6 +37,7 @@
* 当插件加载和卸载时,会根据插件暴露的工具方法,进行工具的加载和卸载。
*
* @author 易文渊
+ * @author 杭潇
* @since 2024-08-15
*/
@Component
@@ -62,14 +64,14 @@ public DefaultToolDiscoverer(ToolRepository toolRepository, ObjectSerializer ser
@Override
public void onPluginStarted(Plugin plugin) {
- this.scanTools(plugin).forEach(this.toolRepository::addTool);
+ this.scanTools(plugin).forEach(toolEntity -> this.toolRepository.addTool(new ToolInfoEntity(toolEntity)));
}
@Override
public void onPluginStopping(Plugin plugin) {
List toolEntities = this.scanTools(plugin);
isTrue(toolEntities.size() < this.maxToolNum, "The tool num in plugin must less than {}", this.maxToolNum);
- toolEntities.forEach(tool -> this.toolRepository.deleteTool(tool.namespace(), tool.name()));
+ toolEntities.forEach(tool -> this.toolRepository.deleteTool(tool.getNamespace(), tool.getSchema().getName()));
}
private List scanTools(Plugin plugin) {
@@ -88,14 +90,16 @@ private List scanTools(Plugin plugin) {
private List parseTools(Resource resource) {
try (InputStream in = resource.read()) {
- Map> toolEntityMap =
- this.serializer.deserialize(in, TypeUtils.parameterized(Map.class, new Type[] {
- String.class, TypeUtils.parameterized(List.class, new Type[] {ToolEntity.class})
- }));
- if (toolEntityMap == null) {
+ ToolJsonEntity toolJsonEntity = this.serializer.deserialize(in, ToolJsonEntity.class);
+ if (toolJsonEntity == null) {
return Collections.emptyList();
}
- return toolEntityMap.get(TOOLS);
+ return toolJsonEntity.getToolGroups().stream()
+ .filter(Objects::nonNull)
+ .map(ToolGroupEntity::getTools)
+ .filter(Objects::nonNull)
+ .flatMap(List::stream)
+ .collect(Collectors.toList());
} catch (IOException exception) {
return Collections.emptyList();
}
diff --git a/framework/fel/java/plugins/tool-discoverer/src/test/resources/tools.json b/framework/fel/java/plugins/tool-discoverer/src/test/resources/tools.json
index e867da2e..b6e2a0aa 100644
--- a/framework/fel/java/plugins/tool-discoverer/src/test/resources/tools.json
+++ b/framework/fel/java/plugins/tool-discoverer/src/test/resources/tools.json
@@ -1,45 +1,108 @@
{
- "tools": [
+ "version": "1.0.0",
+ "definitionGroups": [
{
- "schema": {
- "name": "get_delivery_date",
- "description": "Get the delivery date for a customer's order. Call this whenever you need to know the delivery date, for example when a customer asks 'Where is my package",
- "parameters": {
- "type": "object",
- "properties": {
- "orderId": {
- "type": "string",
- "description": "The customer's order ID."
+ "name": "default_delivery_date",
+ "summary": "",
+ "description": "",
+ "extensions": {},
+ "definitions": [
+ {
+ "schema": {
+ "name": "get_delivery_date",
+ "description": "Get the delivery date for a customer's order. Call this whenever you need to know the delivery date, for example when a customer asks 'Where is my package",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "orderId": {
+ "defaultValue": "",
+ "description": "The customer's order ID.",
+ "name": "arg0",
+ "type": "string",
+ "examples": "",
+ "required": true
+ },
+ "config": {
+ "defaultValue": "",
+ "description": "The customer's config.",
+ "name": "arg1",
+ "type": "string",
+ "examples": "",
+ "required": true
+ }
+ },
+ "required": [
+ "orderId"
+ ]
+ },
+ "order": [
+ "orderId",
+ "config"
+ ],
+ "return": {
+ "type": "integer",
+ "convertor": ""
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "toolGroups": [
+ {
+ "name": "get_delivery_date",
+ "summary": "",
+ "description": "",
+ "extensions": {},
+ "definitionGroupName": "default_delivery_date",
+ "tools": [
+ {
+ "schema": {
+ "name": "get_delivery_date",
+ "description": "Get the delivery date for a customer's order. Call this whenever you need to know the delivery date, for example when a customer asks 'Where is my package",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "orderId": {
+ "name": "orderId",
+ "type": "string",
+ "required": false
+ },
+ "config": {
+ "name": "config",
+ "type": "string",
+ "required": false
+ }
+ },
+ "required": []
},
- "config": {
+ "order": [
+ "orderId",
+ "config"
+ ],
+ "return": {
+ "name": "",
+ "description": "",
"type": "string",
- "description": "The customer's config."
+ "convertor": "",
+ "examples": ""
}
},
- "required": [
- "orderId"
- ]
- },
- "order": [
- "orderId",
- "config"
- ],
- "return": {
- "type": "string",
- "converter": ""
- }
- },
- "namespace": "test",
- "runnables": {
- "FIT": {
- "fitableId": "default",
- "genericableId": "test"
+ "runnables": {
+ "FIT": {
+ "genericableId": "default",
+ "fitableId": "test"
+ }
+ },
+ "extensions": {
+ "tags": [
+ "v2",
+ "v2"
+ ]
+ },
+ "definitionName": "default_delivery_date"
}
- },
- "extensions": {
- "k1": "v2",
- "k2": "v2"
- }
+ ]
}
]
}
\ No newline at end of file
diff --git a/framework/fel/java/plugins/tool-executor/src/main/java/modelengine/fel/tool/support/DefaultToolExecutor.java b/framework/fel/java/plugins/tool-executor/src/main/java/modelengine/fel/tool/support/DefaultToolExecutor.java
index c51dde62..9abd914d 100644
--- a/framework/fel/java/plugins/tool-executor/src/main/java/modelengine/fel/tool/support/DefaultToolExecutor.java
+++ b/framework/fel/java/plugins/tool-executor/src/main/java/modelengine/fel/tool/support/DefaultToolExecutor.java
@@ -8,8 +8,8 @@
import static modelengine.fitframework.inspection.Validation.notNull;
+import modelengine.fel.tool.ToolInfoEntity;
import modelengine.fel.tool.Tool;
-import modelengine.fel.tool.ToolEntity;
import modelengine.fel.tool.ToolFactory;
import modelengine.fel.tool.ToolFactoryRepository;
import modelengine.fel.tool.service.ToolExecuteService;
@@ -80,7 +80,7 @@ public String execute(String uniqueName, Map jsonObject) {
}
private Tool getTool(String group, String toolName) {
- ToolEntity tool = notNull(toolRepository.getTool(group, toolName),
+ ToolInfoEntity tool = notNull(toolRepository.getTool(group, toolName),
() -> new IllegalStateException(StringUtils.format("The tool cannot be found. [group={0}, tool={1}]",
group,
toolName)));
diff --git a/framework/fel/java/plugins/tool-executor/src/test/java/modelengine/fel/tool/support/DefaultToolExecutorTest.java b/framework/fel/java/plugins/tool-executor/src/test/java/modelengine/fel/tool/support/DefaultToolExecutorTest.java
index a2ab2edc..3492cd13 100644
--- a/framework/fel/java/plugins/tool-executor/src/test/java/modelengine/fel/tool/support/DefaultToolExecutorTest.java
+++ b/framework/fel/java/plugins/tool-executor/src/test/java/modelengine/fel/tool/support/DefaultToolExecutorTest.java
@@ -15,8 +15,9 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import modelengine.fel.tool.ToolInfoEntity;
import modelengine.fel.tool.Tool;
-import modelengine.fel.tool.ToolEntity;
+import modelengine.fel.tool.info.entity.ToolEntity;
import modelengine.fel.tool.ToolFactory;
import modelengine.fel.tool.ToolFactoryRepository;
import modelengine.fel.tool.ToolSchema;
@@ -44,6 +45,7 @@
*
* @author 王攀博
* @author 易文渊
+ * @author 杭潇
* @since 2024-04-27
*/
@DisplayName("测试 DefaultToolExecutor")
@@ -68,7 +70,7 @@ void tearDown() {
@Test
@DisplayName("调用工具成功返回结果")
void shouldOkWhenExecuteTool() throws IOException {
- ToolEntity toolEntity = getTestEntity();
+ ToolInfoEntity toolEntity = getTestEntity();
when(this.toolRepository.getTool(any(), eq(toolEntity.name()))).thenReturn(toolEntity);
when(this.toolFactoryRepository.match(any())).thenReturn(Optional.of(this.toolFactory));
Tool tool = mock(Tool.class, RETURNS_DEEP_STUBS);
@@ -94,7 +96,7 @@ void shouldFailWhenToolNotFound() {
@Test
@DisplayName("工具工厂不存在,调用失败")
void shouldFailWhenToolFactoryNotFound() throws IOException {
- ToolEntity toolEntity = getTestEntity();
+ ToolInfoEntity toolEntity = getTestEntity();
when(this.toolRepository.getTool(any(), any())).thenReturn(toolEntity);
when(this.toolFactoryRepository.match(any())).thenReturn(Optional.empty());
@@ -105,12 +107,12 @@ void shouldFailWhenToolFactoryNotFound() throws IOException {
"test")).isInstanceOf(IllegalStateException.class);
}
- private ToolEntity getTestEntity() throws IOException {
+ private ToolInfoEntity getTestEntity() throws IOException {
List toolEntities =
- this.serializer.