From 3eac52f4e267f14b11d4d988f501e81f5f8cd59d Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Mon, 27 Apr 2026 20:53:45 +0800 Subject: [PATCH] refactor(action): switch builtin actions to provider-driven self-registration --- .../action/builtin/BuiltinActionProvider.java | 2 +- .../action/builtin/BuiltinActionRegistry.java | 36 ++++++----------- .../BuiltinCapabilityActionProvider.java | 9 +++++ .../builtin/BuiltinCommandActionProvider.java | 12 ++++++ .../builtin/BuiltinDynamicActionProvider.java | 8 ++++ .../BuiltinInterventionActionProvider.java | 9 +++++ .../builtin/BuiltinActionRegistryTest.java | 40 +++++++++++++++---- 7 files changed, 83 insertions(+), 33 deletions(-) diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionProvider.java b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionProvider.java index e5754b65..7a8348d1 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionProvider.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionProvider.java @@ -2,7 +2,7 @@ package work.slhaf.partner.module.action.builtin; import java.util.List; -interface BuiltinActionProvider { +public interface BuiltinActionProvider { List provideBuiltinActions(); String createActionKey(String actionName); diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistry.java b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistry.java index da5b07de..8e836ce6 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistry.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistry.java @@ -9,7 +9,6 @@ import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCa import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule; import work.slhaf.partner.framework.agent.factory.component.annotation.Init; -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -26,32 +25,26 @@ public class BuiltinActionRegistry extends AbstractAgentModule.Standalone { @Init public void init() { - definitions.clear(); - for (BuiltinActionDefinition definition : buildDefaultActionDefinitions()) { - definitions.put(definition.actionKey(), definition); - } - actionCapability.registerMetaActions(exportMetaActionInfos()); actionCapability.runnerClient().setBuiltinActionRegistry(this); } - protected List buildDefaultActionDefinitions() { - List builtinActionDefinitions = new ArrayList<>(); - BuiltinActionProvider commandActionProvider = new BuiltinCommandActionProvider(); - BuiltinActionProvider capabilityActionProvider = new BuiltinCapabilityActionProvider(); - BuiltinActionProvider interventionActionProvider = new BuiltinInterventionActionProvider(); - BuiltinActionProvider dynamicActionProvider = new BuiltinDynamicActionProvider(); - - builtinActionDefinitions.addAll(commandActionProvider.provideBuiltinActions()); - builtinActionDefinitions.addAll(capabilityActionProvider.provideBuiltinActions()); - builtinActionDefinitions.addAll(interventionActionProvider.provideBuiltinActions()); - builtinActionDefinitions.addAll(dynamicActionProvider.provideBuiltinActions()); - - return builtinActionDefinitions; + public void register(BuiltinActionProvider provider) { + List builtinActionDefinitions = provider.provideBuiltinActions(); + if (builtinActionDefinitions == null || builtinActionDefinitions.isEmpty()) { + return; + } + Map metaActionInfos = new LinkedHashMap<>(); + for (BuiltinActionDefinition definition : builtinActionDefinitions) { + definitions.put(definition.actionKey(), definition); + metaActionInfos.put(definition.actionKey(), definition.metaActionInfo()); + } + actionCapability.registerMetaActions(metaActionInfos); } public void defineBuiltinAction(String name, MetaActionInfo metaActionInfo, Function, String> invoker) { BuiltinActionDefinition definition = new BuiltinActionDefinition(BUILTIN_LOCATION + "::" + name, metaActionInfo, invoker); definitions.put(definition.actionKey(), definition); + actionCapability.registerMetaActions(Map.of(definition.actionKey(), definition.metaActionInfo())); } public String call(@NonNull String actionKey, @NonNull Map params) { @@ -70,11 +63,6 @@ public class BuiltinActionRegistry extends AbstractAgentModule.Standalone { return result; } - private Map exportMetaActionInfos() { - Map metaActions = new LinkedHashMap<>(); - definitions.forEach((key, value) -> metaActions.put(key, value.metaActionInfo())); - return metaActions; - } public record BuiltinActionDefinition( String actionKey, diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCapabilityActionProvider.java b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCapabilityActionProvider.java index 1b50e75d..55ae3bfd 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCapabilityActionProvider.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCapabilityActionProvider.java @@ -14,6 +14,8 @@ import work.slhaf.partner.core.memory.pojo.MemorySlice; import work.slhaf.partner.core.memory.pojo.MemoryUnit; import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability; 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.InjectModule; import work.slhaf.partner.framework.agent.support.Result; import java.util.*; @@ -32,6 +34,13 @@ class BuiltinCapabilityActionProvider implements BuiltinActionProvider { private CognitionCapability cognitionCapability; @InjectCapability private MemoryCapability memoryCapability; + @InjectModule + private BuiltinActionRegistry builtinActionRegistry; + + @Init + public void init() { + builtinActionRegistry.register(this); + } @Override public List provideBuiltinActions() { diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCommandActionProvider.java b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCommandActionProvider.java index 1ed64aad..b729bbcc 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCommandActionProvider.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinCommandActionProvider.java @@ -6,6 +6,9 @@ import work.slhaf.partner.core.action.entity.MetaActionInfo; import work.slhaf.partner.core.action.runner.execution.CommandExecutionService; import work.slhaf.partner.core.action.runner.policy.ExecutionPolicyRegistry; import work.slhaf.partner.core.action.runner.policy.WrappedLaunchSpec; +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.InjectModule; import java.io.IOException; import java.io.RandomAccessFile; @@ -21,6 +24,7 @@ import java.util.function.Function; import static work.slhaf.partner.core.action.ActionCore.BUILTIN_LOCATION; +@AgentComponent class BuiltinCommandActionProvider implements BuiltinActionProvider { private static final String COMMAND_LOCATION = BUILTIN_LOCATION + "::" + "command"; @@ -38,6 +42,14 @@ class BuiltinCommandActionProvider implements BuiltinActionProvider { private final ConcurrentHashMap commandHandles = new ConcurrentHashMap<>(); private final CommandExecutionService commandExecutionService = CommandExecutionService.INSTANCE; + @InjectModule + private BuiltinActionRegistry builtinActionRegistry; + + @Init + public void init() { + builtinActionRegistry.register(this); + } + private Map commandParams() { Map params = new LinkedHashMap<>(); params.put("arg", param("required", "string", "Command executable name or path.")); diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinDynamicActionProvider.java b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinDynamicActionProvider.java index a2b7a242..02bec2ab 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinDynamicActionProvider.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinDynamicActionProvider.java @@ -7,6 +7,7 @@ import work.slhaf.partner.core.action.ActionCapability; import work.slhaf.partner.core.action.entity.*; import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability; 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.InjectModule; import work.slhaf.partner.module.action.scheduler.ActionScheduler; @@ -29,6 +30,13 @@ class BuiltinDynamicActionProvider implements BuiltinActionProvider { private ActionCapability actionCapability; @InjectModule private ActionScheduler actionScheduler; + @InjectModule + private BuiltinActionRegistry builtinActionRegistry; + + @Init + public void init() { + builtinActionRegistry.register(this); + } @Override public List provideBuiltinActions() { diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinInterventionActionProvider.java b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinInterventionActionProvider.java index 0db68c68..56b9c3c4 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinInterventionActionProvider.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/action/builtin/BuiltinInterventionActionProvider.java @@ -17,6 +17,8 @@ import work.slhaf.partner.framework.agent.exception.AgentRuntimeException; import work.slhaf.partner.framework.agent.exception.ExceptionReporterHandler; import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability; 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.InjectModule; import work.slhaf.partner.framework.agent.support.Result; import java.util.*; @@ -35,6 +37,13 @@ class BuiltinInterventionActionProvider implements BuiltinActionProvider { private ActionCapability actionCapability; @InjectCapability private CognitionCapability cognitionCapability; + @InjectModule + private BuiltinActionRegistry builtinActionRegistry; + + @Init + public void init() { + builtinActionRegistry.register(this); + } @Override public List provideBuiltinActions() { diff --git a/Partner-Core/src/test/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistryTest.java b/Partner-Core/src/test/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistryTest.java index 56c2487d..2b46af56 100644 --- a/Partner-Core/src/test/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistryTest.java +++ b/Partner-Core/src/test/java/work/slhaf/partner/module/action/builtin/BuiltinActionRegistryTest.java @@ -52,29 +52,51 @@ class BuiltinActionRegistryTest { } @Test - void testInitRegistersMetaActionsAndMountsRunner() throws Exception { + void testInitMountsRunner() throws Exception { ActionCapability actionCapability = mock(ActionCapability.class); RunnerClient runnerClient = mock(RunnerClient.class); when(actionCapability.runnerClient()).thenReturn(runnerClient); - BuiltinActionRegistry registry = spy(new BuiltinActionRegistry()); - doReturn(List.of( - buildDefinition("echo", buildMetaActionInfo("echo"), params -> params.get("value").toString()) - )).when(registry).buildDefaultActionDefinitions(); + BuiltinActionRegistry registry = new BuiltinActionRegistry(); injectActionCapability(registry, actionCapability); registry.init(); + verify(runnerClient).setBuiltinActionRegistry(registry); + } + + @Test + void testRegisterProviderRegistersDefinitionsAndMetaActions() throws Exception { + ActionCapability actionCapability = mock(ActionCapability.class); + BuiltinActionRegistry registry = new BuiltinActionRegistry(); + injectActionCapability(registry, actionCapability); + + BuiltinActionProvider provider = new BuiltinActionProvider() { + @Override + public List provideBuiltinActions() { + return List.of(buildDefinition("echo", buildMetaActionInfo("echo"), params -> params.get("value").toString())); + } + + @Override + public String createActionKey(String actionName) { + return BUILTIN_LOCATION + "::" + actionName; + } + }; + + registry.register(provider); + verify(actionCapability).registerMetaActions(argThat(metaActions -> metaActions.containsKey("builtin::echo") && "echo".equals(metaActions.get("builtin::echo").getDescription()) )); - verify(runnerClient).setBuiltinActionRegistry(registry); + Assertions.assertEquals("hello", registry.call("builtin::echo", Map.of("value", "hello"))); } @Test - void testCallReturnsStringifiedResults() { + void testCallReturnsStringifiedResults() throws Exception { + ActionCapability actionCapability = mock(ActionCapability.class); BuiltinActionRegistry registry = new BuiltinActionRegistry(); + injectActionCapability(registry, actionCapability); registry.defineBuiltinAction("echo", buildMetaActionInfo("echo"), params -> params.get("value").toString()); registry.defineBuiltinAction("json", buildMetaActionInfo("json"), params -> Map.of("ok", true).toString()); registry.defineBuiltinAction("nil", buildMetaActionInfo("nil"), params -> null); @@ -91,8 +113,10 @@ class BuiltinActionRegistryTest { } @Test - void testCallPropagatesInvokerFailure() { + void testCallPropagatesInvokerFailure() throws Exception { + ActionCapability actionCapability = mock(ActionCapability.class); BuiltinActionRegistry registry = new BuiltinActionRegistry(); + injectActionCapability(registry, actionCapability); registry.defineBuiltinAction("boom", buildMetaActionInfo("boom"), params -> { throw new IllegalStateException("boom"); });