From 7879836b91709a4784bc59ce2c53ac719dbededd Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Tue, 24 Mar 2026 22:28:42 +0800 Subject: [PATCH] refactor(action): remove the explicit PendingAction control flow and assume the confirmation semantics through a short-term, fast-decaying ContextBlock belonging to the ACTION domain. --- .../partner/core/action/ActionCapability.java | 18 +- .../slhaf/partner/core/action/ActionCore.java | 162 +----------- .../action/entity/PendingActionRecord.java | 39 --- .../modules/action/planner/ActionPlanner.java | 241 ++++++++---------- .../planner/confirmer/ActionConfirmer.java | 124 --------- .../confirmer/entity/ConfirmerInput.java | 14 - .../confirmer/entity/ConfirmerResult.java | 11 - .../confirmer/entity/PendingDecisionItem.java | 15 -- .../planner/evaluator/ActionEvaluator.java | 6 +- .../evaluator/entity/EvaluatorResult.java | 7 + .../planner/extractor/ActionExtractor.java | 7 +- 11 files changed, 128 insertions(+), 516 deletions(-) delete mode 100644 Partner-Core/src/main/java/work/slhaf/partner/core/action/entity/PendingActionRecord.java delete mode 100644 Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/ActionConfirmer.java delete mode 100644 Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerInput.java delete mode 100644 Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerResult.java delete mode 100644 Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/PendingDecisionItem.java diff --git a/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCapability.java b/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCapability.java index aa36ef71..379cd87f 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCapability.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCapability.java @@ -3,7 +3,9 @@ package work.slhaf.partner.core.action; import lombok.NonNull; import org.jetbrains.annotations.Nullable; import work.slhaf.partner.api.agent.factory.capability.annotation.Capability; -import work.slhaf.partner.core.action.entity.*; +import work.slhaf.partner.core.action.entity.ExecutableAction; +import work.slhaf.partner.core.action.entity.MetaAction; +import work.slhaf.partner.core.action.entity.MetaActionInfo; import work.slhaf.partner.core.action.entity.cache.CacheAdjustData; import work.slhaf.partner.core.action.entity.intervention.MetaIntervention; import work.slhaf.partner.core.action.runner.RunnerClient; @@ -20,20 +22,6 @@ public interface ActionCapability { Set listActions(@Nullable ExecutableAction.Status status, @Nullable String source); - PendingActionRecord createPendingAction(String userId, ExecutableAction executableAction, long ttlMillis, long reminderBeforeMillis); - - List listActivePendingActions(String userId); - - PendingActionRecord resolvePendingDecision(String userId, String pendingId, PendingActionRecord.Decision decision, String reason); - - boolean markPendingReminded(String pendingId); - - PendingActionRecord expirePendingIfWaiting(String pendingId); - - void bindPendingLifecycleActions(String pendingId, StateAction reminderAction, StateAction expireAction); - - void cancelPendingLifecycleActions(String pendingId); - List selectTendencyCache(String input); void updateTendencyCache(CacheAdjustData data); diff --git a/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCore.java b/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCore.java index bd76504c..7e01989e 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCore.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/core/action/ActionCore.java @@ -8,7 +8,9 @@ import work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityCore import work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityMethod; import work.slhaf.partner.common.vector.VectorClient; import work.slhaf.partner.core.PartnerCore; -import work.slhaf.partner.core.action.entity.*; +import work.slhaf.partner.core.action.entity.ExecutableAction; +import work.slhaf.partner.core.action.entity.MetaAction; +import work.slhaf.partner.core.action.entity.MetaActionInfo; import work.slhaf.partner.core.action.entity.cache.ActionCacheData; import work.slhaf.partner.core.action.entity.cache.CacheAdjustData; import work.slhaf.partner.core.action.entity.cache.CacheAdjustMetaData; @@ -48,11 +50,6 @@ public class ActionCore extends PartnerCore { * 持久行动池 */ private CopyOnWriteArraySet actionPool = new CopyOnWriteArraySet<>(); - /** - * 待确认任务,以userId区分不同用户,因为需要跨请求确认 - */ - private final HashMap> pendingActions = new HashMap<>(); - private final HashMap pendingLifecycleActions = new HashMap<>(); /** * 语义缓存与行为倾向映射 */ @@ -88,132 +85,6 @@ public class ActionCore extends PartnerCore { .collect(Collectors.toSet()); } - @CapabilityMethod - public synchronized PendingActionRecord createPendingAction(String userId, ExecutableAction executableAction, - long ttlMillis, long reminderBeforeMillis) { - long now = System.currentTimeMillis(); - long safeTtl = Math.max(ttlMillis, 1000L); - long safeReminderBefore = Math.max(0L, Math.min(reminderBeforeMillis, safeTtl - 1000L)); - - PendingActionRecord record = new PendingActionRecord(); - record.setUserId(userId); - record.setExecutableAction(executableAction); - record.setCreatedAt(now); - record.setExpireAt(now + safeTtl); - record.setRemindAt(record.getExpireAt() - safeReminderBefore); - record.setStatus(PendingActionRecord.Status.WAITING_CONFIRM); - - pendingActions.computeIfAbsent(userId, k -> new ArrayList<>()).add(record); - return record; - } - - @CapabilityMethod - public synchronized List listActivePendingActions(String userId) { - List records = pendingActions.get(userId); - if (records == null || records.isEmpty()) { - return List.of(); - } - return records.stream() - .filter(record -> record.getStatus() == PendingActionRecord.Status.WAITING_CONFIRM - || record.getStatus() == PendingActionRecord.Status.REMINDER_SENT) - .toList(); - } - - @CapabilityMethod - public synchronized PendingActionRecord resolvePendingDecision(String userId, String pendingId, - PendingActionRecord.Decision decision, String reason) { - PendingActionRecord record = findPendingByUserAndId(userId, pendingId); - if (record == null) { - return null; - } - PendingActionRecord.Status status = record.getStatus(); - boolean active = status == PendingActionRecord.Status.WAITING_CONFIRM - || status == PendingActionRecord.Status.REMINDER_SENT; - if (!active) { - return record; - } - - if (decision == PendingActionRecord.Decision.CONFIRM) { - record.setStatus(PendingActionRecord.Status.CONFIRMED); - record.setDecisionAt(System.currentTimeMillis()); - record.setDecisionReason(reason); - cancelPendingLifecycleActions(pendingId); - return record; - } - - if (decision == PendingActionRecord.Decision.REJECT) { - record.setStatus(PendingActionRecord.Status.REJECTED); - record.setDecisionAt(System.currentTimeMillis()); - record.setDecisionReason(reason); - ExecutableAction executableAction = record.getExecutableAction(); - executableAction.setStatus(ExecutableAction.Status.FAILED); - executableAction.setResult("行动被拒绝"); - cancelPendingLifecycleActions(pendingId); - return record; - } - - record.setDecisionReason(reason); - return record; - } - - @CapabilityMethod - public synchronized boolean markPendingReminded(String pendingId) { - PendingActionRecord record = findPendingById(pendingId); - if (record == null) { - return false; - } - if (record.getStatus() != PendingActionRecord.Status.WAITING_CONFIRM) { - return false; - } - record.setStatus(PendingActionRecord.Status.REMINDER_SENT); - record.setReminded(true); - return true; - } - - @CapabilityMethod - public synchronized PendingActionRecord expirePendingIfWaiting(String pendingId) { - PendingActionRecord record = findPendingById(pendingId); - if (record == null) { - return null; - } - PendingActionRecord.Status status = record.getStatus(); - if (status != PendingActionRecord.Status.WAITING_CONFIRM - && status != PendingActionRecord.Status.REMINDER_SENT) { - return null; - } - record.setStatus(PendingActionRecord.Status.EXPIRED); - record.setDecisionAt(System.currentTimeMillis()); - record.setDecisionReason("等待确认超时"); - cancelPendingLifecycleActions(pendingId); - return record; - } - - @CapabilityMethod - public synchronized void bindPendingLifecycleActions(String pendingId, StateAction reminderAction, StateAction expireAction) { - PendingLifecycleActions old = pendingLifecycleActions.put( - pendingId, new PendingLifecycleActions(reminderAction, expireAction) - ); - if (old != null) { - old.reminderAction.setEnabled(false); - old.expireAction.setEnabled(false); - } - PendingActionRecord record = findPendingById(pendingId); - if (record != null) { - record.setReminderActionId(reminderAction.getUuid()); - record.setExpireActionId(expireAction.getUuid()); - } - } - - @CapabilityMethod - public synchronized void cancelPendingLifecycleActions(String pendingId) { - PendingLifecycleActions actions = pendingLifecycleActions.remove(pendingId); - if (actions == null) { - return; - } - actions.reminderAction.setEnabled(false); - actions.expireAction.setEnabled(false); - } - /** * 计算输入内容的语义向量,根据与{@link ActionCacheData#getInputVector()}的相似度挑取缓存,后续将根据评估结果来更新计数 * @@ -514,33 +385,6 @@ public class ActionCore extends PartnerCore { return "action-core"; } - private PendingActionRecord findPendingByUserAndId(String userId, String pendingId) { - List records = pendingActions.get(userId); - if (records == null) { - return null; - } - for (PendingActionRecord record : records) { - if (record.getPendingId().equals(pendingId)) { - return record; - } - } - return null; - } - - private PendingActionRecord findPendingById(String pendingId) { - for (List records : pendingActions.values()) { - for (PendingActionRecord record : records) { - if (record.getPendingId().equals(pendingId)) { - return record; - } - } - } - return null; - } - - private record PendingLifecycleActions(StateAction reminderAction, StateAction expireAction) { - } - public enum ExecutorType { VIRTUAL, PLATFORM } diff --git a/Partner-Core/src/main/java/work/slhaf/partner/core/action/entity/PendingActionRecord.java b/Partner-Core/src/main/java/work/slhaf/partner/core/action/entity/PendingActionRecord.java deleted file mode 100644 index 680f02c9..00000000 --- a/Partner-Core/src/main/java/work/slhaf/partner/core/action/entity/PendingActionRecord.java +++ /dev/null @@ -1,39 +0,0 @@ -package work.slhaf.partner.core.action.entity; - -import lombok.Data; - -import java.util.UUID; - -@Data -public class PendingActionRecord { - - private final String pendingId = UUID.randomUUID().toString(); - private String userId; - private ExecutableAction executableAction; - private Status status = Status.WAITING_CONFIRM; - - private long createdAt; - private long remindAt; - private long expireAt; - - private boolean reminded; - private long decisionAt; - private String decisionReason; - - private String reminderActionId; - private String expireActionId; - - public enum Status { - WAITING_CONFIRM, - REMINDER_SENT, - CONFIRMED, - REJECTED, - EXPIRED - } - - public enum Decision { - CONFIRM, - REJECT, - HOLD - } -} diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java index 6771056e..c5ac3b0a 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java @@ -2,6 +2,8 @@ package work.slhaf.partner.module.modules.action.planner; import kotlin.Unit; import org.jetbrains.annotations.NotNull; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability; import work.slhaf.partner.api.agent.factory.component.abstracts.AbstractAgentModule; import work.slhaf.partner.api.agent.factory.component.annotation.Init; @@ -12,12 +14,10 @@ import work.slhaf.partner.core.action.ActionCore; import work.slhaf.partner.core.action.entity.*; import work.slhaf.partner.core.action.entity.cache.CacheAdjustData; import work.slhaf.partner.core.action.entity.cache.CacheAdjustMetaData; +import work.slhaf.partner.core.cognition.BlockContent; import work.slhaf.partner.core.cognition.CognitionCapability; +import work.slhaf.partner.core.cognition.ContextBlock; import work.slhaf.partner.module.modules.action.executor.ActionExecutor; -import work.slhaf.partner.module.modules.action.planner.confirmer.ActionConfirmer; -import work.slhaf.partner.module.modules.action.planner.confirmer.entity.ConfirmerInput; -import work.slhaf.partner.module.modules.action.planner.confirmer.entity.ConfirmerResult; -import work.slhaf.partner.module.modules.action.planner.confirmer.entity.PendingDecisionItem; import work.slhaf.partner.module.modules.action.planner.evaluator.ActionEvaluator; import work.slhaf.partner.module.modules.action.planner.evaluator.entity.EvaluatorInput; import work.slhaf.partner.module.modules.action.planner.evaluator.entity.EvaluatorResult; @@ -26,11 +26,7 @@ import work.slhaf.partner.module.modules.action.planner.extractor.entity.Extract import work.slhaf.partner.module.modules.action.scheduler.ActionScheduler; import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.util.*; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; @@ -39,9 +35,11 @@ import java.util.concurrent.atomic.AtomicBoolean; */ public class ActionPlanner extends AbstractAgentModule.Running { - private static final long PENDING_TTL_MILLIS = 30 * 60 * 1000L; - private static final long PENDING_REMINDER_ADVANCE_MILLIS = 5 * 60 * 1000L; private static final String IMMEDIATE_WATCHER_CRON = "0/5 * * * * ?"; + private static final String PENDING_BLOCK_SOURCE = "action_planner_pending"; + private static final double PENDING_REPLACE_FADE_FACTOR = 100.0; + private static final double PENDING_TIME_FADE_FACTOR = 40.0; + private static final double PENDING_ACTIVATE_FACTOR = 0.0; private final ActionAssemblyHelper assemblyHelper = new ActionAssemblyHelper(); @@ -55,8 +53,6 @@ public class ActionPlanner extends AbstractAgentModule.Running> tasks = new ArrayList<>(); - addConfirmTask(tasks, context); - addNewActionTask(tasks, context); - executor.invokeAll(tasks); - } catch (Exception e) { - log.error("执行异常", e); - } - } - - /** - * 新的提取与评估任务 - * - * @param tasks 并发任务列表 - * @param context 流程上下文 - */ - private void addNewActionTask(List> tasks, PartnerRunningFlowContext context) { - tasks.add(() -> { ExtractorResult extractorResult = actionExtractor.execute(context.getInput()); if (extractorResult.getTendencies().isEmpty()) { - return null; + return; } EvaluatorInput evaluatorInput = assemblyHelper.buildEvaluatorInput(extractorResult); List evaluatorResults = actionEvaluator.execute(evaluatorInput); // 并发操作均为访问 putActionData(evaluatorResults, context); updateTendencyCache(evaluatorResults, context.getInput(), extractorResult); - return null; - }); + } catch (Exception e) { + log.error("执行异常", e); + } } private void updateTendencyCache(List evaluatorResults, String input, @@ -122,117 +102,114 @@ public class ActionPlanner extends AbstractAgentModule.Running> tasks, PartnerRunningFlowContext context) { - tasks.add(() -> { - ConfirmerInput confirmerInput = assemblyHelper.buildConfirmerInput(context); - ConfirmerResult result = actionConfirmer.execute(confirmerInput); - setupConfirmedActionInfo(context, result); - return null; - }); - } - - private void setupConfirmedActionInfo(PartnerRunningFlowContext context, ConfirmerResult result) { - List decisions = result.getDecisions(); - if (decisions == null || decisions.isEmpty()) { - return; - } - for (PendingDecisionItem decisionItem : decisions) { - PendingActionRecord pendingAction = actionCapability.resolvePendingDecision( - context.getSource(), - decisionItem.getPendingId(), - decisionItem.getDecision(), - decisionItem.getReason() - ); - if (pendingAction == null) { - continue; - } - if (decisionItem.getDecision() == PendingActionRecord.Decision.CONFIRM - && pendingAction.getStatus() == PendingActionRecord.Status.CONFIRMED) { - executeOrSchedule(pendingAction.getExecutableAction()); - } - } - } - private void putActionData(List evaluatorResults, PartnerRunningFlowContext context) { for (EvaluatorResult evaluatorResult : evaluatorResults) { + expireResolvedPending(evaluatorResult); + if (!evaluatorResult.isOk()) { + continue; + } ExecutableAction executableAction = assemblyHelper.buildActionData(evaluatorResult, context.getSource()); if (evaluatorResult.isNeedConfirm()) { - PendingActionRecord pendingAction = actionCapability.createPendingAction( - context.getSource(), - executableAction, - PENDING_TTL_MILLIS, - PENDING_REMINDER_ADVANCE_MILLIS - ); - schedulePendingLifecycleActions(pendingAction); - } else { - executeOrSchedule(executableAction); + registerPendingContextBlock(executableAction, evaluatorResult); + continue; } + executeOrSchedule(executableAction); } } - private void schedulePendingLifecycleActions(PendingActionRecord pendingAction) { - StateAction reminderAction = buildPendingReminderAction(pendingAction); - StateAction expireAction = buildPendingExpireAction(pendingAction); - actionCapability.bindPendingLifecycleActions(pendingAction.getPendingId(), reminderAction, expireAction); - actionScheduler.schedule(reminderAction); - actionScheduler.schedule(expireAction); - } - - private StateAction buildPendingReminderAction(PendingActionRecord pendingAction) { - return new StateAction( - pendingAction.getUserId(), - "pending-action-reminder:" + pendingAction.getPendingId(), - "待确认行动提醒", - Schedulable.ScheduleType.ONCE, - asScheduleContent(pendingAction.getRemindAt()), - new StateAction.Trigger.Call(() -> { - handlePendingReminder(pendingAction.getPendingId(), pendingAction.getUserId()); - return Unit.INSTANCE; - }) - ); - } - - private StateAction buildPendingExpireAction(PendingActionRecord pendingAction) { - return new StateAction( - pendingAction.getUserId(), - "pending-action-expire:" + pendingAction.getPendingId(), - "待确认行动失效", - Schedulable.ScheduleType.ONCE, - asScheduleContent(pendingAction.getExpireAt()), - new StateAction.Trigger.Call(() -> { - handlePendingExpire(pendingAction.getPendingId()); - return Unit.INSTANCE; - }) - ); - } - - private void handlePendingReminder(String pendingId, String userId) { - boolean marked = actionCapability.markPendingReminded(pendingId); - if (!marked) { + private void expireResolvedPending(EvaluatorResult evaluatorResult) { + EvaluatorResult.ResolvedPending resolvedPending = evaluatorResult.getResolvedPending(); + if (resolvedPending == null) { return; } - try { - // TODO target 指定行为待补充; 主动回复链路待补充 - cognitionCapability.initiateTurn("系统提醒:存在待确认行动即将过期,请确认是否继续执行。pendingId=" + pendingId, userId); - } catch (Exception e) { - log.warn("触发待确认行动提醒失败, pendingId: {}", pendingId, e); + if (resolvedPending.getBlockName() == null || resolvedPending.getSource() == null) { + return; } + cognitionCapability.contextWorkspace().expire( + resolvedPending.getBlockName(), + resolvedPending.getSource() + ); } - private void handlePendingExpire(String pendingId) { - actionCapability.expirePendingIfWaiting(pendingId); + private void registerPendingContextBlock(ExecutableAction executableAction, EvaluatorResult evaluatorResult) { + String blockName = buildPendingBlockName(executableAction); + ContextBlock block = new ContextBlock( + buildPendingBlock(blockName, executableAction, evaluatorResult), + buildPendingCompactBlock(blockName, executableAction, evaluatorResult), + buildPendingAbstractBlock(blockName, executableAction, evaluatorResult), + Set.of(ContextBlock.VisibleDomain.ACTION), + PENDING_REPLACE_FADE_FACTOR, + PENDING_TIME_FADE_FACTOR, + PENDING_ACTIVATE_FACTOR + ); + cognitionCapability.contextWorkspace().register(block); } - private String asScheduleContent(long targetTimeMillis) { - long now = System.currentTimeMillis(); - long safeTarget = Math.max(targetTimeMillis, now + 1000L); - return ZonedDateTime.ofInstant(Instant.ofEpochMilli(safeTarget), ZoneId.systemDefault()).toString(); + private String buildPendingBlockName(ExecutableAction executableAction) { + return "pending_action-" + executableAction.getUuid(); + } + + private BlockContent buildPendingBlock(String blockName, ExecutableAction executableAction, EvaluatorResult evaluatorResult) { + return new BlockContent(blockName, PENDING_BLOCK_SOURCE) { + @Override + protected void fillXml(@NotNull Document document, @NotNull Element root) { + appendTextElement(document, root, "state", "waiting_confirm"); + appendTextElement(document, root, "action_uuid", executableAction.getUuid()); + appendTextElement(document, root, "action_type", evaluatorResult.getType()); + appendTextElement(document, root, "tendency", executableAction.getTendency()); + appendTextElement(document, root, "reason", executableAction.getReason()); + appendTextElement(document, root, "description", executableAction.getDescription()); + appendTextElement(document, root, "source_user", executableAction.getSource()); + if (evaluatorResult.getScheduleType() != null) { + appendTextElement(document, root, "schedule_type", evaluatorResult.getScheduleType()); + } + if (evaluatorResult.getScheduleContent() != null) { + appendTextElement(document, root, "schedule_content", evaluatorResult.getScheduleContent()); + } + Map> primaryActionChain = evaluatorResult.getPrimaryActionChain(); + if (primaryActionChain == null || primaryActionChain.isEmpty()) { + return; + } + Element chainRoot = document.createElement("primary_action_chain"); + root.appendChild(chainRoot); + List orders = new ArrayList<>(primaryActionChain.keySet()); + orders.sort(Integer::compareTo); + for (Integer order : orders) { + Element orderElement = document.createElement("step"); + orderElement.setAttribute("order", String.valueOf(order)); + chainRoot.appendChild(orderElement); + appendRepeatedElements( + document, + orderElement, + "action_key", + primaryActionChain.getOrDefault(order, List.of()) + ); + } + } + }; + } + + private BlockContent buildPendingCompactBlock(String blockName, ExecutableAction executableAction, EvaluatorResult evaluatorResult) { + return new BlockContent(blockName, PENDING_BLOCK_SOURCE) { + @Override + protected void fillXml(@NotNull Document document, @NotNull Element root) { + appendTextElement(document, root, "state", "waiting_confirm"); + appendTextElement(document, root, "tendency", executableAction.getTendency()); + appendTextElement(document, root, "description", executableAction.getDescription()); + appendTextElement(document, root, "action_type", evaluatorResult.getType()); + } + }; + } + + private BlockContent buildPendingAbstractBlock(String blockName, ExecutableAction executableAction, EvaluatorResult evaluatorResult) { + return new BlockContent(blockName, PENDING_BLOCK_SOURCE) { + @Override + protected void fillXml(@NotNull Document document, @NotNull Element root) { + appendTextElement(document, root, "pending_tendency", executableAction.getTendency()); + appendTextElement(document, root, "summary", "exists pending action waiting for confirmation"); + appendTextElement(document, root, "action_type", evaluatorResult.getType()); + } + }; } private void executeOrSchedule(ExecutableAction executableAction) { @@ -403,13 +380,5 @@ public class ActionPlanner extends AbstractAgentModule.Running pendingActions = actionCapability.listActivePendingActions(context.getSource()); - confirmerInput.setRecentMessages(cognitionCapability.snapshotChatMessages()); - confirmerInput.setPendingActions(pendingActions); - return confirmerInput; - } } } diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/ActionConfirmer.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/ActionConfirmer.java deleted file mode 100644 index 6df84f6a..00000000 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/ActionConfirmer.java +++ /dev/null @@ -1,124 +0,0 @@ -package work.slhaf.partner.module.modules.action.planner.confirmer; - -import com.alibaba.fastjson2.JSONArray; -import com.alibaba.fastjson2.JSONObject; -import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability; -import work.slhaf.partner.api.agent.factory.component.abstracts.AbstractAgentModule; -import work.slhaf.partner.api.agent.factory.component.abstracts.ActivateModel; -import work.slhaf.partner.api.chat.pojo.Message; -import work.slhaf.partner.core.action.ActionCapability; -import work.slhaf.partner.core.action.ActionCore; -import work.slhaf.partner.core.action.entity.ExecutableAction; -import work.slhaf.partner.core.action.entity.PendingActionRecord; -import work.slhaf.partner.module.modules.action.planner.confirmer.entity.ConfirmerInput; -import work.slhaf.partner.module.modules.action.planner.confirmer.entity.ConfirmerResult; -import work.slhaf.partner.module.modules.action.planner.confirmer.entity.PendingDecisionItem; - -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; - -public class ActionConfirmer extends AbstractAgentModule.Sub implements ActivateModel { - @InjectCapability - private ActionCapability actionCapability; - - @Override - public ConfirmerResult execute(ConfirmerInput data) { - List pendingActions = data.getPendingActions(); - if (pendingActions == null || pendingActions.isEmpty()) { - return new ConfirmerResult(); - } - ExecutorService executor = actionCapability.getExecutor(ActionCore.ExecutorType.VIRTUAL); - CountDownLatch latch = new CountDownLatch(pendingActions.size()); - ConfirmerResult result = new ConfirmerResult(); - List decisions = result.getDecisions(); - for (PendingActionRecord pendingAction : pendingActions) { - executor.execute(() -> { - try { - ExecutableAction executableAction = pendingAction.getExecutableAction(); - String prompt = buildPrompt(executableAction, data.getInput(), data.getRecentMessages()); - DecisionResponse tempResult = formattedChat( - List.of(new Message(Message.Character.USER, prompt)), - DecisionResponse.class - ); - PendingActionRecord.Decision decision = parseDecision(tempResult); - String reason = tempResult.getReason(); - synchronized (decisions) { - decisions.add(new PendingDecisionItem(pendingAction.getPendingId(), decision, reason)); - } - } catch (Exception e) { - synchronized (decisions) { - decisions.add(new PendingDecisionItem( - pendingAction.getPendingId(), - PendingActionRecord.Decision.HOLD, - "确认解析失败: " + e.getLocalizedMessage() - )); - } - } finally { - latch.countDown(); - } - }); - } - try { - latch.await(); - } catch (InterruptedException e) { - log.warn("CountDownLatch阻塞已中断"); - } - return result; - } - - private PendingActionRecord.Decision parseDecision(DecisionResponse tempResult) { - if (tempResult == null) { - return PendingActionRecord.Decision.HOLD; - } - String decisionText = tempResult.getDecision(); - if (decisionText != null) { - String upperDecision = decisionText.toUpperCase(); - if (upperDecision.contains("CONFIRM")) { - return PendingActionRecord.Decision.CONFIRM; - } - if (upperDecision.contains("REJECT")) { - return PendingActionRecord.Decision.REJECT; - } - if (upperDecision.contains("HOLD")) { - return PendingActionRecord.Decision.HOLD; - } - } - Boolean confirmed = tempResult.getConfirmed(); - if (Boolean.TRUE.equals(confirmed)) { - return PendingActionRecord.Decision.CONFIRM; - } - return PendingActionRecord.Decision.HOLD; - } - - private String buildPrompt(ExecutableAction data, String input, List recentMessages) { - JSONObject prompt = new JSONObject(); - prompt.put("[用户输入]", input); - JSONObject actionData = prompt.putObject("[行动数据]"); - actionData.put("[行动倾向]", data.getTendency()); - actionData.put("[行动原因]", data.getReason()); - actionData.put("[行动来源]", data.getSource()); - actionData.put("[行动描述]", data.getDescription()); - JSONArray decisionEnums = prompt.putArray("[决策选项]"); - decisionEnums.add("CONFIRM"); - decisionEnums.add("REJECT"); - decisionEnums.add("HOLD"); - JSONArray messageData = prompt.putArray("[近期对话]"); - if (recentMessages != null) { - messageData.addAll(recentMessages); - } - return prompt.toString(); - } - - @Override - public String modelKey() { - return "action-confirmer"; - } - - @lombok.Data - private static class DecisionResponse { - private String decision; - private String reason; - private Boolean confirmed; - } -} diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerInput.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerInput.java deleted file mode 100644 index 4f96174b..00000000 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerInput.java +++ /dev/null @@ -1,14 +0,0 @@ -package work.slhaf.partner.module.modules.action.planner.confirmer.entity; - -import lombok.Data; -import work.slhaf.partner.api.chat.pojo.Message; -import work.slhaf.partner.core.action.entity.PendingActionRecord; - -import java.util.List; - -@Data -public class ConfirmerInput { - private String input; - private List pendingActions; - private List recentMessages; -} diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerResult.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerResult.java deleted file mode 100644 index c25abf84..00000000 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/ConfirmerResult.java +++ /dev/null @@ -1,11 +0,0 @@ -package work.slhaf.partner.module.modules.action.planner.confirmer.entity; - -import lombok.Data; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class ConfirmerResult { - private List decisions = new ArrayList<>(); -} diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/PendingDecisionItem.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/PendingDecisionItem.java deleted file mode 100644 index 1bfbaafa..00000000 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/confirmer/entity/PendingDecisionItem.java +++ /dev/null @@ -1,15 +0,0 @@ -package work.slhaf.partner.module.modules.action.planner.confirmer.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import work.slhaf.partner.core.action.entity.PendingActionRecord; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class PendingDecisionItem { - private String pendingId; - private PendingActionRecord.Decision decision; - private String reason; -} diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/ActionEvaluator.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/ActionEvaluator.java index 8c896dae..1b9f0c7f 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/ActionEvaluator.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/ActionEvaluator.java @@ -53,7 +53,11 @@ public class ActionEvaluator extends AbstractAgentModule.Sub { List messages = List.of( - cognitionCapability.contextWorkspace().resolve(List.of(ContextBlock.VisibleDomain.ACTION, ContextBlock.VisibleDomain.COGNITION, ContextBlock.VisibleDomain.MEMORY)).encodeToContextMessage(), + cognitionCapability.contextWorkspace().resolve(List.of( + ContextBlock.VisibleDomain.ACTION, + ContextBlock.VisibleDomain.COGNITION, + ContextBlock.VisibleDomain.MEMORY + )).encodeToContextMessage(), availableMetaActionContext(), new Message(Message.Character.USER, tendency) ); diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java index 79266942..13749bbe 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/evaluator/entity/EvaluatorResult.java @@ -10,6 +10,7 @@ import java.util.Map; public class EvaluatorResult { private boolean ok; private boolean needConfirm; + private ResolvedPending resolvedPending; private ActionType type; private String scheduleContent; private SchedulableExecutableAction.ScheduleType scheduleType; @@ -21,4 +22,10 @@ public class EvaluatorResult { public enum ActionType { IMMEDIATE, PLANNING } + + @Data + public static class ResolvedPending { + private String blockName; + private String source; + } } diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/extractor/ActionExtractor.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/extractor/ActionExtractor.java index 87a119af..336debec 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/extractor/ActionExtractor.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/extractor/ActionExtractor.java @@ -29,7 +29,10 @@ public class ActionExtractor extends AbstractAgentModule.Sub messages = List.of( - cognitionCapability.contextWorkspace().resolve(List.of(ContextBlock.VisibleDomain.COGNITION)).encodeToContextMessage(), + cognitionCapability.contextWorkspace().resolve(List.of( + ContextBlock.VisibleDomain.ACTION, + ContextBlock.VisibleDomain.COGNITION + )).encodeToContextMessage(), new Message(Message.Character.USER, input) ); return formattedChat( @@ -37,7 +40,7 @@ public class ActionExtractor extends AbstractAgentModule.Sub