mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
refactor(action): pass launcher through meta action flow instead of inferring command by file extension
This commit is contained in:
@@ -329,7 +329,8 @@ public class ActionCore extends PartnerCore<ActionCore> {
|
||||
MetaAction.Type type = BUILTIN_LOCATION.equals(split[0]) ? MetaAction.Type.BUILTIN : MetaAction.Type.MCP;
|
||||
return new MetaAction(
|
||||
split[1],
|
||||
metaActionInfo.isIo(),
|
||||
metaActionInfo.getIo(),
|
||||
metaActionInfo.getLauncher(),
|
||||
type,
|
||||
split[0]
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ public class GeneratedData {
|
||||
private List<String> dependencies;
|
||||
private String code;
|
||||
private String codeType;
|
||||
private String launcher;
|
||||
private boolean serialize;
|
||||
private JSONObject responseSchema;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,13 @@ data class MetaAction(
|
||||
* 是否IO密集,用于决定使用何种线程池
|
||||
*/
|
||||
val io: Boolean = false,
|
||||
/**
|
||||
* 启动器/解释器,对于原生 MCP Tool 、Dynamic Action 来说可忽略,目前仅用于 ORIGIN 类型
|
||||
*/
|
||||
val launcher: String? = null,
|
||||
/**
|
||||
* 行动程序类型,可分为 MCP、ORIGIN、BUILTIN 三种,
|
||||
* 分别对应读取到的 MCP Tool、生成的临时行动程序、本地内置行动
|
||||
* 分别对应读取到的 MCP Tool、生成的临时行动程序、内置行动
|
||||
*/
|
||||
val type: Type,
|
||||
/**
|
||||
|
||||
@@ -1,25 +1,44 @@
|
||||
package work.slhaf.partner.core.action.entity;
|
||||
package work.slhaf.partner.core.action.entity
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import com.alibaba.fastjson2.JSONObject
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class MetaActionInfo {
|
||||
private boolean io;
|
||||
data class MetaActionInfo(
|
||||
/**
|
||||
* 是否 IO 密集
|
||||
*/
|
||||
val io: Boolean,
|
||||
/**
|
||||
* 所需的启动器/解释器
|
||||
*/
|
||||
val launcher: String?,
|
||||
/**
|
||||
* 参数描述
|
||||
*/
|
||||
val params: Map<String, String>,
|
||||
/**
|
||||
* 行动功能描述
|
||||
*/
|
||||
val description: String,
|
||||
/**
|
||||
* 行动标签
|
||||
*/
|
||||
val tags: Set<String>,
|
||||
/**
|
||||
* 前置行动依赖
|
||||
*/
|
||||
val preActions: Set<String>,
|
||||
/**
|
||||
* 后置行动依赖
|
||||
*/
|
||||
val postActions: Set<String>,
|
||||
|
||||
private Map<String, Object> params;
|
||||
private String description;
|
||||
private List<String> tags;
|
||||
|
||||
private List<String> preActions;
|
||||
private List<String> postActions;
|
||||
/**
|
||||
* 是否严格依赖前置行动的成功执行,若为true且前置行动失败则不执行该行动,后置任务多为触发式。默认即执行。
|
||||
*/
|
||||
private boolean strictDependencies;
|
||||
|
||||
private JSONObject responseSchema;
|
||||
}
|
||||
val strictDependencies: Boolean,
|
||||
/**
|
||||
* 响应格式说明
|
||||
*/
|
||||
val responseSchema: JSONObject,
|
||||
)
|
||||
|
||||
@@ -11,18 +11,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CommandExecutionService {
|
||||
|
||||
public String[] buildCommands(String ext, Map<String, Object> params, String absolutePath) {
|
||||
String command = switch (ext) {
|
||||
case "py" -> "python";
|
||||
case "sh" -> "bash";
|
||||
default -> null;
|
||||
};
|
||||
if (command == null) {
|
||||
return null;
|
||||
}
|
||||
public String[] buildCommands(String launcher, Map<String, Object> params, String absolutePath) {
|
||||
int paramSize = params == null ? 0 : params.size();
|
||||
String[] commands = new String[paramSize + 2];
|
||||
commands[0] = command;
|
||||
commands[0] = launcher;
|
||||
commands[1] = absolutePath;
|
||||
AtomicInteger paramCount = new AtomicInteger(2);
|
||||
if (params != null) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package work.slhaf.partner.core.action.runner.execution;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import work.slhaf.partner.core.action.entity.MetaAction;
|
||||
import work.slhaf.partner.core.action.runner.RunnerClient;
|
||||
|
||||
@@ -17,18 +16,7 @@ public class OriginExecutionService {
|
||||
public RunnerClient.RunnerResponse run(MetaAction metaAction) {
|
||||
RunnerClient.RunnerResponse response = new RunnerClient.RunnerResponse();
|
||||
File file = new File(metaAction.getLocation());
|
||||
String ext = FileUtil.getSuffix(file);
|
||||
if (ext == null || ext.isEmpty()) {
|
||||
response.setOk(false);
|
||||
response.setData("未知文件类型");
|
||||
return response;
|
||||
}
|
||||
String[] commands = commandExecutionService.buildCommands(ext, metaAction.getParams(), file.getAbsolutePath());
|
||||
if (commands == null || commands.length == 0) {
|
||||
response.setOk(false);
|
||||
response.setData("不支持的文件类型: " + file.getName());
|
||||
return response;
|
||||
}
|
||||
String[] commands = commandExecutionService.buildCommands(metaAction.getLauncher(), metaAction.getParams(), file.getAbsolutePath());
|
||||
CommandExecutionService.Result execResult = commandExecutionService.exec(commands);
|
||||
response.setOk(execResult.isOk());
|
||||
response.setData(execResult.getTotal());
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package work.slhaf.partner.core.action.runner.mcp;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import io.modelcontextprotocol.common.McpTransportContext;
|
||||
@@ -292,8 +291,8 @@ public class DynamicActionMcpManager implements AutoCloseable {
|
||||
Map<String, Object> additional = Map.of(
|
||||
"pre", info.getPreActions(),
|
||||
"post", info.getPostActions(),
|
||||
"strict_pre", info.isStrictDependencies(),
|
||||
"io", info.isIo()
|
||||
"strict_pre", info.getStrictDependencies(),
|
||||
"io", info.getIo()
|
||||
);
|
||||
McpSchema.Tool tool = McpSchema.Tool.builder()
|
||||
.name(name)
|
||||
@@ -305,18 +304,17 @@ public class DynamicActionMcpManager implements AutoCloseable {
|
||||
.build();
|
||||
return McpStatelessServerFeatures.AsyncToolSpecification.builder()
|
||||
.tool(tool)
|
||||
.callHandler(buildToolHandler(program))
|
||||
.callHandler(buildToolHandler(program, info.getLauncher()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private BiFunction<McpTransportContext, McpSchema.CallToolRequest, Mono<McpSchema.CallToolResult>> buildToolHandler(File program) {
|
||||
private BiFunction<McpTransportContext, McpSchema.CallToolRequest, Mono<McpSchema.CallToolResult>> buildToolHandler(File program, String launcher) {
|
||||
return (mcpTransportContext, callToolRequest) -> {
|
||||
Map<String, Object> arguments = callToolRequest.arguments();
|
||||
if (arguments == null) {
|
||||
arguments = Map.of();
|
||||
}
|
||||
String ext = FileUtil.getSuffix(program);
|
||||
String[] commands = commandExecutionService.buildCommands(ext, arguments, program.getAbsolutePath());
|
||||
String[] commands = commandExecutionService.buildCommands(launcher, arguments, program.getAbsolutePath());
|
||||
if (commands == null) {
|
||||
return Mono.just(McpSchema.CallToolResult.builder()
|
||||
.addTextContent("未知文件类型: " + program.getName())
|
||||
|
||||
@@ -46,6 +46,7 @@ public class DynamicActionGenerator extends AbstractAgentModule.Sub<GeneratorInp
|
||||
MetaAction tempAction = new MetaAction(
|
||||
input.getActionName(),
|
||||
true,
|
||||
generatorData.getLauncher(),
|
||||
MetaAction.Type.ORIGIN,
|
||||
location
|
||||
);
|
||||
@@ -63,6 +64,7 @@ public class DynamicActionGenerator extends AbstractAgentModule.Sub<GeneratorInp
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO persist serialize. For now, it can be scheduled as a cycling-triggered StateAction or as a special MetaAction
|
||||
private void waitingSerialize() {
|
||||
throw new UnsupportedOperationException("Unimplemented method 'waitingSerialize'");
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class RepairerInput {
|
||||
|
||||
private String userId;
|
||||
private List<Message> recentMessages;
|
||||
private Map<String, Object> params;
|
||||
private Map<String, String> params;
|
||||
private String actionDescription;
|
||||
private List<HistoryAction> historyActionResults;
|
||||
}
|
||||
|
||||
@@ -380,12 +380,12 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
|
||||
for (String actionKey : actionKeys) {
|
||||
// 根据 actionKey 加载行动信息,并检查是否存在必需前置依赖
|
||||
MetaActionInfo metaActionInfo = actionCapability.loadMetaActionInfo(actionKey);
|
||||
List<String> preActions = metaActionInfo.getPreActions();
|
||||
boolean preActionsExist = preActions != null && !preActions.isEmpty();
|
||||
Set<String> preActions = metaActionInfo.getPreActions();
|
||||
boolean preActionsExist = preActions.isEmpty();
|
||||
if (!preActionsExist) {
|
||||
continue;
|
||||
}
|
||||
if (!metaActionInfo.isStrictDependencies()) {
|
||||
if (!metaActionInfo.getStrictDependencies()) {
|
||||
continue;
|
||||
}
|
||||
if (checkDependenciesExist(lastOrder, preActions, primaryActionChain)) {
|
||||
@@ -398,8 +398,8 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
|
||||
fixed.set(true);
|
||||
List<String> actionsInChain = primaryActionChain.computeIfAbsent(lastOrder,
|
||||
list -> new ArrayList<>());
|
||||
preActions = new ArrayList<>(preActions);
|
||||
preActions.removeAll(actionsInChain);
|
||||
preActions = new HashSet<>(preActions);
|
||||
actionsInChain.forEach(preActions::remove);
|
||||
actionsInChain.addAll(preActions);
|
||||
tempOrders.add(lastOrder);
|
||||
}
|
||||
@@ -418,7 +418,7 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkDependenciesExist(int lastOrder, List<String> preActions,
|
||||
private boolean checkDependenciesExist(int lastOrder, Set<String> preActions,
|
||||
Map<Integer, List<String>> primaryActionChain) {
|
||||
if (!primaryActionChain.containsKey(lastOrder)) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user