From cdea8d63229da895ce40929559b2ab35a2fb7d3d Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Sun, 8 Feb 2026 16:27:44 +0800 Subject: [PATCH] refactor(ActionData): migrate to Kotlin sealed class and data classes, update planner/scheduler usage --- .../partner/core/action/entity/ActionData.kt | 105 ++++++++++++++---- .../action/entity/ImmediateActionData.java | 12 -- .../action/entity/ScheduledActionData.java | 44 -------- .../dispatcher/scheduler/ActionScheduler.kt | 11 +- .../modules/action/planner/ActionPlanner.java | 35 +++--- .../evaluator/entity/EvaluatorResult.java | 4 + .../executor/ActionExecutorTest.java | 19 ++-- 7 files changed, 122 insertions(+), 108 deletions(-) delete mode 100644 Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ImmediateActionData.java delete mode 100644 Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ScheduledActionData.java diff --git a/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ActionData.kt b/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ActionData.kt index 5494a14b..2260fbc5 100644 --- a/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ActionData.kt +++ b/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ActionData.kt @@ -1,80 +1,143 @@ -package work.slhaf.partner.core.action.entity; +package work.slhaf.partner.core.action.entity -import lombok.Data; -import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction +import java.time.ZonedDateTime +import java.util.* /** * 行动模块传递的行动数据,包含行动uuid、倾向、状态、行动链、结果、发起原因、行动描述等信息。 */ -@Data -public abstract class ActionData { +sealed class ActionData { /** * 行动ID */ - protected String uuid; + val uuid: String = UUID.randomUUID().toString() + /** * 行动倾向 */ - protected String tendency; + abstract val tendency: String /** * 行动状态 */ - protected ActionStatus status; + var status: ActionStatus = ActionStatus.PREPARE + /** * 行动链 */ - protected Map> actionChain; + abstract val actionChain: MutableMap> + /** * 行动阶段(当前阶段) */ - protected int executingStage; + var executingStage: Int = 0 + /** * 行动结果 */ - protected String result; - protected Map> history = new HashMap<>(); + lateinit var result: String + + val history: MutableMap> = mutableMapOf() + /** * 修复上下文 */ - protected Map> additionalContext; + val additionalContext: MutableMap> = mutableMapOf() + /** * 行动原因 */ - protected String reason; + abstract val reason: String + /** * 行动描述 */ - protected String description; + abstract val description: String + /** * 行动来源 */ - protected String source; + abstract val source: String - public enum ActionStatus { + enum class ActionStatus { /** * 执行成功 */ SUCCESS, + /** * 执行失败 */ FAILED, + /** * 执行中 */ EXECUTING, + /** * 暂时中断 */ INTERRUPTED, + /** * 预备执行 */ PREPARE } } + +/** + * 计划行动数据类,继承自{@link ActionData},扩展了属性{@link ScheduledActionData#type}和{@link ScheduledActionData#scheduleContent},用于标识计划类型(单次还是周期性任务)和计划内容 + */ +data class ScheduledActionData( + override val tendency: String, + override val actionChain: MutableMap>, + override val reason: String, + override val description: String, + override val source: String, + val scheduleType: ScheduleType, + val scheduleContent: String, +) : ActionData() { + + val scheduleHistories = ArrayList() + + fun recordAndReset() { + val newHistory = ScheduleHistory(ZonedDateTime.now(), result, history.toMap()) + scheduleHistories.add(newHistory) + + additionalContext.clear() + executingStage = 0 + for (entry in actionChain) { + for (action in entry.value) { + action.params.clear() + action.result = MetaAction.Result() + } + } + + status = ActionStatus.PREPARE + } + + enum class ScheduleType { + CYCLE, + ONCE + } + + data class ScheduleHistory( + val endTime: ZonedDateTime, + val result: String, + val history: Map> + ) +} + +/** + * 即时行动数据类 + */ +data class ImmediateActionData( + override val tendency: String, + override val actionChain: MutableMap>, + override val reason: String, + override val description: String, + override val source: String, +) : ActionData() diff --git a/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ImmediateActionData.java b/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ImmediateActionData.java deleted file mode 100644 index 388ea0b1..00000000 --- a/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ImmediateActionData.java +++ /dev/null @@ -1,12 +0,0 @@ -package work.slhaf.partner.core.action.entity; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 即时行动数据类,继承自{@link ActionData} - */ -@EqualsAndHashCode(callSuper = true) -@Data -public class ImmediateActionData extends ActionData { -} diff --git a/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ScheduledActionData.java b/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ScheduledActionData.java deleted file mode 100644 index 09bd04bf..00000000 --- a/Partner-Main/src/main/java/work/slhaf/partner/core/action/entity/ScheduledActionData.java +++ /dev/null @@ -1,44 +0,0 @@ -package work.slhaf.partner.core.action.entity; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction; - -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 计划行动数据类,继承自{@link ActionData},扩展了属性{@link ScheduledActionData#type}和{@link ScheduledActionData#scheduleContent},用于标识计划类型(单次还是周期性任务)和计划内容 - */ -@EqualsAndHashCode(callSuper = true) -@Data -public class ScheduledActionData extends ActionData { - private ScheduledType type; - private String scheduleContent; //如果为周期,则对应cron表达式,如果为一次性,则对应为ZonedDateTime字符串 - private List scheduledHistories = new ArrayList<>(); - - public void recordAndReset() { - this.scheduledHistories.add(new ScheduledHistory(ZonedDateTime.now(), this.result, Map.copyOf(this.history))); - - // 清理执行时内容 - this.additionalContext.clear(); - this.executingStage = 0; - this.getActionChain().forEach((stage, actions) -> { - for (MetaAction action : actions) { - action.getParams().clear(); - action.setResult(new MetaAction.Result()); - } - }); - - this.setStatus(ActionStatus.PREPARE); - } - - public enum ScheduledType { - CYCLE, ONCE - } - - private record ScheduledHistory(ZonedDateTime endTime, String result, Map> history) { - } -} diff --git a/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/dispatcher/scheduler/ActionScheduler.kt b/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/dispatcher/scheduler/ActionScheduler.kt index 9f211e64..c68dc002 100644 --- a/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/dispatcher/scheduler/ActionScheduler.kt +++ b/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/dispatcher/scheduler/ActionScheduler.kt @@ -90,7 +90,7 @@ class ActionScheduler : AgentRunningSubModule, Void>() } val parseToZonedDateTime = parseToZonedDateTime( - actionData.type, + actionData.scheduleType, actionData.scheduleContent, ZonedDateTime.now() ) ?: run { @@ -226,7 +226,7 @@ class ActionScheduler : AgentRunningSubModule, Void>() for (actionData in primaryActions) { val latestExecutingTime = parseToZonedDateTime( - actionData.type, + actionData.scheduleType, actionData.scheduleContent, now ) ?: run { @@ -250,12 +250,13 @@ class ActionScheduler : AgentRunningSubModule, Void>() } private fun parseToZonedDateTime( - scheduleType: ScheduledActionData.ScheduledType, + scheduleType: ScheduledActionData.ScheduleType, scheduleContent: String, now: ZonedDateTime ): ZonedDateTime? { return when (scheduleType) { - ScheduledActionData.ScheduledType.CYCLE -> { + ScheduledActionData.ScheduleType.CYCLE + -> { val cron = try { cronParser.parse(scheduleContent).validate() } catch (_: Exception) { @@ -265,7 +266,7 @@ class ActionScheduler : AgentRunningSubModule, Void>() executionTime.nextExecution(now).getOrNull() } - ScheduledActionData.ScheduledType.ONCE -> { + ScheduledActionData.ScheduleType.ONCE -> { val executionTime = try { ZonedDateTime.parse(scheduleContent) } catch (_: Exception) { diff --git a/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java b/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java index 21fc04d9..4456406a 100644 --- a/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java +++ b/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java @@ -153,7 +153,7 @@ public class ActionPlanner extends PreRunningModule { private void putActionData(List evaluatorResults, PartnerRunningFlowContext context) { for (EvaluatorResult evaluatorResult : evaluatorResults) { - ActionData actionData = assemblyHelper.buildActionData(evaluatorResult); + ActionData actionData = assemblyHelper.buildActionData(evaluatorResult, context.getUserId()); if (evaluatorResult.isNeedConfirm()) { actionCapability.putPendingActions(context.getUserId(), actionData); } else { @@ -231,24 +231,25 @@ public class ActionPlanner extends PreRunningModule { return input; } - private ActionData buildActionData(EvaluatorResult evaluatorResult) { + private ActionData buildActionData(EvaluatorResult evaluatorResult, String userId) { Map> actionChain = getActionChain(evaluatorResult); return switch (evaluatorResult.getType()) { - case PLANNING -> { - ScheduledActionData actionInfo = new ScheduledActionData(); - actionInfo.setActionChain(actionChain); - actionInfo.setScheduleContent(evaluatorResult.getScheduleContent()); - actionInfo.setStatus(ActionData.ActionStatus.PREPARE); - actionInfo.setUuid(UUID.randomUUID().toString()); - yield actionInfo; - } - case IMMEDIATE -> { - ImmediateActionData actionInfo = new ImmediateActionData(); - actionInfo.setActionChain(actionChain); - actionInfo.setStatus(ActionData.ActionStatus.PREPARE); - actionInfo.setUuid(UUID.randomUUID().toString()); - yield actionInfo; - } + case PLANNING -> new ScheduledActionData( + evaluatorResult.getTendency(), + actionChain, + evaluatorResult.getReason(), + evaluatorResult.getDescription(), + userId, + evaluatorResult.getScheduleType(), + evaluatorResult.getScheduleContent() + ); + case IMMEDIATE -> new ImmediateActionData( + evaluatorResult.getTendency(), + actionChain, + evaluatorResult.getReason(), + evaluatorResult.getDescription(), + userId + ); }; } diff --git a/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java b/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java index 1db2a03c..f6cf7c01 100644 --- a/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java +++ b/Partner-Main/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java @@ -1,6 +1,7 @@ package work.slhaf.partner.module.modules.action.planner.evaluator.entity; import lombok.Data; +import work.slhaf.partner.core.action.entity.ScheduledActionData; import java.util.List; import java.util.Map; @@ -11,8 +12,11 @@ public class EvaluatorResult { private boolean needConfirm; private ActionType type; private String scheduleContent; + private ScheduledActionData.ScheduleType scheduleType; private Map> primaryActionChain; private String tendency; + private String reason; + private String description; public enum ActionType { IMMEDIATE, PLANNING diff --git a/Partner-Main/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionExecutorTest.java b/Partner-Main/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionExecutorTest.java index 262dea16..a2f9441d 100644 --- a/Partner-Main/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionExecutorTest.java +++ b/Partner-Main/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionExecutorTest.java @@ -1,6 +1,7 @@ package work.slhaf.partner.module.modules.action.dispatcher.executor; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -373,15 +374,15 @@ class ActionExecutorTest { } private ImmediateActionData buildActionData(Map> actionChain) { - ImmediateActionData actionData = new ImmediateActionData(); - actionData.setStatus(ActionData.ActionStatus.PREPARE); - actionData.setActionChain(actionChain); - actionData.setAdditionalContext(initAdditionalContext(actionChain)); - actionData.setReason("reason"); - actionData.setDescription("desc"); - actionData.setSource("source"); - actionData.setTendency("tendency"); - return actionData; + val immediateActionData = new ImmediateActionData( + "tendency", + actionChain, + "reason", + "desc", + "source" + ); + immediateActionData.getAdditionalContext().putAll(initAdditionalContext(actionChain)); + return immediateActionData; } private Map> singleStageChain(boolean io) {