mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
refactor(framework): migrate startup chain exceptions to AgentException hierarchy
This commit is contained in:
@@ -3,7 +3,8 @@ package work.slhaf.partner.framework.agent.config
|
|||||||
import com.alibaba.fastjson2.JSON
|
import com.alibaba.fastjson2.JSON
|
||||||
import com.alibaba.fastjson2.JSONObject
|
import com.alibaba.fastjson2.JSONObject
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentLaunchFailedException
|
import work.slhaf.partner.framework.agent.exception.AgentStartupException
|
||||||
|
import work.slhaf.partner.framework.agent.exception.checkAgentStartup
|
||||||
import work.slhaf.partner.framework.agent.support.DirectoryWatchSupport
|
import work.slhaf.partner.framework.agent.support.DirectoryWatchSupport
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
@@ -19,6 +20,7 @@ import kotlin.reflect.full.memberProperties
|
|||||||
import kotlin.reflect.jvm.javaField
|
import kotlin.reflect.jvm.javaField
|
||||||
|
|
||||||
object ConfigCenter : AutoCloseable {
|
object ConfigCenter : AutoCloseable {
|
||||||
|
private const val COMPONENT_NAME = "config-center"
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(ConfigCenter::class.java)
|
private val log = LoggerFactory.getLogger(ConfigCenter::class.java)
|
||||||
val paths = resolvePaths()
|
val paths = resolvePaths()
|
||||||
@@ -31,9 +33,8 @@ object ConfigCenter : AutoCloseable {
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun register(configurable: Configurable) {
|
fun register(configurable: Configurable) {
|
||||||
|
checkAgentStartup(!started) {
|
||||||
check(!started) {
|
AgentStartupException("ConfigCenter does not allow registration after watching started", COMPONENT_NAME)
|
||||||
"ConfigCenter does not allow registration after watching started"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val declared = configurable.declare()
|
val declared = configurable.declare()
|
||||||
@@ -42,15 +43,18 @@ object ConfigCenter : AutoCloseable {
|
|||||||
declared.forEach { (path, registration) ->
|
declared.forEach { (path, registration) ->
|
||||||
val normalizedPath = normalizeRelativePath(path)
|
val normalizedPath = normalizeRelativePath(path)
|
||||||
|
|
||||||
check(normalized.putIfAbsent(normalizedPath, registration) == null) {
|
checkAgentStartup(normalized.putIfAbsent(normalizedPath, registration) == null) {
|
||||||
"Duplicated config path declared in the same configurable: $normalizedPath"
|
AgentStartupException(
|
||||||
|
"Duplicated config path declared in the same configurable: $normalizedPath",
|
||||||
|
COMPONENT_NAME
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
normalized.forEach { (path, registration) ->
|
normalized.forEach { (path, registration) ->
|
||||||
check(registrations.putIfAbsent(path, registration) == null) {
|
checkAgentStartup(registrations.putIfAbsent(path, registration) == null) {
|
||||||
"Config path already registered: $path"
|
AgentStartupException("Config path already registered: $path", COMPONENT_NAME)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +97,10 @@ object ConfigCenter : AutoCloseable {
|
|||||||
(registration as ConfigRegistration<Config>).init(defaultConfig, null)
|
(registration as ConfigRegistration<Config>).init(defaultConfig, null)
|
||||||
}
|
}
|
||||||
val configDoc = resolveConfigDoc(registration.type())
|
val configDoc = resolveConfigDoc(registration.type())
|
||||||
throw AgentLaunchFailedException("Failed to init config, related path: $path, config definition: $configDoc")
|
throw AgentStartupException(
|
||||||
|
"Failed to init config, related path: $path, config definition: $configDoc",
|
||||||
|
COMPONENT_NAME
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -232,8 +239,8 @@ object ConfigCenter : AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun normalizeRelativePath(path: Path): Path {
|
private fun normalizeRelativePath(path: Path): Path {
|
||||||
require(!path.isAbsolute) {
|
checkAgentStartup(!path.isAbsolute) {
|
||||||
"Config path must be relative: $path"
|
AgentStartupException("Config path must be relative: $path", COMPONENT_NAME)
|
||||||
}
|
}
|
||||||
return path.normalize()
|
return path.normalize()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,16 @@ open class GatewayException @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class GatewayRegistryException @JvmOverloads constructor(
|
||||||
|
message: String,
|
||||||
|
val gatewayName: String,
|
||||||
|
cause: Throwable? = null
|
||||||
|
) : InteractionException(message, cause) {
|
||||||
|
override fun toReport(): ExceptionReport = super.toReport().also {
|
||||||
|
it.extra["gatewayName"] = gatewayName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open class ModelInvokeException(
|
open class ModelInvokeException(
|
||||||
message: String,
|
message: String,
|
||||||
val providerName: String,
|
val providerName: String,
|
||||||
@@ -51,3 +61,17 @@ open class ModelInvokeException(
|
|||||||
it.extra["override"] = override
|
it.extra["override"] = override
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class ModelRegistryException(
|
||||||
|
message: String,
|
||||||
|
val providerName: String,
|
||||||
|
val modelKey: String,
|
||||||
|
val override: Map<String, String> = emptyMap(),
|
||||||
|
cause: Throwable? = null
|
||||||
|
) : AgentRuntimeException(message, cause) {
|
||||||
|
override fun toReport(): ExceptionReport = super.toReport().also {
|
||||||
|
it.extra["providerName"] = providerName
|
||||||
|
it.extra["modelKey"] = modelKey
|
||||||
|
it.extra["override"] = override
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,3 +23,31 @@ open class FactoryExecutionException @JvmOverloads constructor(
|
|||||||
return report
|
return report
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class GatewayStartupException @JvmOverloads constructor(
|
||||||
|
message: String,
|
||||||
|
val gatewayName: String,
|
||||||
|
cause: Throwable? = null
|
||||||
|
) : AgentStartupException(message, "agent-gateway-registry", cause) {
|
||||||
|
override fun toReport(): ExceptionReport {
|
||||||
|
val report = super.toReport()
|
||||||
|
report.extra["gatewayName"] = gatewayName
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class ModelRegistryStartupException @JvmOverloads constructor(
|
||||||
|
message: String,
|
||||||
|
val providerName: String,
|
||||||
|
val modelKey: String,
|
||||||
|
val override: Map<String, String> = emptyMap(),
|
||||||
|
cause: Throwable? = null
|
||||||
|
) : AgentStartupException(message, "model-runtime-registry", cause) {
|
||||||
|
override fun toReport(): ExceptionReport {
|
||||||
|
val report = super.toReport()
|
||||||
|
report.extra["providerName"] = providerName
|
||||||
|
report.extra["modelKey"] = modelKey
|
||||||
|
report.extra["override"] = override
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory
|
package work.slhaf.partner.framework.agent.factory
|
||||||
|
|
||||||
import org.reflections.util.ClasspathHelper
|
import org.reflections.util.ClasspathHelper
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.CapabilityAnnotationValidatorFactory
|
import work.slhaf.partner.framework.agent.factory.capability.CapabilityAnnotationValidatorFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.CapabilityInjectorFactory
|
import work.slhaf.partner.framework.agent.factory.capability.CapabilityInjectorFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.CapabilityRegisterFactory
|
import work.slhaf.partner.framework.agent.factory.capability.CapabilityRegisterFactory
|
||||||
@@ -10,7 +11,6 @@ import work.slhaf.partner.framework.agent.factory.component.ComponentInjectorFac
|
|||||||
import work.slhaf.partner.framework.agent.factory.component.ComponentRegisterFactory
|
import work.slhaf.partner.framework.agent.factory.component.ComponentRegisterFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.context.ShutdownHookCollectorFactory
|
import work.slhaf.partner.framework.agent.factory.context.ShutdownHookCollectorFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.exception.ExternalModuleLoadFailedException
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
@@ -72,7 +72,11 @@ object AgentRegisterFactory {
|
|||||||
.filter { it.name.endsWith(".jar") }
|
.filter { it.name.endsWith(".jar") }
|
||||||
.forEach { urls.add(it.toURI().toURL()) }
|
.forEach { urls.add(it.toURI().toURL()) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw ExternalModuleLoadFailedException("外部模块URL获取失败: $externalPackagePath", e)
|
throw FactoryExecutionException(
|
||||||
|
"Failed to load external module URLs from: $externalPackagePath",
|
||||||
|
"agent-register-factory",
|
||||||
|
e
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,12 @@ package work.slhaf.partner.framework.agent.factory.capability
|
|||||||
|
|
||||||
import cn.hutool.core.util.ClassUtil
|
import cn.hutool.core.util.ClassUtil
|
||||||
import org.reflections.Reflections
|
import org.reflections.Reflections
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.Capability
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.Capability
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityMethod
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityMethod
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.DuplicateCapabilityException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.UnMatchedCapabilityException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.UnMatchedCapabilityMethodException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.isAssignableFromAnnotation
|
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.isAssignableFromAnnotation
|
||||||
@@ -25,6 +23,8 @@ import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.methodSignatu
|
|||||||
* - `@InjectCapability` 字段仅允许位于 `@AgentComponent` 相关类中。
|
* - `@InjectCapability` 字段仅允许位于 `@AgentComponent` 相关类中。
|
||||||
*/
|
*/
|
||||||
class CapabilityAnnotationValidatorFactory : AgentBaseFactory() {
|
class CapabilityAnnotationValidatorFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "capability-annotation-validator-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val reflections = context.reflections
|
val reflections = context.reflections
|
||||||
val cores = loadCores(reflections)
|
val cores = loadCores(reflections)
|
||||||
@@ -61,7 +61,7 @@ class CapabilityAnnotationValidatorFactory : AgentBaseFactory() {
|
|||||||
val value = capability.getAnnotation(Capability::class.java).value
|
val value = capability.getAnnotation(Capability::class.java).value
|
||||||
val existed = capabilityByValue.putIfAbsent(value, capability)
|
val existed = capabilityByValue.putIfAbsent(value, capability)
|
||||||
if (existed != null) {
|
if (existed != null) {
|
||||||
throw DuplicateCapabilityException("Capability 注册异常: 重复的Capability接口: $value")
|
throw FactoryExecutionException("Duplicate capability value detected: $value", factoryName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,9 +73,9 @@ class CapabilityAnnotationValidatorFactory : AgentBaseFactory() {
|
|||||||
methods.forEach { method ->
|
methods.forEach { method ->
|
||||||
val declaringClass = method.declaringClass
|
val declaringClass = method.declaringClass
|
||||||
if (!declaringClass.isAnnotationPresent(CapabilityCore::class.java)) {
|
if (!declaringClass.isAnnotationPresent(CapabilityCore::class.java)) {
|
||||||
throw UnMatchedCapabilityException(
|
throw FactoryExecutionException(
|
||||||
"@CapabilityMethod 仅能用于 @CapabilityCore 所标注类中: " +
|
"@CapabilityMethod can only be declared in @CapabilityCore classes: ${declaringClass.name}#${method.name}",
|
||||||
"${declaringClass.name}#${method.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,13 +109,19 @@ class CapabilityAnnotationValidatorFactory : AgentBaseFactory() {
|
|||||||
val signature = methodSignature(method)
|
val signature = methodSignature(method)
|
||||||
val implementors = signatureMap[signature].orEmpty()
|
val implementors = signatureMap[signature].orEmpty()
|
||||||
if (implementors.isEmpty()) {
|
if (implementors.isEmpty()) {
|
||||||
throw UnMatchedCapabilityMethodException(
|
throw FactoryExecutionException(
|
||||||
"Capability方法缺少实现: $capabilityValue.$signature"
|
"Missing capability method implementation: $capabilityValue.$signature",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (implementors.size > 1) {
|
if (implementors.size > 1) {
|
||||||
throw UnMatchedCapabilityMethodException(
|
throw FactoryExecutionException(
|
||||||
"Capability方法存在多个实现: $capabilityValue.$signature -> ${implementors.joinToString(", ")}"
|
"Multiple capability method implementations found: $capabilityValue.$signature -> ${
|
||||||
|
implementors.joinToString(
|
||||||
|
", "
|
||||||
|
)
|
||||||
|
}",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,8 +135,9 @@ class CapabilityAnnotationValidatorFactory : AgentBaseFactory() {
|
|||||||
reflections.getFieldsAnnotatedWith(InjectCapability::class.java).forEach { field ->
|
reflections.getFieldsAnnotatedWith(InjectCapability::class.java).forEach { field ->
|
||||||
val declaringClass = field.declaringClass
|
val declaringClass = field.declaringClass
|
||||||
if (!isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) {
|
if (!isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) {
|
||||||
throw UnMatchedCapabilityException(
|
throw FactoryExecutionException(
|
||||||
"InjectCapability 注解只能用于 AgentComponent 注解所在类,检查该类是否使用了@CapabilityHolder注解或者受其标注的注解或父类: $declaringClass"
|
"@InjectCapability can only be declared on AgentComponent classes: $declaringClass",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability
|
package work.slhaf.partner.framework.agent.factory.capability
|
||||||
|
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.Capability
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.Capability
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.CapabilityProxySetFailedException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentContext
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
@@ -16,6 +16,8 @@ import java.lang.reflect.Modifier
|
|||||||
* 注入值来源于 `AgentContext.capabilities`。
|
* 注入值来源于 `AgentContext.capabilities`。
|
||||||
*/
|
*/
|
||||||
class CapabilityInjectorFactory : AgentBaseFactory() {
|
class CapabilityInjectorFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "capability-injector-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val agentContext = context.agentContext
|
val agentContext = context.agentContext
|
||||||
val targets = buildTargets(agentContext)
|
val targets = buildTargets(agentContext)
|
||||||
@@ -38,11 +40,12 @@ class CapabilityInjectorFactory : AgentBaseFactory() {
|
|||||||
field.isAccessible = true
|
field.isAccessible = true
|
||||||
val value = resolveCapabilityInstance(field, capabilityMap, target::class.java)
|
val value = resolveCapabilityInstance(field, capabilityMap, target::class.java)
|
||||||
field.set(target, value)
|
field.set(target, value)
|
||||||
} catch (e: CapabilityProxySetFailedException) {
|
} catch (e: FactoryExecutionException) {
|
||||||
throw e
|
throw e
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw CapabilityProxySetFailedException(
|
throw FactoryExecutionException(
|
||||||
"Capability 注入失败: ${target::class.java.name}#${field.name}",
|
"Failed to inject capability dependency: ${target::class.java.name}#${field.name}",
|
||||||
|
factoryName,
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -55,17 +58,20 @@ class CapabilityInjectorFactory : AgentBaseFactory() {
|
|||||||
targetClass: Class<*>
|
targetClass: Class<*>
|
||||||
): Any {
|
): Any {
|
||||||
val capability = field.type.getAnnotation(Capability::class.java)
|
val capability = field.type.getAnnotation(Capability::class.java)
|
||||||
?: throw CapabilityProxySetFailedException(
|
?: throw FactoryExecutionException(
|
||||||
"InjectCapability 字段类型未标注 @Capability: ${targetClass.name}#${field.name} -> ${field.type.name}"
|
"InjectCapability target type is not annotated with @Capability: ${targetClass.name}#${field.name} -> ${field.type.name}",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
|
|
||||||
val capabilityValue = capability.value
|
val capabilityValue = capability.value
|
||||||
val implementation = capabilityMap[capabilityValue] ?: throw CapabilityProxySetFailedException(
|
val implementation = capabilityMap[capabilityValue] ?: throw FactoryExecutionException(
|
||||||
"未找到可注入 Capability 实例: ${targetClass.name}#${field.name} -> $capabilityValue"
|
"Injectable capability implementation not found: ${targetClass.name}#${field.name} -> $capabilityValue",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
if (!field.type.isAssignableFrom(implementation.instance.javaClass)) {
|
if (!field.type.isAssignableFrom(implementation.instance.javaClass)) {
|
||||||
throw CapabilityProxySetFailedException(
|
throw FactoryExecutionException(
|
||||||
"Capability 实例类型不匹配: ${targetClass.name}#${field.name} -> $capabilityValue"
|
"Capability implementation type mismatch: ${targetClass.name}#${field.name} -> $capabilityValue",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return implementation.instance
|
return implementation.instance
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability
|
package work.slhaf.partner.framework.agent.factory.capability
|
||||||
|
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.Capability
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.Capability
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityMethod
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityMethod
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.CapabilityCoreInstancesCreateFailedException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.CapabilityFactoryExecuteFailedException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.exception.DuplicateMethodException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.methodSignature
|
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.methodSignature
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
@@ -23,6 +21,8 @@ import java.util.function.Function
|
|||||||
* - 将 capability 代理、cores 与方法映射注册到 `AgentContext`。
|
* - 将 capability 代理、cores 与方法映射注册到 `AgentContext`。
|
||||||
*/
|
*/
|
||||||
class CapabilityRegisterFactory : AgentBaseFactory() {
|
class CapabilityRegisterFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "capability-register-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val capabilityFactoryContext = context.capabilityFactoryContext
|
val capabilityFactoryContext = context.capabilityFactoryContext
|
||||||
val agentContext = context.agentContext
|
val agentContext = context.agentContext
|
||||||
@@ -30,7 +30,10 @@ class CapabilityRegisterFactory : AgentBaseFactory() {
|
|||||||
val cores = capabilityFactoryContext.cores.toSet()
|
val cores = capabilityFactoryContext.cores.toSet()
|
||||||
val capabilities = capabilityFactoryContext.capabilities.toSet()
|
val capabilities = capabilityFactoryContext.capabilities.toSet()
|
||||||
if (cores.isEmpty() || capabilities.isEmpty()) {
|
if (cores.isEmpty() || capabilities.isEmpty()) {
|
||||||
throw CapabilityFactoryExecuteFailedException("CapabilityFactoryContext 中缺少已校验的 capability/core 信息")
|
throw FactoryExecutionException(
|
||||||
|
"Validated capability/core scan result is missing from CapabilityFactoryContext",
|
||||||
|
factoryName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val coreInstances = LinkedHashMap<Class<*>, Any>()
|
val coreInstances = LinkedHashMap<Class<*>, Any>()
|
||||||
@@ -59,7 +62,7 @@ class CapabilityRegisterFactory : AgentBaseFactory() {
|
|||||||
coreInstances[core] = constructor.newInstance()
|
coreInstances[core] = constructor.newInstance()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw CapabilityCoreInstancesCreateFailedException("core实例创建失败", e)
|
throw FactoryExecutionException("Failed to instantiate capability cores", factoryName, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,14 +75,17 @@ class CapabilityRegisterFactory : AgentBaseFactory() {
|
|||||||
cores.forEach { core ->
|
cores.forEach { core ->
|
||||||
val capabilityValue = core.getAnnotation(CapabilityCore::class.java).value
|
val capabilityValue = core.getAnnotation(CapabilityCore::class.java).value
|
||||||
val coreInstance = coreInstances[core]
|
val coreInstance = coreInstances[core]
|
||||||
?: throw CapabilityFactoryExecuteFailedException("未找到CapabilityCore实例: ${core.name}")
|
?: throw FactoryExecutionException("Capability core instance not found: ${core.name}", factoryName)
|
||||||
|
|
||||||
core.methods
|
core.methods
|
||||||
.filter { it.isAnnotationPresent(CapabilityMethod::class.java) }
|
.filter { it.isAnnotationPresent(CapabilityMethod::class.java) }
|
||||||
.forEach { method ->
|
.forEach { method ->
|
||||||
val key = "$capabilityValue.${methodSignature(method)}"
|
val key = "$capabilityValue.${methodSignature(method)}"
|
||||||
if (map.containsKey(key) || methodsRouterTable.containsKey(key)) {
|
if (map.containsKey(key) || methodsRouterTable.containsKey(key)) {
|
||||||
throw DuplicateMethodException("重复注册能力方法: ${core.name}#${method.name}")
|
throw FactoryExecutionException(
|
||||||
|
"Duplicate capability method binding: ${core.name}#${method.name}",
|
||||||
|
factoryName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
map[key] = MethodBinding(core, coreInstance, method)
|
map[key] = MethodBinding(core, coreInstance, method)
|
||||||
methodsRouterTable[key] = Function { args ->
|
methodsRouterTable[key] = Function { args ->
|
||||||
@@ -106,7 +112,7 @@ class CapabilityRegisterFactory : AgentBaseFactory() {
|
|||||||
else -> {
|
else -> {
|
||||||
val key = "$capabilityValue.${methodSignature(method)}"
|
val key = "$capabilityValue.${methodSignature(method)}"
|
||||||
val fn = methodsRouterTable[key]
|
val fn = methodsRouterTable[key]
|
||||||
?: throw CapabilityFactoryExecuteFailedException("未找到能力方法路由: $key")
|
?: throw FactoryExecutionException("Capability method route not found: $key", factoryName)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val actualArgs = (args ?: emptyArray<Any?>()) as Array<Any?>
|
val actualArgs = (args ?: emptyArray<Any?>()) as Array<Any?>
|
||||||
@@ -128,7 +134,7 @@ class CapabilityRegisterFactory : AgentBaseFactory() {
|
|||||||
}
|
}
|
||||||
val key = "$capabilityValue.${methodSignature(method)}"
|
val key = "$capabilityValue.${methodSignature(method)}"
|
||||||
val binding = methodBindingMap[key]
|
val binding = methodBindingMap[key]
|
||||||
?: throw CapabilityFactoryExecuteFailedException("Capability方法缺少实现: $key")
|
?: throw FactoryExecutionException("Missing capability method implementation for: $key", factoryName)
|
||||||
methods[key] = binding.method
|
methods[key] = binding.method
|
||||||
}
|
}
|
||||||
return methods
|
return methods
|
||||||
@@ -149,8 +155,9 @@ class CapabilityRegisterFactory : AgentBaseFactory() {
|
|||||||
return try {
|
return try {
|
||||||
method.invoke(instance, *args)
|
method.invoke(instance, *args)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw CapabilityFactoryExecuteFailedException(
|
throw FactoryExecutionException(
|
||||||
"能力方法调用失败: ${instance::class.java.name}#${method.name}",
|
"Failed to invoke capability method: ${instance::class.java.name}#${method.name}",
|
||||||
|
factoryName,
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentLaunchFailedException;
|
|
||||||
|
|
||||||
public class CapabilityCheckFailedException extends AgentLaunchFailedException {
|
|
||||||
public CapabilityCheckFailedException(String message) {
|
|
||||||
super("Capability注册失败: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CapabilityCheckFailedException(String message, Throwable cause) {
|
|
||||||
super("Capability注册失败: " + message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class CapabilityCoreInstancesCreateFailedException extends CapabilityFactoryExecuteFailedException {
|
|
||||||
public CapabilityCoreInstancesCreateFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CapabilityCoreInstancesCreateFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentLaunchFailedException;
|
|
||||||
|
|
||||||
public class CapabilityFactoryExecuteFailedException extends AgentLaunchFailedException {
|
|
||||||
public CapabilityFactoryExecuteFailedException(String message) {
|
|
||||||
super("CapabilityRegisterFactory 执行失败: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CapabilityFactoryExecuteFailedException(String message, Throwable cause) {
|
|
||||||
super("CapabilityRegisterFactory 执行失败: " + message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class CapabilityProxySetFailedException extends CapabilityFactoryExecuteFailedException {
|
|
||||||
public CapabilityProxySetFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CapabilityProxySetFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class DuplicateCapabilityException extends CapabilityCheckFailedException {
|
|
||||||
public DuplicateCapabilityException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DuplicateCapabilityException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class DuplicateMethodException extends CapabilityCheckFailedException {
|
|
||||||
public DuplicateMethodException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DuplicateMethodException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class EmptyCapabilityHolderException extends CapabilityCheckFailedException {
|
|
||||||
public EmptyCapabilityHolderException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmptyCapabilityHolderException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class UnMatchedCapabilityException extends CapabilityCheckFailedException {
|
|
||||||
public UnMatchedCapabilityException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnMatchedCapabilityException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class UnMatchedCapabilityMethodException extends CapabilityCheckFailedException {
|
|
||||||
public UnMatchedCapabilityMethodException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnMatchedCapabilityMethodException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.capability.exception;
|
|
||||||
|
|
||||||
public class UnMatchedCoordinatedMethodException extends CapabilityCheckFailedException {
|
|
||||||
public UnMatchedCoordinatedMethodException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnMatchedCoordinatedMethodException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component
|
package work.slhaf.partner.framework.agent.factory.component
|
||||||
|
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule
|
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.Init
|
import work.slhaf.partner.framework.agent.factory.component.annotation.Init
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.InjectModule
|
import work.slhaf.partner.framework.agent.factory.component.annotation.InjectModule
|
||||||
import work.slhaf.partner.framework.agent.factory.component.exception.ModuleCheckException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil
|
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil
|
||||||
|
|
||||||
@@ -18,6 +18,8 @@ import work.slhaf.partner.framework.agent.factory.util.ReflectUtil
|
|||||||
* - 通过校验的 `@Init` 方法按声明类存入 `ComponentFactoryContext`。
|
* - 通过校验的 `@Init` 方法按声明类存入 `ComponentFactoryContext`。
|
||||||
*/
|
*/
|
||||||
class ComponentAnnotationValidatorFactory : AgentBaseFactory() {
|
class ComponentAnnotationValidatorFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "component-annotation-validator-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val reflections = context.reflections
|
val reflections = context.reflections
|
||||||
val componentFactoryContext = context.componentFactoryContext
|
val componentFactoryContext = context.componentFactoryContext
|
||||||
@@ -27,15 +29,15 @@ class ComponentAnnotationValidatorFactory : AgentBaseFactory() {
|
|||||||
.forEach { method ->
|
.forEach { method ->
|
||||||
val declaringClass = method.declaringClass
|
val declaringClass = method.declaringClass
|
||||||
if (!ReflectUtil.isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) {
|
if (!ReflectUtil.isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"@Init 只能用于 AgentComponent 中: " +
|
"@Init can only be declared on AgentComponent classes: ${declaringClass.name}#${method.name}",
|
||||||
"${declaringClass.name}#${method.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (method.parameterCount > 0) {
|
if (method.parameterCount > 0) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"@Init 标注的方法不能包含形参: " +
|
"@Init methods must not declare parameters: ${declaringClass.name}#${method.name}",
|
||||||
"${declaringClass.name}#${method.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val methods = componentFactoryContext
|
val methods = componentFactoryContext
|
||||||
@@ -48,15 +50,15 @@ class ComponentAnnotationValidatorFactory : AgentBaseFactory() {
|
|||||||
.forEach { field ->
|
.forEach { field ->
|
||||||
val declaringClass = field.declaringClass
|
val declaringClass = field.declaringClass
|
||||||
if (!ReflectUtil.isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) {
|
if (!ReflectUtil.isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"@InjectModule 只能用于 AgentComponent 中: " +
|
"@InjectModule can only be declared on AgentComponent classes: ${declaringClass.name}#${field.name}",
|
||||||
"${declaringClass.name}#${field.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (AbstractAgentModule.Running::class.java.isAssignableFrom(field.type)) {
|
if (AbstractAgentModule.Running::class.java.isAssignableFrom(field.type)) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"@InjectModule 不可注入 AbstractAgentModule.Running 子类: " +
|
"@InjectModule cannot target AbstractAgentModule.Running subclasses: ${declaringClass.name}#${field.name} -> ${field.type.name}",
|
||||||
"${declaringClass.name}#${field.name} -> ${field.type.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component
|
package work.slhaf.partner.framework.agent.factory.component
|
||||||
|
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.Init
|
import work.slhaf.partner.framework.agent.factory.component.annotation.Init
|
||||||
import work.slhaf.partner.framework.agent.factory.component.exception.ModuleInitHookExecuteFailedException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentContext
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.methodSignature
|
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil.methodSignature
|
||||||
@@ -15,6 +15,8 @@ import java.lang.reflect.Method
|
|||||||
* 执行目标包括 modules 与 additionalComponents,按 `order` 升序执行。
|
* 执行目标包括 modules 与 additionalComponents,按 `order` 升序执行。
|
||||||
*/
|
*/
|
||||||
class ComponentInitHookExecutorFactory : AgentBaseFactory() {
|
class ComponentInitHookExecutorFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "component-init-hook-executor-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val initMethodsByDeclaringType = context.componentFactoryContext.initMethodsByDeclaringType
|
val initMethodsByDeclaringType = context.componentFactoryContext.initMethodsByDeclaringType
|
||||||
val targets = buildTargets(context.agentContext)
|
val targets = buildTargets(context.agentContext)
|
||||||
@@ -48,21 +50,19 @@ class ComponentInitHookExecutorFactory : AgentBaseFactory() {
|
|||||||
initMethods.forEach { method ->
|
initMethods.forEach { method ->
|
||||||
try {
|
try {
|
||||||
if (method.parameterCount > 0) {
|
if (method.parameterCount > 0) {
|
||||||
throw ModuleInitHookExecuteFailedException(
|
throw FactoryExecutionException(
|
||||||
"Init方法不支持参数: ${target::class.java.name}#${methodSignature(method)}"
|
"Init method must not declare parameters: ${target::class.java.name}#${methodSignature(method)}",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
method.isAccessible = true
|
method.isAccessible = true
|
||||||
method.invoke(target)
|
method.invoke(target)
|
||||||
} catch (e: ModuleInitHookExecuteFailedException) {
|
} catch (e: FactoryExecutionException) {
|
||||||
throw e
|
throw e
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw ModuleInitHookExecuteFailedException(
|
throw FactoryExecutionException(
|
||||||
"模块的init hook方法执行失败! 模块: ${target::class.java.simpleName} 方法签名: ${
|
"Failed to execute init hook: ${target::class.java.name}#${methodSignature(method)}",
|
||||||
methodSignature(
|
factoryName,
|
||||||
method
|
|
||||||
)
|
|
||||||
}",
|
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component
|
package work.slhaf.partner.framework.agent.factory.component
|
||||||
|
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.InjectModule
|
import work.slhaf.partner.framework.agent.factory.component.annotation.InjectModule
|
||||||
import work.slhaf.partner.framework.agent.factory.component.exception.ModuleInstanceGenerateFailedException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.context.ModuleContextData
|
import work.slhaf.partner.framework.agent.factory.context.ModuleContextData
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
@@ -19,6 +19,8 @@ import java.lang.reflect.Modifier
|
|||||||
* 当注入目标无匹配实例或存在多个匹配实例时抛出异常。
|
* 当注入目标无匹配实例或存在多个匹配实例时抛出异常。
|
||||||
*/
|
*/
|
||||||
class ComponentInjectorFactory : AgentBaseFactory() {
|
class ComponentInjectorFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "component-injector-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val agentContext = context.agentContext
|
val agentContext = context.agentContext
|
||||||
val moduleContextList = agentContext.modules.values.toList()
|
val moduleContextList = agentContext.modules.values.toList()
|
||||||
@@ -62,8 +64,9 @@ class ComponentInjectorFactory : AgentBaseFactory() {
|
|||||||
field.isAccessible = true
|
field.isAccessible = true
|
||||||
field.set(target, value)
|
field.set(target, value)
|
||||||
} catch (e: IllegalAccessException) {
|
} catch (e: IllegalAccessException) {
|
||||||
throw ModuleInstanceGenerateFailedException(
|
throw FactoryExecutionException(
|
||||||
"模块注入失败: ${target::class.java.name}#${field.name}",
|
"Failed to inject module dependency: ${target::class.java.name}#${field.name}",
|
||||||
|
factoryName,
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -73,13 +76,15 @@ class ComponentInjectorFactory : AgentBaseFactory() {
|
|||||||
private fun resolveInjectValue(field: Field, providers: List<Any>, targetClass: Class<*>): Any {
|
private fun resolveInjectValue(field: Field, providers: List<Any>, targetClass: Class<*>): Any {
|
||||||
val matched = providers.filter { field.type.isAssignableFrom(it::class.java) }
|
val matched = providers.filter { field.type.isAssignableFrom(it::class.java) }
|
||||||
if (matched.isEmpty()) {
|
if (matched.isEmpty()) {
|
||||||
throw ModuleInstanceGenerateFailedException(
|
throw FactoryExecutionException(
|
||||||
"模块注入失败, 未找到可注入实例: ${targetClass.name}#${field.name} -> ${field.type.name}"
|
"No injectable module instance found for: ${targetClass.name}#${field.name} -> ${field.type.name}",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (matched.size > 1) {
|
if (matched.size > 1) {
|
||||||
throw ModuleInstanceGenerateFailedException(
|
throw FactoryExecutionException(
|
||||||
"模块注入失败, 存在多个可注入实例: ${targetClass.name}#${field.name} -> ${field.type.name}"
|
"Multiple injectable module instances found for: ${targetClass.name}#${field.name} -> ${field.type.name}",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return matched.first()
|
return matched.first()
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package work.slhaf.partner.framework.agent.factory.component
|
|||||||
import com.alibaba.fastjson2.JSONArray
|
import com.alibaba.fastjson2.JSONArray
|
||||||
import com.alibaba.fastjson2.JSONObject
|
import com.alibaba.fastjson2.JSONObject
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule
|
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
||||||
import work.slhaf.partner.framework.agent.factory.component.exception.ModuleFactoryInitFailedException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentContext
|
||||||
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
import work.slhaf.partner.framework.agent.factory.context.AgentRegisterContext
|
||||||
import work.slhaf.partner.framework.agent.factory.context.ModuleContextData
|
import work.slhaf.partner.framework.agent.factory.context.ModuleContextData
|
||||||
@@ -25,6 +25,7 @@ import java.time.ZonedDateTime
|
|||||||
class ComponentRegisterFactory : AgentBaseFactory() {
|
class ComponentRegisterFactory : AgentBaseFactory() {
|
||||||
companion object {
|
companion object {
|
||||||
private val log = LoggerFactory.getLogger(ComponentRegisterFactory::class.java)
|
private val log = LoggerFactory.getLogger(ComponentRegisterFactory::class.java)
|
||||||
|
private const val FACTORY_NAME = "component-register-factory"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
@@ -40,7 +41,11 @@ class ComponentRegisterFactory : AgentBaseFactory() {
|
|||||||
constructor.isAccessible = true
|
constructor.isAccessible = true
|
||||||
constructor.newInstance()
|
constructor.newInstance()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw ModuleFactoryInitFailedException("AgentComponent 实例化失败: ${componentClass.name}", e)
|
throw FactoryExecutionException(
|
||||||
|
"Failed to instantiate AgentComponent: ${componentClass.name}",
|
||||||
|
FACTORY_NAME,
|
||||||
|
e
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentInstance is AbstractAgentModule) {
|
if (componentInstance is AbstractAgentModule) {
|
||||||
@@ -62,8 +67,9 @@ class ComponentRegisterFactory : AgentBaseFactory() {
|
|||||||
module: AbstractAgentModule
|
module: AbstractAgentModule
|
||||||
) {
|
) {
|
||||||
if (agentContext.modules.containsKey(module.moduleName)) {
|
if (agentContext.modules.containsKey(module.moduleName)) {
|
||||||
throw ModuleFactoryInitFailedException(
|
throw FactoryExecutionException(
|
||||||
"模块注册失败, 存在重复 moduleName: ${module.moduleName} (class=${componentClass.name})"
|
"Duplicate module name detected: ${module.moduleName} (class=${componentClass.name})",
|
||||||
|
FACTORY_NAME
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component.exception;
|
|
||||||
|
|
||||||
public class ModuleCheckException extends ModuleFactoryInitFailedException {
|
|
||||||
public ModuleCheckException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleCheckException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component.exception;
|
|
||||||
|
|
||||||
public class ModuleFactoryInitFailedException extends RuntimeException {
|
|
||||||
public ModuleFactoryInitFailedException(String message) {
|
|
||||||
super("ModuleFactory 执行失败: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleFactoryInitFailedException(String message, Throwable cause) {
|
|
||||||
super("ModuleFactory 执行失败: " + message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component.exception;
|
|
||||||
|
|
||||||
public class ModuleInitHookExecuteFailedException extends ModuleFactoryInitFailedException {
|
|
||||||
public ModuleInitHookExecuteFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleInitHookExecuteFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component.exception;
|
|
||||||
|
|
||||||
public class ModuleInstanceGenerateFailedException extends ModuleFactoryInitFailedException {
|
|
||||||
public ModuleInstanceGenerateFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleInstanceGenerateFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component.exception;
|
|
||||||
|
|
||||||
public class ModuleProxyGenerateFailedException extends ModuleFactoryInitFailedException {
|
|
||||||
public ModuleProxyGenerateFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleProxyGenerateFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.component.exception;
|
|
||||||
|
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentRuntimeException;
|
|
||||||
|
|
||||||
public class ProxiedModuleRunningException extends AgentRuntimeException {
|
|
||||||
public ProxiedModuleRunningException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProxiedModuleRunningException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
public class ConfigDirNotExistException extends ConfigFactoryInitFailedException {
|
|
||||||
public ConfigDirNotExistException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigDirNotExistException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentLaunchFailedException;
|
|
||||||
|
|
||||||
public class ConfigFactoryInitFailedException extends AgentLaunchFailedException {
|
|
||||||
public ConfigFactoryInitFailedException(String message, Throwable cause) {
|
|
||||||
super("AgentConfigLoader 执行失败: " + message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFactoryInitFailedException(String message) {
|
|
||||||
super("AgentConfigLoader 执行失败: " + message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentRuntimeException;
|
|
||||||
|
|
||||||
public class ConfigFactoryRuntimeException extends AgentRuntimeException {
|
|
||||||
public ConfigFactoryRuntimeException(String message, Throwable cause) {
|
|
||||||
super("ConfigFactory 运行出错: " + message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFactoryRuntimeException(String message) {
|
|
||||||
super("ConfigFactory 运行出错: " + message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
public class ConfigGenerateFailedException extends ConfigFactoryInitFailedException {
|
|
||||||
public ConfigGenerateFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigGenerateFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
public class ConfigNotExistException extends ConfigFactoryInitFailedException {
|
|
||||||
public ConfigNotExistException(String message, Throwable e) {
|
|
||||||
super(message, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigNotExistException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
public class ConfigUpdateFailedException extends ConfigFactoryRuntimeException {
|
|
||||||
public ConfigUpdateFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigUpdateFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
public class PromptDirNotExistException extends ConfigFactoryInitFailedException {
|
|
||||||
public PromptDirNotExistException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PromptDirNotExistException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.config.exception;
|
|
||||||
|
|
||||||
public class PromptNotExistException extends ConfigFactoryInitFailedException {
|
|
||||||
public PromptNotExistException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PromptNotExistException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ package work.slhaf.partner.framework.agent.factory.context
|
|||||||
import com.alibaba.fastjson2.JSONArray
|
import com.alibaba.fastjson2.JSONArray
|
||||||
import com.alibaba.fastjson2.JSONObject
|
import com.alibaba.fastjson2.JSONObject
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import work.slhaf.partner.framework.agent.exception.deprecated.AgentRunningFailedException
|
import work.slhaf.partner.framework.agent.exception.AgentRuntimeException
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
||||||
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule
|
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
||||||
@@ -150,7 +150,7 @@ object AgentContext {
|
|||||||
ShutdownHookDesc.Type.CAPABILITY -> instances.capability[clazz]
|
ShutdownHookDesc.Type.CAPABILITY -> instances.capability[clazz]
|
||||||
}
|
}
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
throw AgentRunningFailedException("Instance of type $type not found")
|
throw AgentRuntimeException("Instance of type $type not found")
|
||||||
}
|
}
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.context
|
package work.slhaf.partner.framework.agent.factory.context
|
||||||
|
|
||||||
|
import work.slhaf.partner.framework.agent.exception.FactoryExecutionException
|
||||||
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
import work.slhaf.partner.framework.agent.factory.AgentBaseFactory
|
||||||
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
import work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore
|
||||||
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
import work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent
|
||||||
import work.slhaf.partner.framework.agent.factory.component.exception.ModuleCheckException
|
|
||||||
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil
|
import work.slhaf.partner.framework.agent.factory.util.ReflectUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,6 +16,8 @@ import work.slhaf.partner.framework.agent.factory.util.ReflectUtil
|
|||||||
* 收集通过后,统一调用 `AgentContext.addShutdownHook` 注册。
|
* 收集通过后,统一调用 `AgentContext.addShutdownHook` 注册。
|
||||||
*/
|
*/
|
||||||
class ShutdownHookCollectorFactory : AgentBaseFactory() {
|
class ShutdownHookCollectorFactory : AgentBaseFactory() {
|
||||||
|
private val factoryName = "shutdown-hook-collector-factory"
|
||||||
|
|
||||||
override fun execute(context: AgentRegisterContext) {
|
override fun execute(context: AgentRegisterContext) {
|
||||||
val reflections = context.reflections
|
val reflections = context.reflections
|
||||||
val agentContext = context.agentContext
|
val agentContext = context.agentContext
|
||||||
@@ -29,23 +31,24 @@ class ShutdownHookCollectorFactory : AgentBaseFactory() {
|
|||||||
ReflectUtil.isAssignableFromAnnotation(declaringClass, CapabilityCore::class.java)
|
ReflectUtil.isAssignableFromAnnotation(declaringClass, CapabilityCore::class.java)
|
||||||
|
|
||||||
if (!isAgentComponentRelated && !isCapabilityCoreRelated) {
|
if (!isAgentComponentRelated && !isCapabilityCoreRelated) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"@Shutdown 仅能用于 AgentComponent/CapabilityCore 相关类: " +
|
"@Shutdown can only be declared on AgentComponent/CapabilityCore classes: ${declaringClass.name}#${method.name}",
|
||||||
"${declaringClass.name}#${method.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (method.parameterCount > 0) {
|
if (method.parameterCount > 0) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"@Shutdown 标注的方法不能包含形参: " +
|
"@Shutdown methods must not declare parameters: ${declaringClass.name}#${method.name}",
|
||||||
"${declaringClass.name}#${method.name}"
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val order = method.getAnnotation(Shutdown::class.java).order
|
val order = method.getAnnotation(Shutdown::class.java).order
|
||||||
val added = agentContext.addShutdownHook(method, order)
|
val added = agentContext.addShutdownHook(method, order)
|
||||||
if (!added) {
|
if (!added) {
|
||||||
throw ModuleCheckException(
|
throw FactoryExecutionException(
|
||||||
"ShutdownHook 收集失败: ${declaringClass.name}#${method.name}"
|
"Failed to collect shutdown hook: ${declaringClass.name}#${method.name}",
|
||||||
|
factoryName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.exception;
|
|
||||||
|
|
||||||
public class AgentRegisterFactoryFailedException extends RuntimeException {
|
|
||||||
public AgentRegisterFactoryFailedException(String message, Throwable cause) {
|
|
||||||
super("AgentRegisterFactory 执行失败: " + message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AgentRegisterFactoryFailedException(String message) {
|
|
||||||
super("AgentRegisterFactory 执行失败: " + message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package work.slhaf.partner.framework.agent.factory.exception;
|
|
||||||
|
|
||||||
public class ExternalModuleLoadFailedException extends AgentRegisterFactoryFailedException {
|
|
||||||
public ExternalModuleLoadFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExternalModuleLoadFailedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,11 +7,13 @@ import work.slhaf.partner.framework.agent.config.Config
|
|||||||
import work.slhaf.partner.framework.agent.config.ConfigDoc
|
import work.slhaf.partner.framework.agent.config.ConfigDoc
|
||||||
import work.slhaf.partner.framework.agent.config.ConfigRegistration
|
import work.slhaf.partner.framework.agent.config.ConfigRegistration
|
||||||
import work.slhaf.partner.framework.agent.config.Configurable
|
import work.slhaf.partner.framework.agent.config.Configurable
|
||||||
|
import work.slhaf.partner.framework.agent.exception.*
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegistryConfig>, AutoCloseable {
|
object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegistryConfig>, AutoCloseable {
|
||||||
|
private const val COMPONENT_NAME = "agent-gateway-registry"
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(AgentGatewayRegistry::class.java)
|
private val log = LoggerFactory.getLogger(AgentGatewayRegistry::class.java)
|
||||||
private val registryLock = ReentrantLock()
|
private val registryLock = ReentrantLock()
|
||||||
@@ -26,8 +28,11 @@ object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegis
|
|||||||
|
|
||||||
fun register(registration: AgentGatewayRegistration) = registryLock.withLock {
|
fun register(registration: AgentGatewayRegistration) = registryLock.withLock {
|
||||||
val previous = registrations.putIfAbsent(registration.channelName, registration)
|
val previous = registrations.putIfAbsent(registration.channelName, registration)
|
||||||
check(previous == null || previous === registration) {
|
checkAgentStartup(previous == null || previous === registration) {
|
||||||
"AgentGateway channel already registered: ${registration.channelName}"
|
AgentStartupException(
|
||||||
|
"AgentGateway channel already registered: ${registration.channelName}",
|
||||||
|
COMPONENT_NAME
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +45,13 @@ object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegis
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun init(config: AgentGatewayRegistryConfig, json: JSONObject?) = registryLock.withLock {
|
override fun init(config: AgentGatewayRegistryConfig, json: JSONObject?) = registryLock.withLock {
|
||||||
|
try {
|
||||||
applyConfig(config)
|
applyConfig(config)
|
||||||
|
} catch (e: GatewayRegistryException) {
|
||||||
|
throw GatewayStartupException(e.message ?: "Failed to apply gateway registry config", e.gatewayName, e)
|
||||||
|
} catch (e: GatewayException) {
|
||||||
|
throw GatewayStartupException(e.message ?: "Failed to apply gateway config", e.gatewayName, e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReload(config: AgentGatewayRegistryConfig, json: JSONObject?) = registryLock.withLock {
|
override fun onReload(config: AgentGatewayRegistryConfig, json: JSONObject?) = registryLock.withLock {
|
||||||
@@ -48,7 +59,10 @@ object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegis
|
|||||||
val defaultSnapshot = AgentRuntime.defaultResponseChannel()
|
val defaultSnapshot = AgentRuntime.defaultResponseChannel()
|
||||||
try {
|
try {
|
||||||
applyConfig(config)
|
applyConfig(config)
|
||||||
} catch (e: Exception) {
|
} catch (e: GatewayRegistryException) {
|
||||||
|
log.error("Error while reloading gateway config", e)
|
||||||
|
restoreSnapshot(runtimeSnapshot, defaultSnapshot)
|
||||||
|
} catch (e: GatewayException) {
|
||||||
log.error("Error while reloading gateway config", e)
|
log.error("Error while reloading gateway config", e)
|
||||||
restoreSnapshot(runtimeSnapshot, defaultSnapshot)
|
restoreSnapshot(runtimeSnapshot, defaultSnapshot)
|
||||||
}
|
}
|
||||||
@@ -69,20 +83,34 @@ object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegis
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun validateConfig(config: AgentGatewayRegistryConfig) {
|
private fun validateConfig(config: AgentGatewayRegistryConfig) {
|
||||||
require(config.defaultChannel.isNotBlank()) { "default_channel must not be blank" }
|
if (config.defaultChannel.isBlank()) {
|
||||||
require(config.channels.isNotEmpty()) { "channels must not be empty" }
|
throw GatewayRegistryException("default_channel must not be blank", COMPONENT_NAME)
|
||||||
|
}
|
||||||
|
if (config.channels.isEmpty()) {
|
||||||
|
throw GatewayRegistryException("channels must not be empty", COMPONENT_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
val channelNames = mutableSetOf<String>()
|
val channelNames = mutableSetOf<String>()
|
||||||
config.channels.forEach { channel ->
|
config.channels.forEach { channel ->
|
||||||
require(channel.channelName.isNotBlank()) { "channel_name must not be blank" }
|
if (channel.channelName.isBlank()) {
|
||||||
require(channelNames.add(channel.channelName)) { "Duplicated channel_name: ${channel.channelName}" }
|
throw GatewayRegistryException("channel_name must not be blank", COMPONENT_NAME)
|
||||||
require(registrations.containsKey(channel.channelName)) {
|
}
|
||||||
"AgentGateway channel is not registered: ${channel.channelName}"
|
if (!channelNames.add(channel.channelName)) {
|
||||||
|
throw GatewayRegistryException("Duplicate channel_name: ${channel.channelName}", channel.channelName)
|
||||||
|
}
|
||||||
|
if (!registrations.containsKey(channel.channelName)) {
|
||||||
|
throw GatewayRegistryException(
|
||||||
|
"AgentGateway channel is not registered: ${channel.channelName}",
|
||||||
|
channel.channelName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require(channelNames.contains(config.defaultChannel)) {
|
if (!channelNames.contains(config.defaultChannel)) {
|
||||||
"default_channel must exist in channels: ${config.defaultChannel}"
|
throw GatewayRegistryException(
|
||||||
|
"default_channel must exist in channels: ${config.defaultChannel}",
|
||||||
|
config.defaultChannel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +121,10 @@ object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegis
|
|||||||
|
|
||||||
configuredChannels.forEach { channelConfig ->
|
configuredChannels.forEach { channelConfig ->
|
||||||
val registration = registrations[channelConfig.channelName]
|
val registration = registrations[channelConfig.channelName]
|
||||||
?: error("AgentGateway channel is not registered: ${channelConfig.channelName}")
|
?: throw GatewayRegistryException(
|
||||||
|
"AgentGateway channel is not registered: ${channelConfig.channelName}",
|
||||||
|
channelConfig.channelName
|
||||||
|
)
|
||||||
val existing = runningChannels[channelConfig.channelName]
|
val existing = runningChannels[channelConfig.channelName]
|
||||||
if (existing != null && existing.registration === registration &&
|
if (existing != null && existing.registration === registration &&
|
||||||
registration.supportsHotReloadReuse(existing.params, channelConfig.params)
|
registration.supportsHotReloadReuse(existing.params, channelConfig.params)
|
||||||
@@ -129,7 +160,11 @@ object AgentGatewayRegistry : Configurable, ConfigRegistration<AgentGatewayRegis
|
|||||||
shutdownError
|
shutdownError
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
throw e
|
throw GatewayException(
|
||||||
|
"Failed to launch gateway channel: ${channelConfig.channelName}",
|
||||||
|
channelConfig.channelName,
|
||||||
|
e
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import work.slhaf.partner.framework.agent.config.Config
|
|||||||
import work.slhaf.partner.framework.agent.config.ConfigDoc
|
import work.slhaf.partner.framework.agent.config.ConfigDoc
|
||||||
import work.slhaf.partner.framework.agent.config.ConfigRegistration
|
import work.slhaf.partner.framework.agent.config.ConfigRegistration
|
||||||
import work.slhaf.partner.framework.agent.config.Configurable
|
import work.slhaf.partner.framework.agent.config.Configurable
|
||||||
|
import work.slhaf.partner.framework.agent.exception.ModelRegistryException
|
||||||
|
import work.slhaf.partner.framework.agent.exception.ModelRegistryStartupException
|
||||||
import work.slhaf.partner.framework.agent.model.ProviderConfig.ProviderType.OPENAI_COMPATIBLE
|
import work.slhaf.partner.framework.agent.model.ProviderConfig.ProviderType.OPENAI_COMPATIBLE
|
||||||
import work.slhaf.partner.framework.agent.model.provider.ModelProvider
|
import work.slhaf.partner.framework.agent.model.provider.ModelProvider
|
||||||
import work.slhaf.partner.framework.agent.model.provider.ProviderOverride
|
import work.slhaf.partner.framework.agent.model.provider.ProviderOverride
|
||||||
@@ -18,6 +20,7 @@ import kotlin.concurrent.withLock
|
|||||||
object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegistryConfig> {
|
object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegistryConfig> {
|
||||||
|
|
||||||
private const val DEFAULT_PROVIDER = "default"
|
private const val DEFAULT_PROVIDER = "default"
|
||||||
|
private const val COMPONENT_NAME = "model-runtime-registry"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础的 provider 提供商,可 fork 出新的 runtime provider,必须提供一个 default provider
|
* 基础的 provider 提供商,可 fork 出新的 runtime provider,必须提供一个 default provider
|
||||||
@@ -49,14 +52,29 @@ object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegis
|
|||||||
|
|
||||||
private fun forkProvider(config: RuntimeProviderConfig) {
|
private fun forkProvider(config: RuntimeProviderConfig) {
|
||||||
val provider = baseProvider[config.providerName]
|
val provider = baseProvider[config.providerName]
|
||||||
?: throw IllegalArgumentException("Provider ${config.providerName} not found")
|
?: throw runtimeModelException(
|
||||||
|
"Provider ${config.providerName} not found",
|
||||||
|
config.providerName,
|
||||||
|
config.modelKey,
|
||||||
|
config.override
|
||||||
|
)
|
||||||
val override = config.override
|
val override = config.override
|
||||||
|
|
||||||
|
try {
|
||||||
runtimeProvider[config.modelKey] = if (override != null) {
|
runtimeProvider[config.modelKey] = if (override != null) {
|
||||||
provider.fork(override)
|
provider.fork(override)
|
||||||
} else {
|
} else {
|
||||||
provider
|
provider
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw runtimeModelException(
|
||||||
|
"Failed to build runtime provider for model key ${config.modelKey}",
|
||||||
|
config.providerName,
|
||||||
|
config.modelKey,
|
||||||
|
override,
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun declare(): Map<Path, ConfigRegistration<out Config>> {
|
override fun declare(): Map<Path, ConfigRegistration<out Config>> {
|
||||||
@@ -66,8 +84,17 @@ object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegis
|
|||||||
override fun type(): Class<ModelRuntimeRegistryConfig> = ModelRuntimeRegistryConfig::class.java
|
override fun type(): Class<ModelRuntimeRegistryConfig> = ModelRuntimeRegistryConfig::class.java
|
||||||
|
|
||||||
override fun init(config: ModelRuntimeRegistryConfig, json: JSONObject?) = providerLock.withLock {
|
override fun init(config: ModelRuntimeRegistryConfig, json: JSONObject?) = providerLock.withLock {
|
||||||
config.providerConfigSet.forEach { registerProvider(it) }
|
try {
|
||||||
config.runtimeConfigSet.forEach { forkProvider(it) }
|
applyConfig(config)
|
||||||
|
} catch (e: ModelRegistryException) {
|
||||||
|
throw ModelRegistryStartupException(
|
||||||
|
e.message ?: "Failed to apply model runtime config",
|
||||||
|
e.providerName,
|
||||||
|
e.modelKey,
|
||||||
|
e.override,
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReload(config: ModelRuntimeRegistryConfig, json: JSONObject?) = providerLock.withLock {
|
override fun onReload(config: ModelRuntimeRegistryConfig, json: JSONObject?) = providerLock.withLock {
|
||||||
@@ -76,19 +103,33 @@ object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegis
|
|||||||
val runtimeProviderSnapshot = runtimeProvider.toMap()
|
val runtimeProviderSnapshot = runtimeProvider.toMap()
|
||||||
try {
|
try {
|
||||||
val providerSetJson = root.getJSONArray("providerConfigSet")
|
val providerSetJson = root.getJSONArray("providerConfigSet")
|
||||||
?: throw IllegalStateException("providerConfigSet is missing or not an array")
|
?: throw runtimeModelException("providerConfigSet is missing or not an array")
|
||||||
baseProvider.clear()
|
baseProvider.clear()
|
||||||
for (i in providerSetJson.indices) {
|
for (i in providerSetJson.indices) {
|
||||||
val providerJson = providerSetJson.getJSONObject(i)
|
val providerJson = providerSetJson.getJSONObject(i)
|
||||||
?: throw IllegalStateException("providerConfigSet[$i] is not an object")
|
?: throw runtimeModelException("providerConfigSet[$i] is not an object")
|
||||||
val typeText = providerJson.getString("type")
|
val typeText = providerJson.getString("type")
|
||||||
?: throw IllegalStateException("providerConfigSet[$i].type is missing")
|
?: throw runtimeModelException(
|
||||||
val providerType = ProviderConfig.ProviderType.valueOf(typeText.uppercase(getDefault()))
|
"providerConfigSet[$i].type is missing",
|
||||||
|
providerJson.getString("name") ?: COMPONENT_NAME
|
||||||
|
)
|
||||||
|
val providerType = try {
|
||||||
|
ProviderConfig.ProviderType.valueOf(typeText.uppercase(getDefault()))
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw runtimeModelException(
|
||||||
|
"Unsupported provider type: $typeText",
|
||||||
|
providerJson.getString("name") ?: COMPONENT_NAME,
|
||||||
|
cause = e
|
||||||
|
)
|
||||||
|
}
|
||||||
val concreteProviderConfig = when (providerType) {
|
val concreteProviderConfig = when (providerType) {
|
||||||
OPENAI_COMPATIBLE -> providerJson.toJavaObject(OpenAiCompatibleProviderConfig::class.java)
|
OPENAI_COMPATIBLE -> providerJson.toJavaObject(OpenAiCompatibleProviderConfig::class.java)
|
||||||
}
|
}
|
||||||
registerProvider(concreteProviderConfig)
|
registerProvider(concreteProviderConfig)
|
||||||
}
|
}
|
||||||
|
if (!baseProvider.containsKey(DEFAULT_PROVIDER)) {
|
||||||
|
throw runtimeModelException("Provider default not found", DEFAULT_PROVIDER)
|
||||||
|
}
|
||||||
runtimeProvider.clear()
|
runtimeProvider.clear()
|
||||||
config.runtimeConfigSet.forEach { forkProvider(it) }
|
config.runtimeConfigSet.forEach { forkProvider(it) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -114,6 +155,42 @@ object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegis
|
|||||||
), setOf()
|
), setOf()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyConfig(config: ModelRuntimeRegistryConfig) {
|
||||||
|
baseProvider.clear()
|
||||||
|
runtimeProvider.clear()
|
||||||
|
config.providerConfigSet.forEach { registerProvider(it) }
|
||||||
|
if (!baseProvider.containsKey(DEFAULT_PROVIDER)) {
|
||||||
|
throw runtimeModelException("Provider default not found", DEFAULT_PROVIDER)
|
||||||
|
}
|
||||||
|
config.runtimeConfigSet.forEach { forkProvider(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runtimeModelException(
|
||||||
|
message: String,
|
||||||
|
providerName: String = COMPONENT_NAME,
|
||||||
|
modelKey: String = COMPONENT_NAME,
|
||||||
|
override: ProviderOverride? = null,
|
||||||
|
cause: Throwable? = null
|
||||||
|
): ModelRegistryException {
|
||||||
|
return ModelRegistryException(
|
||||||
|
message,
|
||||||
|
providerName,
|
||||||
|
modelKey,
|
||||||
|
override?.toReportOverride() ?: emptyMap(),
|
||||||
|
cause
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ProviderOverride.toReportOverride(): Map<String, String> {
|
||||||
|
val result = linkedMapOf<String, String>()
|
||||||
|
result["model"] = model
|
||||||
|
temperature?.let { result["temperature"] = it.toString() }
|
||||||
|
topP?.let { result["topP"] = it.toString() }
|
||||||
|
maxTokens?.let { result["maxTokens"] = it.toString() }
|
||||||
|
extras?.forEach { (key, value) -> result["extra.$key"] = value?.toString() ?: "null" }
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ModelRuntimeRegistryConfig(
|
data class ModelRuntimeRegistryConfig(
|
||||||
|
|||||||
Reference in New Issue
Block a user