mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
refactor(ActionData): migrate to Kotlin sealed class and data classes, update planner/scheduler usage
This commit is contained in:
@@ -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<Integer, List<MetaAction>> actionChain;
|
||||
abstract val actionChain: MutableMap<Int, MutableList<MetaAction>>
|
||||
|
||||
/**
|
||||
* 行动阶段(当前阶段)
|
||||
*/
|
||||
protected int executingStage;
|
||||
var executingStage: Int = 0
|
||||
|
||||
/**
|
||||
* 行动结果
|
||||
*/
|
||||
protected String result;
|
||||
protected Map<Integer, List<HistoryAction>> history = new HashMap<>();
|
||||
lateinit var result: String
|
||||
|
||||
val history: MutableMap<Int, MutableList<HistoryAction>> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* 修复上下文
|
||||
*/
|
||||
protected Map<Integer, List<String>> additionalContext;
|
||||
val additionalContext: MutableMap<Int, MutableList<String>> = 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<Int, MutableList<MetaAction>>,
|
||||
override val reason: String,
|
||||
override val description: String,
|
||||
override val source: String,
|
||||
val scheduleType: ScheduleType,
|
||||
val scheduleContent: String,
|
||||
) : ActionData() {
|
||||
|
||||
val scheduleHistories = ArrayList<ScheduleHistory>()
|
||||
|
||||
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<Int, List<HistoryAction>>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 即时行动数据类
|
||||
*/
|
||||
data class ImmediateActionData(
|
||||
override val tendency: String,
|
||||
override val actionChain: MutableMap<Int, MutableList<MetaAction>>,
|
||||
override val reason: String,
|
||||
override val description: String,
|
||||
override val source: String,
|
||||
) : ActionData()
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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<ScheduledHistory> 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<Integer, List<HistoryAction>> history) {
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, Void>()
|
||||
}
|
||||
|
||||
val parseToZonedDateTime = parseToZonedDateTime(
|
||||
actionData.type,
|
||||
actionData.scheduleType,
|
||||
actionData.scheduleContent,
|
||||
ZonedDateTime.now()
|
||||
) ?: run {
|
||||
@@ -226,7 +226,7 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, Void>()
|
||||
for (actionData in primaryActions) {
|
||||
val latestExecutingTime =
|
||||
parseToZonedDateTime(
|
||||
actionData.type,
|
||||
actionData.scheduleType,
|
||||
actionData.scheduleContent,
|
||||
now
|
||||
) ?: run {
|
||||
@@ -250,12 +250,13 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, 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<Set<ScheduledActionData>, Void>()
|
||||
executionTime.nextExecution(now).getOrNull()
|
||||
}
|
||||
|
||||
ScheduledActionData.ScheduledType.ONCE -> {
|
||||
ScheduledActionData.ScheduleType.ONCE -> {
|
||||
val executionTime = try {
|
||||
ZonedDateTime.parse(scheduleContent)
|
||||
} catch (_: Exception) {
|
||||
|
||||
@@ -153,7 +153,7 @@ public class ActionPlanner extends PreRunningModule {
|
||||
|
||||
private void putActionData(List<EvaluatorResult> 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<Integer, List<MetaAction>> 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
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Integer, List<String>> primaryActionChain;
|
||||
private String tendency;
|
||||
private String reason;
|
||||
private String description;
|
||||
|
||||
public enum ActionType {
|
||||
IMMEDIATE, PLANNING
|
||||
|
||||
@@ -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<Integer, List<MetaAction>> 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<Integer, List<MetaAction>> singleStageChain(boolean io) {
|
||||
|
||||
Reference in New Issue
Block a user