diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
new file mode 100644
index 00000000..e3f440ad
--- /dev/null
+++ b/.idea/dictionaries/project.xml
@@ -0,0 +1,7 @@
+
+
+
+ zuper
+
+
+
\ No newline at end of file
diff --git a/Partner-Api/pom.xml b/Partner-Api/pom.xml
index 51066335..15b6ee64 100644
--- a/Partner-Api/pom.xml
+++ b/Partner-Api/pom.xml
@@ -12,11 +12,58 @@
Partner-Api
+
+ net.bytebuddy
+ byte-buddy
+ 1.17.6
+
org.reflections
reflections
0.10.2
+
+ org.projectlombok
+ lombok
+ 1.18.36
+ provided
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.13.2
+
+
+ org.slf4j
+ slf4j-api
+ 2.0.17
+
+
+ ch.qos.logback
+ logback-classic
+ 1.5.17
+
+
+ commons-io
+ commons-io
+ 2.18.0
+
+
+ cn.hutool
+ hutool-all
+ 5.8.36
+
+
+ com.alibaba
+ fastjson
+ 2.0.56
+
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/entity/AgentBaseFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentBaseFactory.java
similarity index 86%
rename from Partner-Api/src/main/java/work/slhaf/partner/api/factory/entity/AgentBaseFactory.java
rename to Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentBaseFactory.java
index db2a74c8..5e9735d8 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/entity/AgentBaseFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentBaseFactory.java
@@ -1,6 +1,7 @@
-package work.slhaf.partner.api.factory.entity;
+package work.slhaf.partner.api.factory;
import work.slhaf.partner.api.factory.capability.exception.CapabilityFactoryExecuteFailedException;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
import java.lang.reflect.InvocationTargetException;
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentRegisterFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentRegisterFactory.java
index 96a89a54..20f50211 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentRegisterFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/AgentRegisterFactory.java
@@ -1,32 +1,35 @@
package work.slhaf.partner.api.factory;
import cn.hutool.core.bean.BeanUtil;
+import org.reflections.util.ClasspathHelper;
import work.slhaf.partner.api.entity.AgentContext;
import work.slhaf.partner.api.factory.capability.CapabilityCheckFactory;
import work.slhaf.partner.api.factory.capability.CapabilityInjectFactory;
import work.slhaf.partner.api.factory.capability.CapabilityRegisterFactory;
import work.slhaf.partner.api.factory.config.ConfigLoaderFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.exception.ExternalModuleLoadFailedException;
import work.slhaf.partner.api.factory.exception.ExternalModulePathNotExistException;
import work.slhaf.partner.api.factory.module.ModuleCheckFactory;
-import work.slhaf.partner.api.factory.module.ModuleProxyFactory;
import work.slhaf.partner.api.factory.module.ModulePreHookExecuteFactory;
+import work.slhaf.partner.api.factory.module.ModuleProxyFactory;
import work.slhaf.partner.api.factory.module.ModuleRegisterFactory;
import java.io.File;
+import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class AgentRegisterFactory {
- private static List paths = new ArrayList<>();
+ private static final List urls = new ArrayList<>();
private AgentRegisterFactory() {
}
- public static AgentContext launch(String path) {
- paths.add(path);
- AgentRegisterContext registerContext = new AgentRegisterContext(paths);
+ public static AgentContext launch(String packageName) {
+ urls.addAll(packageNameToURL(packageName));
+ AgentRegisterContext registerContext = new AgentRegisterContext(urls);
//流程
//0. 加载配置
new ConfigLoaderFactory().execute(registerContext);
@@ -44,17 +47,41 @@ public class AgentRegisterFactory {
new ModulePreHookExecuteFactory().execute(registerContext);
AgentContext agentContext = new AgentContext();
- BeanUtil.copyProperties(registerContext,agentContext);
+ BeanUtil.copyProperties(registerContext, agentContext);
return agentContext;
}
- //TODO 也需要可指定路径,当前只是新增了可扫描包
- public static void addScanPath(String path) {
- File file = new File(path);
- if (!file.exists() || !file.isDirectory()) {
- throw new ExternalModulePathNotExistException("不存在的外部模块目录: "+path);
- }
- paths.add(path);
+ /**
+ * 添加可扫描包
+ * @param packageName 指定的包名
+ */
+ public static void addScanPackage(String packageName) {
+ urls.addAll(packageNameToURL(packageName));
}
+ /**
+ * 添加外部模块目录
+ * @param externalPackagePath 指定的外部模块目录路径
+ */
+ public static void addScanDir(String externalPackagePath) {
+ File file = new File(externalPackagePath);
+ if (!file.exists() || !file.isDirectory()) {
+ throw new ExternalModulePathNotExistException("不存在的外部模块目录: " + externalPackagePath);
+ }
+ try {
+ for (File f : file.listFiles()) {
+ if (f.getName().endsWith(".jar")) {
+ urls.add(f.toURI().toURL());
+ }
+ }
+ } catch (Exception e) {
+ throw new ExternalModuleLoadFailedException("外部模块URL获取失败: " + externalPackagePath, e);
+ }
+ }
+
+ private static List packageNameToURL(String packageName) {
+ return ClasspathHelper.forPackage(packageName).stream().toList();
+ }
+
+
}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityCheckFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityCheckFactory.java
index 4f1f0815..a3103483 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityCheckFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityCheckFactory.java
@@ -2,13 +2,14 @@ package work.slhaf.partner.api.factory.capability;
import org.reflections.Reflections;
import work.slhaf.partner.api.common.util.AgentUtil;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
import work.slhaf.partner.api.factory.capability.annotation.*;
import work.slhaf.partner.api.factory.capability.exception.DuplicateCapabilityException;
import work.slhaf.partner.api.factory.capability.exception.UnMatchedCapabilityException;
import work.slhaf.partner.api.factory.capability.exception.UnMatchedCapabilityMethodException;
import work.slhaf.partner.api.factory.capability.exception.UnMatchedCoordinatedMethodException;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.CapabilityFactoryContext;
import java.lang.reflect.Method;
import java.util.*;
@@ -28,9 +29,10 @@ public class CapabilityCheckFactory extends AgentBaseFactory {
@Override
protected void setVariables(AgentRegisterContext context) {
+ CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
- cores = context.getCores();
- capabilities = context.getCapabilities();
+ cores = factoryContext.getCores();
+ capabilities = factoryContext.getCapabilities();
}
@Override
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityInjectFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityInjectFactory.java
index 02b0621f..f4457697 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityInjectFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityInjectFactory.java
@@ -1,12 +1,13 @@
package work.slhaf.partner.api.factory.capability;
import org.reflections.Reflections;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
import work.slhaf.partner.api.factory.capability.annotation.Capability;
import work.slhaf.partner.api.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.factory.capability.annotation.ToCoordinated;
import work.slhaf.partner.api.factory.capability.exception.ProxySetFailedExceptionCapability;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.CapabilityFactoryContext;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
@@ -28,10 +29,11 @@ public class CapabilityInjectFactory extends AgentBaseFactory {
@Override
protected void setVariables(AgentRegisterContext context) {
+ CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
- coordinatedMethodsRouterTable = context.getCoordinatedMethodsRouterTable();
- methodsRouterTable = context.getMethodsRouterTable();
- capabilityHolderInstances = context.getCapabilityHolderInstances();
+ coordinatedMethodsRouterTable = factoryContext.getCoordinatedMethodsRouterTable();
+ methodsRouterTable = factoryContext.getMethodsRouterTable();
+ capabilityHolderInstances = factoryContext.getCapabilityHolderInstances();
}
@Override
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityRegisterFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityRegisterFactory.java
index ef3b9d66..d8e0dd96 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityRegisterFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/capability/CapabilityRegisterFactory.java
@@ -1,12 +1,13 @@
package work.slhaf.partner.api.factory.capability;
import org.reflections.Reflections;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
import work.slhaf.partner.api.factory.capability.annotation.*;
import work.slhaf.partner.api.factory.capability.exception.CapabilityFactoryExecuteFailedException;
import work.slhaf.partner.api.factory.capability.exception.CoreInstancesCreateFailedExceptionCapability;
import work.slhaf.partner.api.factory.capability.exception.DuplicateMethodException;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.CapabilityFactoryContext;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -35,13 +36,14 @@ public final class CapabilityRegisterFactory extends AgentBaseFactory {
@Override
protected void setVariables(AgentRegisterContext context) {
+ CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
- methodsRouterTable = context.getMethodsRouterTable();
- coordinatedMethodsRouterTable = context.getCoordinatedMethodsRouterTable();
- capabilityCoreInstances = context.getCapabilityCoreInstances();
- cores = context.getCores();
- capabilities = context.getCapabilities();
- capabilityHolderInstances = context.getCapabilityHolderInstances();
+ methodsRouterTable = factoryContext.getMethodsRouterTable();
+ coordinatedMethodsRouterTable = factoryContext.getCoordinatedMethodsRouterTable();
+ capabilityCoreInstances = factoryContext.getCapabilityCoreInstances();
+ cores = factoryContext.getCores();
+ capabilities = factoryContext.getCapabilities();
+ capabilityHolderInstances = factoryContext.getCapabilityHolderInstances();
}
@Override
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/config/ConfigLoaderFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/config/ConfigLoaderFactory.java
index c69a7b2b..c195c109 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/config/ConfigLoaderFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/config/ConfigLoaderFactory.java
@@ -2,9 +2,10 @@ package work.slhaf.partner.api.factory.config;
import lombok.Setter;
import work.slhaf.partner.api.common.chat.pojo.Message;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.ConfigFactoryContext;
import java.util.HashMap;
import java.util.List;
@@ -18,8 +19,9 @@ public class ConfigLoaderFactory extends AgentBaseFactory {
@Override
protected void setVariables(AgentRegisterContext context) {
- modelConfigMap = context.getModelConfigMap();
- modelPromptMap = context.getModelPromptMap();
+ ConfigFactoryContext factoryContext = context.getConfigFactoryContext();
+ modelConfigMap = factoryContext.getModelConfigMap();
+ modelPromptMap = factoryContext.getModelPromptMap();
}
@Override
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/AgentRegisterContext.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/AgentRegisterContext.java
new file mode 100644
index 00000000..4ada2fd5
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/AgentRegisterContext.java
@@ -0,0 +1,28 @@
+package work.slhaf.partner.api.factory.context;
+
+import lombok.Data;
+import org.reflections.Reflections;
+import org.reflections.scanners.Scanners;
+import org.reflections.util.ConfigurationBuilder;
+
+import java.net.URL;
+import java.util.List;
+
+@Data
+public class AgentRegisterContext {
+ private Reflections reflections;
+ private CapabilityFactoryContext capabilityFactoryContext = new CapabilityFactoryContext();
+ private ConfigFactoryContext configFactoryContext = new ConfigFactoryContext();
+ private ModuleFactoryContext moduleFactoryContext = new ModuleFactoryContext();
+
+ public AgentRegisterContext(List urls) {
+ reflections = new Reflections(new ConfigurationBuilder().setScanners(
+ Scanners.FieldsAnnotated,
+ Scanners.SubTypes,
+ Scanners.MethodsAnnotated,
+ Scanners.TypesAnnotated
+ )
+ .setUrls(urls)
+ );
+ }
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/CapabilityFactoryContext.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/CapabilityFactoryContext.java
new file mode 100644
index 00000000..85033d39
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/CapabilityFactoryContext.java
@@ -0,0 +1,17 @@
+package work.slhaf.partner.api.factory.context;
+
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.function.Function;
+
+@Data
+public class CapabilityFactoryContext {
+ private final HashMap> methodsRouterTable = new HashMap<>();
+ private final HashMap> coordinatedMethodsRouterTable = new HashMap<>();
+ private final HashMap, Object> capabilityCoreInstances = new HashMap<>();
+ private final HashMap, Object> capabilityHolderInstances = new HashMap<>();
+ private Set> cores;
+ private Set> capabilities;
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/ConfigFactoryContext.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/ConfigFactoryContext.java
new file mode 100644
index 00000000..17ff36ac
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/ConfigFactoryContext.java
@@ -0,0 +1,14 @@
+package work.slhaf.partner.api.factory.context;
+
+import lombok.Data;
+import work.slhaf.partner.api.common.chat.pojo.Message;
+import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
+
+import java.util.HashMap;
+import java.util.List;
+
+@Data
+public class ConfigFactoryContext {
+ private HashMap> modelPromptMap = new HashMap<>();
+ private HashMap modelConfigMap = new HashMap<>();
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/ModuleFactoryContext.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/ModuleFactoryContext.java
new file mode 100644
index 00000000..7496e766
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/context/ModuleFactoryContext.java
@@ -0,0 +1,17 @@
+package work.slhaf.partner.api.factory.context;
+
+import lombok.Data;
+import work.slhaf.partner.api.factory.module.pojo.MetaMethod;
+import work.slhaf.partner.api.factory.module.pojo.MetaModule;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+@Data
+public class ModuleFactoryContext {
+ private List moduleList = new ArrayList<>();
+ private HashMap,Set> preHookMethods = new HashMap<>();
+ private HashMap,Set> postHookMethods = new HashMap<>();
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/entity/AgentRegisterContext.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/entity/AgentRegisterContext.java
deleted file mode 100644
index 0fd2e79c..00000000
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/entity/AgentRegisterContext.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package work.slhaf.partner.api.factory.entity;
-
-import lombok.Data;
-import org.reflections.Reflections;
-import org.reflections.scanners.Scanners;
-import org.reflections.util.ConfigurationBuilder;
-import work.slhaf.partner.api.common.chat.pojo.Message;
-import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
-import work.slhaf.partner.api.factory.module.pojo.MetaModule;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Function;
-
-@Data
-public class AgentRegisterContext {
- private Reflections reflections;
- private final HashMap> methodsRouterTable = new HashMap<>();
- private final HashMap> coordinatedMethodsRouterTable = new HashMap<>();
- private final HashMap, Object> capabilityCoreInstances = new HashMap<>();
- private final HashMap, Object> capabilityHolderInstances = new HashMap<>();
- private Set> cores;
- private Set> capabilities;
- private HashMap> modelPromptMap = new HashMap<>();
- private HashMap modelConfigMap = new HashMap<>();
- private List moduleList = new ArrayList<>();
-
- public AgentRegisterContext(List paths) {
- reflections = new Reflections(new ConfigurationBuilder().setScanners(
- Scanners.FieldsAnnotated,
- Scanners.SubTypes,
- Scanners.MethodsAnnotated,
- Scanners.TypesAnnotated
- )
- .forPackages(paths.toArray(paths.toArray(new String[0])))
- );
- }
-}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/AgentRegisterFactoryFailedException.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/AgentRegisterFactoryFailedException.java
new file mode 100644
index 00000000..14b5a7c9
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/AgentRegisterFactoryFailedException.java
@@ -0,0 +1,11 @@
+package work.slhaf.partner.api.factory.exception;
+
+public class AgentRegisterFactoryFailedException extends RuntimeException {
+ public AgentRegisterFactoryFailedException(String message, Throwable cause) {
+ super("AgentRegisterFactory 执行失败: " + message, cause);
+ }
+
+ public AgentRegisterFactoryFailedException(String message) {
+ super("AgentRegisterFactory 执行失败: " + message);
+ }
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModuleLoadFailedException.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModuleLoadFailedException.java
new file mode 100644
index 00000000..a49e6168
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModuleLoadFailedException.java
@@ -0,0 +1,11 @@
+package work.slhaf.partner.api.factory.exception;
+
+public class ExternalModuleLoadFailedException extends AgentRegisterFactoryFailedException{
+ public ExternalModuleLoadFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ExternalModuleLoadFailedException(String message) {
+ super(message);
+ }
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModulePathNotExistException.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModulePathNotExistException.java
index 95fb61dc..55563014 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModulePathNotExistException.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/exception/ExternalModulePathNotExistException.java
@@ -1,7 +1,11 @@
package work.slhaf.partner.api.factory.exception;
-public class ExternalModulePathNotExistException extends RuntimeException {
+public class ExternalModulePathNotExistException extends AgentRegisterFactoryFailedException {
public ExternalModulePathNotExistException(String message) {
- super("AgentRegisterFactory 执行失败: " + message);
+ super(message);
+ }
+
+ public ExternalModulePathNotExistException(String message, Throwable cause) {
+ super(message, cause);
}
}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleCheckFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleCheckFactory.java
index 679326c9..338a193a 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleCheckFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleCheckFactory.java
@@ -1,9 +1,9 @@
package work.slhaf.partner.api.factory.module;
import org.reflections.Reflections;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
import work.slhaf.partner.api.factory.config.ModelConfigManager;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.factory.module.annotation.After;
import work.slhaf.partner.api.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.factory.module.annotation.Before;
@@ -28,14 +28,27 @@ public class ModuleCheckFactory extends AgentBaseFactory {
@Override
protected void run() {
+ Set> types = reflections.getTypesAnnotatedWith(AgentModule.class);
//检查注解AgentModule所在类是否继承了AgentInteractionModule
- agentModuleAnnotationCheck();
+ agentModuleAnnotationCheck(types);
+ //检查AgentModule是否具备无参构造方法
+ moduleConstructorsCheck(types);
//检查hook注解所在方法是否位于AgentInteractionModule子类/AgentInteractionSubModule子类/ActivateModel子类
hookLocationCheck();
//检查实现了ActivateModel的模块数量、名称与prompt是否一致
activateModelImplCheck();
}
+ private void moduleConstructorsCheck(Set> types) {
+ for (Class> type : types) {
+ try {
+ type.getConstructor();
+ } catch (NoSuchMethodException e) {
+ throw new ModuleCheckException("缺少无参构造方法的模块: " + type.getSimpleName(), e);
+ }
+ }
+ }
+
private void activateModelImplCheck() {
try {
Set> types = reflections.getSubTypesOf(ActivateModel.class);
@@ -47,10 +60,10 @@ public class ModuleCheckFactory extends AgentBaseFactory {
Set promptKeySet = ModelConfigManager.INSTANCE.getModelPromptMap().keySet();
if (!promptKeySet.containsAll(modelKeySet)) {
modelKeySet.removeAll(promptKeySet);
- throw new ModuleCheckException("存在未配置Prompt的ActivateModel实现! 缺少Prompt的ModelKey列表: "+ modelKeySet);
+ throw new ModuleCheckException("存在未配置Prompt的ActivateModel实现! 缺少Prompt的ModelKey列表: " + modelKeySet);
}
- }catch (Exception e) {
- throw new ModuleCheckException("ActivateModel 检测出错",e);
+ } catch (Exception e) {
+ throw new ModuleCheckException("ActivateModel 检测出错", e);
}
}
@@ -89,12 +102,11 @@ public class ModuleCheckFactory extends AgentBaseFactory {
if (ActivateModel.class.isAssignableFrom(type)) {
continue;
}
- throw new ModuleCheckException("在不支持的类中使用了hook注解: "+type.getSimpleName());
+ throw new ModuleCheckException("在不支持的类中使用了hook注解: " + type.getSimpleName());
}
}
- private void agentModuleAnnotationCheck() {
- Set> types = reflections.getTypesAnnotatedWith(AgentModule.class);
+ private void agentModuleAnnotationCheck(Set> types) {
for (Class> type : types) {
if (type.isAnnotation()) {
continue;
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModulePreHookExecuteFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModulePreHookExecuteFactory.java
index 49f1e369..5a007c71 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModulePreHookExecuteFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModulePreHookExecuteFactory.java
@@ -1,7 +1,7 @@
package work.slhaf.partner.api.factory.module;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
import java.lang.reflect.InvocationTargetException;
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleProxyFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleProxyFactory.java
index 30ed77aa..62053cdd 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleProxyFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleProxyFactory.java
@@ -1,21 +1,96 @@
package work.slhaf.partner.api.factory.module;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.implementation.bind.annotation.*;
+import net.bytebuddy.matcher.ElementMatchers;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
+import work.slhaf.partner.api.factory.module.exception.ModuleInstanceGenerateFailedException;
+import work.slhaf.partner.api.factory.module.exception.ModuleProxyGenerateFailedException;
+import work.slhaf.partner.api.factory.module.pojo.MetaMethod;
+import work.slhaf.partner.api.factory.module.pojo.MetaModule;
+import work.slhaf.partner.api.flow.abstracts.AgentInteractionModule;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
/**
* 通过扫描注解@Before,获取到各个模块的后hook逻辑并通过动态代理添加到执行逻辑之后
*/
public class ModuleProxyFactory extends AgentBaseFactory {
+
+ private List moduleList;
+ private HashMap, Set> postHookMethods;
+
@Override
protected void setVariables(AgentRegisterContext context) {
-
+ ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
+ moduleList = factoryContext.getModuleList();
+ postHookMethods = factoryContext.getPostHookMethods();
}
@Override
protected void run() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- //TODO 通过动态代理生成实例、添加PostHook逻辑
+ //TODO 生成实例、并通过动态代理添加PostHook逻辑
+ generateInstances();
+ setPostHookProxy();
+ }
+
+ private void setPostHookProxy() {
+ for (MetaModule module : moduleList) {
+ Class> clazz = module.getClazz();
+ try {
+ Class> proxyClass = new ByteBuddy()
+ .subclass(clazz)
+ .method(ElementMatchers.isOverriddenFrom(AgentInteractionModule.class))
+ .intercept(MethodDelegation.to(new ModuleProxyInterceptor(postHookMethods.get(clazz).stream().sorted(Comparator.comparing(MetaMethod::getOrder)).toList())))
+ .make()
+ .load(ModuleProxyFactory.class.getClassLoader())
+ .getLoaded();
+
+ AgentInteractionModule interactionModule = (AgentInteractionModule) proxyClass.getConstructor().newInstance();
+ //TODO 检测代理写法是否正确
+ //TODO 添加ModuleManager,负责统一管理Module的加载、卸载
+ } catch (Exception e) {
+ throw new ModuleProxyGenerateFailedException("创建代理对象失败: " + clazz.getSimpleName(), e);
+ }
+ }
+ }
+
+ private void generateInstances() {
+ for (MetaModule metaModule : moduleList) {
+ try {
+ Class> clazz = metaModule.getClazz();
+ Object instance = clazz.getConstructor().newInstance();
+ metaModule.setInstance(instance);
+ } catch (Exception e) {
+ throw new ModuleInstanceGenerateFailedException("模块实例构造失败:" + e.getMessage());
+ }
+ }
+ }
+
+ private static class ModuleProxyInterceptor {
+
+ private List postHookMethods;
+
+ private ModuleProxyInterceptor(List postHookMethods) {
+ this.postHookMethods = postHookMethods;
+ }
+
+ @RuntimeType
+ public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable> zuper, @This Object proxy) throws Exception {
+ Object res = zuper.call();
+ for (MetaMethod metaMethod : postHookMethods) {
+ metaMethod.getMethod().invoke(proxy, allArguments);
+ }
+ return res;
+ }
}
}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleRegisterFactory.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleRegisterFactory.java
index bfc2b395..8358b180 100644
--- a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleRegisterFactory.java
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/ModuleRegisterFactory.java
@@ -1,15 +1,17 @@
package work.slhaf.partner.api.factory.module;
import org.reflections.Reflections;
-import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
-import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
+import work.slhaf.partner.api.factory.AgentBaseFactory;
+import work.slhaf.partner.api.factory.context.AgentRegisterContext;
+import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
+import work.slhaf.partner.api.factory.module.annotation.After;
import work.slhaf.partner.api.factory.module.annotation.AgentModule;
+import work.slhaf.partner.api.factory.module.annotation.Before;
+import work.slhaf.partner.api.factory.module.pojo.MetaMethod;
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
+import java.lang.reflect.Method;
+import java.util.*;
/**
* 负责扫描@Module注解获取模块实例
@@ -18,15 +20,63 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
private Reflections reflections;
private List moduleList;
+ private HashMap, Set> postHookMethods;
+ private HashMap, Set> preHookMethods;
@Override
protected void setVariables(AgentRegisterContext context) {
+ ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
reflections = context.getReflections();
- moduleList = context.getModuleList();
+ moduleList = factoryContext.getModuleList();
+ postHookMethods = factoryContext.getPostHookMethods();
+ preHookMethods = factoryContext.getPreHookMethods();
}
@Override
protected void run() {
+ registerModuleList();
+ registerHookSet();
+ }
+
+ private void registerHookSet() {
+ setPostHookMethods();
+ setPreHookMethods();
+ }
+
+ private void setPreHookMethods() {
+ Set methods = reflections.getMethodsAnnotatedWith(After.class);
+ for (Method method : methods) {
+ MetaMethod metaMethod = new MetaMethod();
+ metaMethod.setMethod(method);
+ metaMethod.setOrder(method.getAnnotation(After.class).order());
+
+ addMetaMethod(method, metaMethod, postHookMethods);
+ }
+ }
+
+ private void setPostHookMethods() {
+ Set methods = reflections.getMethodsAnnotatedWith(Before.class);
+ for (Method method : methods) {
+ MetaMethod metaMethod = new MetaMethod();
+ metaMethod.setMethod(method);
+ metaMethod.setOrder(method.getAnnotation(Before.class).order());
+
+ addMetaMethod(method, metaMethod, preHookMethods);
+ }
+ }
+
+ private void addMetaMethod(Method method, MetaMethod metaMethod, HashMap, Set> preHookMethods) {
+ Class> clazz = method.getDeclaringClass();
+ if (preHookMethods.containsKey(clazz)) {
+ preHookMethods.get(clazz).add(metaMethod);
+ }else {
+ HashSet metaMethods = new HashSet<>();
+ metaMethods.add(metaMethod);
+ preHookMethods.put(clazz, metaMethods);
+ }
+ }
+
+ private void registerModuleList() {
//反射扫描获取@AgentModule所在类, 该部分为Agent流程执行模块
Set> modules = reflections.getTypesAnnotatedWith(AgentModule.class);
for (Class> module : modules) {
@@ -38,5 +88,6 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
moduleList.add(metaModule);
}
moduleList.sort(Comparator.comparing(MetaModule::getOrder));
+
}
}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/exception/ModuleInstanceGenerateFailedException.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/exception/ModuleInstanceGenerateFailedException.java
new file mode 100644
index 00000000..e7591588
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/exception/ModuleInstanceGenerateFailedException.java
@@ -0,0 +1,11 @@
+package work.slhaf.partner.api.factory.module.exception;
+
+public class ModuleInstanceGenerateFailedException extends ModuleFactoryFailedException{
+ public ModuleInstanceGenerateFailedException(String message) {
+ super(message);
+ }
+
+ public ModuleInstanceGenerateFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/exception/ModuleProxyGenerateFailedException.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/exception/ModuleProxyGenerateFailedException.java
new file mode 100644
index 00000000..2f95cd25
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/exception/ModuleProxyGenerateFailedException.java
@@ -0,0 +1,11 @@
+package work.slhaf.partner.api.factory.module.exception;
+
+public class ModuleProxyGenerateFailedException extends ModuleFactoryFailedException{
+ public ModuleProxyGenerateFailedException(String message) {
+ super(message);
+ }
+
+ public ModuleProxyGenerateFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/pojo/MetaMethod.java b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/pojo/MetaMethod.java
new file mode 100644
index 00000000..d8f11fdf
--- /dev/null
+++ b/Partner-Api/src/main/java/work/slhaf/partner/api/factory/module/pojo/MetaMethod.java
@@ -0,0 +1,11 @@
+package work.slhaf.partner.api.factory.module.pojo;
+
+import lombok.Data;
+
+import java.lang.reflect.Method;
+
+@Data
+public class MetaMethod {
+ private int order;
+ private Method method;
+}
diff --git a/Partner-Test-Demo/pom.xml b/Partner-Test-Demo/pom.xml
index b06b8ca7..691c3e20 100644
--- a/Partner-Test-Demo/pom.xml
+++ b/Partner-Test-Demo/pom.xml
@@ -12,11 +12,6 @@
Partner-Test-Demo
-
- org.reflections
- reflections
- 0.10.2
-
work.slhaf
Partner-Api
diff --git a/pom.xml b/pom.xml
index b7287697..07fa185d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,50 +19,6 @@
21
UTF-8
-
-
- org.projectlombok
- lombok
- 1.18.36
- provided
-
-
- junit
- junit
- 4.13.2
- test
-
-
- org.junit.jupiter
- junit-jupiter
- 5.13.2
-
-
- org.slf4j
- slf4j-api
- 2.0.17
-
-
- ch.qos.logback
- logback-classic
- 1.5.17
-
-
- commons-io
- commons-io
- 2.18.0
-
-
- cn.hutool
- hutool-all
- 5.8.36
-
-
- com.alibaba
- fastjson
- 2.0.56
-
-