feat(LocalRunnerClient): support executing origin actions

Context:
Origin actions are generated by DynamicActionGenerator and may optionally be
persistently serialized. This feature adds the basic execution flow for origin
actions within LocalRunnerClient.

Notes:
The current mapping between action files and their extensions is hardcoded. This should later be replaced with a configurable registry or loaded dynamically
during application startup.
This commit is contained in:
2025-12-16 21:59:53 +08:00
parent 488246525f
commit 1947f25ed6
3 changed files with 98 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
package work.slhaf.partner.core.action.runner; package work.slhaf.partner.core.action.runner;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import lombok.Data; import lombok.Data;
@@ -57,9 +58,39 @@ public class LocalRunnerClient extends RunnerClient {
private RunnerResponse doRunWithOrigin(MetaAction metaAction) { private RunnerResponse doRunWithOrigin(MetaAction metaAction) {
RunnerResponse response = new RunnerResponse(); RunnerResponse response = new RunnerResponse();
File file = metaAction.getPath().toFile();
String ext = FileUtil.getSuffix(file);
if (ext == null || ext.isEmpty()) {
response.setOk(false);
response.setData("未知文件类型");
return response; return response;
} }
String[] commands = buildCommands(ext, metaAction.getParams(), file.getAbsolutePath());
SystemExecResult execResult = exec(commands);
response.setOk(execResult.isOk());
response.setData(execResult.getTotal());
return response;
}
//TODO 后续需在加载时、或者通过配置文件获取可用命令并注册匹配
private String[] buildCommands(String ext, Map<String, String> params, String absolutePath) {
String command = switch (ext) {
case "py" -> "python";
case "sh" -> "bash";
default -> null;
};
if (command == null) {
return null;
}
String[] commands = new String[params.size() + 2];
commands[0] = command;
commands[1] = absolutePath;
AtomicInteger paramCount = new AtomicInteger(2);
params.forEach((param, value) -> {
commands[paramCount.getAndIncrement()] = "--" + param + "=" + value;
});
return commands;
}
private RunnerResponse doRunWithMcp(MetaAction metaAction) { private RunnerResponse doRunWithMcp(MetaAction metaAction) {
RunnerResponse response = new RunnerResponse(); RunnerResponse response = new RunnerResponse();
@@ -95,7 +126,7 @@ public class LocalRunnerClient extends RunnerClient {
JSONObject sysDependencies = new JSONObject(); JSONObject sysDependencies = new JSONObject();
sysDependencies.put("language", "Python"); sysDependencies.put("language", "Python");
JSONArray dependencies = sysDependencies.putArray("dependencies"); JSONArray dependencies = sysDependencies.putArray("dependencies");
SystemExecResult pyResult = exec("pip", "li", "--format=feeze"); SystemExecResult pyResult = exec("pip", "list", "--format=freeze");
System.out.println(pyResult); System.out.println(pyResult);
if (pyResult.isOk()) { if (pyResult.isOk()) {
List<String> resultList = pyResult.getResultList(); List<String> resultList = pyResult.getResultList();

View File

@@ -0,0 +1,24 @@
import sys
def parse_args(argv):
"""
将 --key=value 解析成 dict
"""
params = {}
for arg in argv:
if arg.startswith("--") and "=" in arg:
key, value = arg[2:].split("=", 1)
params[key] = value
return params
def main():
params = parse_args(sys.argv[1:])
name = params.get("name", "World")
print(f"Hello {name}!")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,40 @@
package work.slhaf.partner.core.action.runner;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import work.slhaf.partner.core.action.entity.MetaAction;
import work.slhaf.partner.core.action.entity.MetaActionType;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.Executors;
public class LocalRunnerClientTest {
static LocalRunnerClient runnerClient;
@BeforeAll
static void beforeAll() {
runnerClient = new LocalRunnerClient(Map.of(), Executors.newVirtualThreadPerTaskExecutor(), "/home/slhaf/Projects/IdeaProjects/Projects/Partner/Partner-Main/src/test/java/resources/action/data");
}
@Test
void runOrigin() {
MetaAction metaAction = buildTmpMetaAction();
RunnerClient.RunnerResponse runnerResponse = runnerClient.doRun(metaAction);
System.out.println(runnerResponse.getData());
}
private static @NotNull MetaAction buildTmpMetaAction() {
MetaAction metaAction = new MetaAction();
metaAction.setIo(false);
metaAction.setKey("hello_world");
metaAction.setParams(Map.of("name", "origin_run"));
metaAction.setOrder(-1);
metaAction.setType(MetaActionType.ORIGIN);
metaAction.setPath(Path.of("/home/slhaf/Projects/IdeaProjects/Projects/Partner/Partner-Main/src/test/java/resources/action/tmp/hello_world.py"));
return metaAction;
}
}