diff --git a/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java b/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java index 51ed8313..741cf648 100644 --- a/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java +++ b/Partner-Main/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java @@ -94,19 +94,45 @@ public class LocalRunnerClient extends RunnerClient { registerMcpClient("mcp-desc", pair.clientSide(), 10); } + /** + * 目录按照以下格式进行组织: + *

+ * DYNAMIC_ACTION_PATH/action 名称/ + *

+ * 每个action子目录下,除了相关的程序文件外,将额外提供一个 .meta.json 文件来提供相关描述文件, + * 该描述文件将携带 McpTools、MetaActionInfo 相关的所有信息, + * 故 McpDescServer 将只负责 Common Mcp Servers 的额外描述文件 + */ private void registerDynamicActionMcp() { InProcessMcpTransport.Pair pair = InProcessMcpTransport.pair(); McpSchema.ServerCapabilities serverCapabilities = McpSchema.ServerCapabilities.builder() .tools(true) - .resources(true, true) .build(); dynamicActionMcpServer = McpServer.async(pair.serverSide()) .capabilities(serverCapabilities) .jsonMapper(McpJsonMapper.getDefault()) .build(); + // Tools 的执行逻辑应当高度一致化,但仍需要独立为不同 Tool + // 初始的加载逻辑通过 initialLoad 加载 + // 后续的动态更新通过对应的 event 事件触发 + registerDynamicActionMcpWatch(); registerMcpClient("dynamic-action", pair.clientSide(), 10); } + private void registerDynamicActionMcpWatch() { + // MODIFY、CREATE、DELETE、OVERFLOW 都需要不同的处理方式 + WatchContext ctx = new WatchContext(Path.of(DYNAMIC_ACTION_PATH), watchService); + LocalWatchEventProcessor.Dynamic dynamic = new LocalWatchEventProcessor.Dynamic(existedMetaActions, dynamicActionMcpServer, ctx); + new LocalWatchServiceBuild.BuildRegistry(ctx) + .initialLoad(dynamic.buildLoad()) + .registerCreate(dynamic.buildCreate()) + .registerModify(dynamic.buildModify()) + .registerDelete(dynamic.buildDelete()) + .registerOverflow(dynamic.buildOverflow()) + .watchAll(true) + .commit(executor); + } + @Override protected RunnerResponse doRun(MetaAction metaAction) { RunnerResponse response; @@ -218,6 +244,7 @@ public class LocalRunnerClient extends RunnerClient { // ResourcesChange 事件传递的 Resource 可以由 Client 读取内容 // 预计在 Server 侧,收到客户端发送的新的行动程序信息,该信息由客户端处补充后,将其放置在指定位置 // 并写入描述文件、发起 ResourcesChange 事件 + //TODO 更新触发应当遵循触发逻辑: ToolChange -> client.listResource -> 仅填写 tool 信息 | 根据查找到的 resource 文件修正信息 .toolsChangeConsumer(tools -> updateExistedMetaActions(id, tools)) .build(); mcpClients.put(id, client); @@ -445,6 +472,7 @@ public class LocalRunnerClient extends RunnerClient { protected abstract @NotNull LocalWatchServiceBuild.EventHandler buildOverflow(); + @SuppressWarnings("LoggingSimilarMessage") private static final class Dynamic extends LocalWatchEventProcessor { private final McpStatelessAsyncServer dynamicActionMcpServer; @@ -565,7 +593,8 @@ public class LocalRunnerClient extends RunnerClient { }; } - private McpStatelessServerFeatures.AsyncToolSpecification buildAsyncToolSpecification(MetaActionInfo info, File program, String actionKey, String name) { + private McpStatelessServerFeatures.AsyncToolSpecification buildAsyncToolSpecification(MetaActionInfo + info, File program, String actionKey, String name) { Map additional = Map.of("pre", info.getPreActions(), "post", info.getPostActions(), "strict_pre", info.isStrictDependencies(),