调整 MetaAction 的执行方式,将交给 ActionCapability、SandBoxRunnerClient 执行

This commit is contained in:
2025-11-30 22:16:57 +08:00
parent c548cceec6
commit 3f59719e16
8 changed files with 68 additions and 45 deletions

2
.idea/encodings.xml generated
View File

@@ -3,11 +3,11 @@
<component name="Encoding"> <component name="Encoding">
<file url="file://$PROJECT_DIR$/Partner-Api/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Api/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Executor/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Main/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/java/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Main/src/main/java/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/java/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Main/src/main/java/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Main/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-SandboxRunner/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Test-Demo/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Test-Demo/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Test-Demo/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/Partner-Test-Demo/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />

View File

@@ -45,4 +45,6 @@ public interface ActionCapability {
MetaActionInfo loadMetaActionInfo(@NonNull String actionKey); MetaActionInfo loadMetaActionInfo(@NonNull String actionKey);
boolean checkExists(String... actionKeys); boolean checkExists(String... actionKeys);
void execute(MetaAction metaAction);
} }

View File

@@ -55,6 +55,7 @@ public class ActionCore extends PartnerCore<ActionCore> {
*/ */
private final LinkedHashMap<String, MetaActionInfo> existedMetaActions = new LinkedHashMap<>(); private final LinkedHashMap<String, MetaActionInfo> existedMetaActions = new LinkedHashMap<>();
private final List<PhaserRecord> phaserRecords = new ArrayList<>(); private final List<PhaserRecord> phaserRecords = new ArrayList<>();
private final SandboxRunnerClient sandboxRunnerClient = new SandboxRunnerClient();
public ActionCore() throws IOException, ClassNotFoundException { public ActionCore() throws IOException, ClassNotFoundException {
new ActionWatchService(existedMetaActions, virtualExecutor).launch(); new ActionWatchService(existedMetaActions, virtualExecutor).launch();
@@ -241,6 +242,11 @@ public class ActionCore extends PartnerCore<ActionCore> {
return existedMetaActions.keySet().containsAll(Arrays.asList(actionKeys)); return existedMetaActions.keySet().containsAll(Arrays.asList(actionKeys));
} }
@CapabilityMethod
public void execute(MetaAction metaAction) {
sandboxRunnerClient.run(metaAction);
}
/** /**
* 命中缓存且评估通过时 * 命中缓存且评估通过时
* *

View File

@@ -17,6 +17,7 @@ import java.util.concurrent.ExecutorService;
import static work.slhaf.partner.common.Constant.Path.ACTION_PROGRAM; import static work.slhaf.partner.common.Constant.Path.ACTION_PROGRAM;
// TODO 后续需迁移至 SandboxRunner作为容器内的监听逻辑
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Slf4j @Slf4j
class ActionWatchService { class ActionWatchService {

View File

@@ -0,0 +1,36 @@
package work.slhaf.partner.core.action;
import work.slhaf.partner.core.action.entity.MetaAction;
import java.nio.file.Path;
/**
* 基于 Http 与 WebSocket 的沙盒执行器客户端,负责:
* <ul>
* <li>
* 发送行动单元数据
* </li>
* <li>
* 实时更新获取已存在行动列表
* </li>
* <li>
* 向传入的 MetaAction 回写执行结果
* </li>
* </ul>
*/
class SandboxRunnerClient {
public SandboxRunnerClient() {
// 连接沙盒执行器(websocket)
}
public void run(MetaAction metaAction) {
// 获取已存在行动列表
Path path = metaAction.checkAndGetPath();
if (!metaAction.getResult().isSuccess()) {
return;
}
// 调用沙盒执行器
}
}

View File

@@ -2,7 +2,6 @@ package work.slhaf.partner.core.action.entity;
import lombok.Data; import lombok.Data;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import work.slhaf.partner.common.Constant;
import java.io.File; import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
@@ -10,10 +9,10 @@ import java.nio.file.Path;
import static work.slhaf.partner.common.Constant.Path.ACTION_PROGRAM; import static work.slhaf.partner.common.Constant.Path.ACTION_PROGRAM;
/** /**
* 行动链中的单一元素,实现{@link Runnable}接口,封装了调用外部行动程序的必要信息,可被执行 * 行动链中的单一元素,封装了调用外部行动程序的必要信息与结果容器,可被{@link work.slhaf.partner.core.action.ActionCapability}执行
*/ */
@Data @Data
public class MetaAction implements Comparable<MetaAction>, Runnable { public class MetaAction implements Comparable<MetaAction> {
/** /**
* 行动key用于标识与定位行动程序 * 行动key用于标识与定位行动程序
@@ -40,48 +39,23 @@ public class MetaAction implements Comparable<MetaAction>, Runnable {
*/ */
private MetaActionType type; private MetaActionType type;
@Override public Path checkAndGetPath() {
public int compareTo(@NotNull MetaAction metaAction) { Path path = switch (type) {
return this.order - metaAction.order; case PLUGIN -> Path.of(ACTION_PROGRAM, key, "action.jar");
} case SCRIPT -> Path.of(ACTION_PROGRAM, key, "action.py");
case MCP -> Path.of(ACTION_PROGRAM, key, "action.json");
@Override };
public void run() { File action = path.toFile();
File action = loadFromFile();
if (!action.exists()) { if (!action.exists()) {
result.setSuccess(false); result.setSuccess(false);
result.setData("Action file not found: " + action.getAbsolutePath()); result.setData("Action file not found: " + action.getAbsolutePath());
} }
try { return path;
switch (type) {
case PLUGIN -> executePlugin(action);
case MCP -> executeMcp(action);
case SCRIPT -> executeScript(action);
}
} catch (Exception e) {
result.setSuccess(false);
result.setData(e.getMessage());
}
} }
private File loadFromFile() { @Override
return switch (type) { public int compareTo(@NotNull MetaAction metaAction) {
case PLUGIN -> Path.of(Constant.Path.ACTION_PROGRAM, key, "action.jar").toFile(); return this.order - metaAction.order;
case SCRIPT -> Path.of(ACTION_PROGRAM, key, "action.py").toFile();
case MCP -> Path.of(ACTION_PROGRAM, key, "action.json").toFile();
};
}
private void executePlugin(File actionFile) {
}
private void executeMcp(File actionFile) {
}
private void executeScript(File actionFile) {
} }
@Data @Data

View File

@@ -51,9 +51,12 @@ public class ActionExecutor extends AgentRunningSubModule<List<ImmediateActionDa
Phaser phaser = new Phaser(); Phaser phaser = new Phaser();
phaser.register(); phaser.register();
actionCapability.putPhaserRecord(phaser, actionData); actionCapability.putPhaserRecord(phaser, actionData);
List<Integer> orderList = new ArrayList<>(actionChain.keySet().stream().toList());
orderList.sort(Integer::compareTo);
try { try {
actionChain.forEach((k, v) -> { for (Integer order : orderList) {
for (MetaAction metaAction : v) { List<MetaAction> metaActions = actionChain.get(order);
for (MetaAction metaAction : metaActions) {
// 根据io类型放入合适的列表 // 根据io类型放入合适的列表
if (metaAction.isIo()) { if (metaAction.isIo()) {
virtual.add(metaAction); virtual.add(metaAction);
@@ -65,7 +68,7 @@ public class ActionExecutor extends AgentRunningSubModule<List<ImmediateActionDa
phaser.arriveAndAwaitAdvance(); phaser.arriveAndAwaitAdvance();
virtual.clear(); virtual.clear();
platform.clear(); platform.clear();
}); }
} finally { } finally {
phaser.arriveAndDeregister(); phaser.arriveAndDeregister();
actionCapability.removePhaserRecord(phaser); actionCapability.removePhaserRecord(phaser);
@@ -97,9 +100,10 @@ public class ActionExecutor extends AgentRunningSubModule<List<ImmediateActionDa
String input = getInput(result.getData()); String input = getInput(result.getData());
// 执行时不可使用`for in`和`forEach`,因为在`Intervention`相关模块存在动态调整 // 执行时不可使用`for in`和`forEach`,因为在`Intervention`相关模块存在动态调整
} }
action.run(); actionCapability.execute(action);
} while (!result.isSuccess()); } while (!result.isSuccess());
// TODO 将执行结果写入特定对话角色记忆(cognationCore暴露方法) // TODO 将执行结果写入特定对话角色记忆(cognationCore暴露方法)
} finally { } finally {
phaser.arriveAndDeregister(); phaser.arriveAndDeregister();
} }

View File

@@ -143,7 +143,7 @@ public class InterventionHandler extends AgentRunningSubModule<HandlerInput, Voi
executor = action.isIo() ? virtualExecutor : platformExecutor; executor = action.isIo() ? virtualExecutor : platformExecutor;
executor.execute(() -> { executor.execute(() -> {
try { try {
action.run(); actionCapability.execute(action);
} finally { } finally {
phaser.arriveAndDeregister(); phaser.arriveAndDeregister();
} }