feat: P2全部功能 - MCP协议+插件系统+任务管理+CLI增强
A组 CLI增强: - DiffRenderer: 彩色diff渲染(行号/stat摘要/unified格式) - /hooks: 查看已注册Hook列表 - /review: AI代码审查(支持--staged/文件路径) - /stats: 会话使用统计(tokens/费用/API调用/运行时长) - /branch: 对话分支管理(save/load/list/delete) - /rewind: 回退对话历史 - /tag: 对话位置标签 - /security-review: AI安全审查 B组 任务系统: - TaskManager: 后台任务管理(线程安全/自动执行/手动管理) - TaskCreate/TaskGet/TaskList/TaskUpdate 4个工具 - ConfigTool: 配置读写工具 C组 MCP协议: - McpClient: MCP客户端(JSON-RPC 2.0/工具发现/资源读取) - McpTransport: 传输层接口 - StdioTransport: StdIO传输实现(子进程/异步读写) - McpManager: 多MCP服务器管理(配置加载/生命周期) - McpToolBridge: MCP工具桥接为本地Tool - /mcp: MCP服务器管理命令 D组 插件系统: - Plugin接口 + PluginContext + PluginManager - JAR插件加载(ClassLoader隔离/Manifest读取) - OutputStylePlugin: 内置输出样式插件 - /plugin: 插件管理命令 集成: AppConfig注册全部18工具+28命令 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package com.claudecode.command.impl;
|
||||
|
||||
import com.claudecode.command.CommandContext;
|
||||
import com.claudecode.command.SlashCommand;
|
||||
import com.claudecode.console.AnsiStyle;
|
||||
import com.claudecode.core.HookManager;
|
||||
import com.claudecode.core.HookManager.HookRegistration;
|
||||
import com.claudecode.core.HookManager.HookType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* /hooks 命令 —— 显示所有已注册的 Hook 信息。
|
||||
* <p>
|
||||
* 按 Hook 类型分组展示,包含每个 Hook 的名称和优先级。
|
||||
* 如果没有注册任何 Hook,则显示提示信息。
|
||||
*/
|
||||
public class HooksCommand implements SlashCommand {
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "hooks";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Show all registered hooks";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(String args, CommandContext context) {
|
||||
if (context.agentLoop() == null || context.agentLoop().getHookManager() == null) {
|
||||
return AnsiStyle.yellow(" ⚠ Hook 管理器不可用。");
|
||||
}
|
||||
|
||||
HookManager hookManager = context.agentLoop().getHookManager();
|
||||
List<HookRegistration> allHooks = hookManager.getHooks();
|
||||
|
||||
// 无已注册的 Hook
|
||||
if (allHooks.isEmpty()) {
|
||||
return AnsiStyle.dim(" No hooks registered.");
|
||||
}
|
||||
|
||||
// 按类型分组
|
||||
Map<HookType, List<HookRegistration>> grouped = allHooks.stream()
|
||||
.collect(Collectors.groupingBy(HookRegistration::type));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(AnsiStyle.bold("\n 📎 Registered Hooks\n"));
|
||||
|
||||
// 遍历所有 HookType,保持固定顺序
|
||||
for (HookType type : HookType.values()) {
|
||||
List<HookRegistration> hooks = grouped.get(type);
|
||||
sb.append("\n");
|
||||
sb.append(" ").append(AnsiStyle.cyan(formatTypeName(type))).append("\n");
|
||||
|
||||
if (hooks == null || hooks.isEmpty()) {
|
||||
sb.append(" ").append(AnsiStyle.dim("(none)")).append("\n");
|
||||
} else {
|
||||
// 按优先级排序后展示
|
||||
hooks.stream()
|
||||
.sorted((a, b) -> Integer.compare(a.priority(), b.priority()))
|
||||
.forEach(hook -> {
|
||||
String priorityStr = AnsiStyle.dim("[priority=" + hook.priority() + "]");
|
||||
sb.append(" • ")
|
||||
.append(AnsiStyle.bold(hook.name()))
|
||||
.append(" ")
|
||||
.append(priorityStr)
|
||||
.append("\n");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 统计总数
|
||||
sb.append("\n ").append(AnsiStyle.dim("Total: " + allHooks.size() + " hook(s) registered.")).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 HookType 枚举格式化为可读名称。
|
||||
*
|
||||
* @param type Hook 类型枚举
|
||||
* @return 格式化后的类型名称
|
||||
*/
|
||||
private String formatTypeName(HookType type) {
|
||||
return switch (type) {
|
||||
case PRE_TOOL_USE -> "PRE_TOOL_USE (工具执行前)";
|
||||
case POST_TOOL_USE -> "POST_TOOL_USE (工具执行后)";
|
||||
case PRE_PROMPT -> "PRE_PROMPT (发送提示前)";
|
||||
case POST_RESPONSE -> "POST_RESPONSE (收到响应后)";
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user