docs: 全面更新文档 - README/需求文档/修改记录
README.md: - 功能特性分 P0/P1/P2 三级展示 - 工具列表更新为 18 个(含 P0/P2 工具) - 命令列表更新为 28 个(分基础/P0/P1/P2 四组) - 新增 MCP 服务器配置和使用说明 - 新增插件系统使用说明(JAR 加载、目录结构) - 新增 Vim 模式和 Hook 系统使用说明 - 架构图更新:含 mcp/、plugin/、core/ 新组件 - 核心流程图更新:含 Hook 和权限确认 - 对应关系表新增 MCP/Plugin/Hook/Task 映射 需求文档.md: - 5.1 实现清单更新为 18 工具 + 28 命令 - 5.2 P0/P1/P2 标记为全部已实现 - 仅保留 P3 跳过项目 修改记录.md: - 新增 P0/P1/P2 四条修改记录(倒序排列) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -4,16 +4,35 @@
|
|||||||
|
|
||||||
## ✨ 功能特性
|
## ✨ 功能特性
|
||||||
|
|
||||||
|
### 核心功能
|
||||||
- 🤖 **AI 对话** — 流式输出,逐 token 实时显示
|
- 🤖 **AI 对话** — 流式输出,逐 token 实时显示
|
||||||
- 🔧 **11 个内置工具** — Bash、文件读写编辑、Glob、Grep、Web获取、Agent 等
|
- 🔧 **18 个内置工具** — Bash、文件操作、搜索、Web、任务管理、MCP桥接 等
|
||||||
- ⚡ **双 API 提供者** — 同时支持 OpenAI 兼容 API 和 Anthropic 原生 API
|
- ⚡ **双 API 提供者** — 同时支持 OpenAI 兼容 API 和 Anthropic 原生 API
|
||||||
- 📝 **斜杠命令** — `/help`, `/compact`, `/cost`, `/model`, `/history` 等 11 个命令
|
- 📝 **28 个斜杠命令** — 从基础操作到代码审查、安全分析、对话管理
|
||||||
- 🖥️ **JLine 终端** — 行编辑、历史记录、Tab 补全、多行输入
|
- 🖥️ **JLine 终端** — 行编辑、历史记录、Tab 补全、多行输入、Vim 模式
|
||||||
- 📋 **CLAUDE.md** — 自动加载项目级和用户级记忆文件
|
- 📋 **CLAUDE.md** — 自动加载项目级和用户级记忆文件
|
||||||
- 🎯 **Skills** — 可扩展的技能系统
|
- 🎯 **Skills** — 可扩展的技能系统
|
||||||
- 🌿 **Git 上下文** — 自动收集分支、状态、最近提交
|
- 🌿 **Git 上下文** — 自动收集分支、状态、最近提交
|
||||||
- 💾 **对话持久化** — 自动保存对话历史,支持回顾
|
|
||||||
- 🗜️ **上下文压缩** — AI 生成摘要替代简单清空
|
### P0 核心增强
|
||||||
|
- 🔒 **权限确认** — 危险操作(文件写入、Bash执行)前要求用户确认 [Y/n/always]
|
||||||
|
- 💭 **Thinking 显示** — 展示 AI 思考过程(Anthropic extended thinking)
|
||||||
|
- 🔍 **WebSearch** — DuckDuckGo 网络搜索(无需 API Key)
|
||||||
|
- ❓ **AskUser** — AI 在执行过程中向用户提问
|
||||||
|
|
||||||
|
### P1 体验增强
|
||||||
|
- 📊 **底部状态行** — 持续显示模型、Token、费用、工作目录
|
||||||
|
- 🪝 **Hook 系统** — PreToolUse/PostToolUse/PrePrompt/PostResponse 4 种钩子
|
||||||
|
- 🎨 **代码语法高亮** — 支持 Java/JS/TS/Python/Bash/SQL 6 种语言
|
||||||
|
- ⌨️ **Vim 模式** — JLine vi 编辑模式(`CLAUDE_CODE_VIM=1` 启用)
|
||||||
|
|
||||||
|
### P2 扩展功能
|
||||||
|
- 🔌 **MCP 协议** — Model Context Protocol 客户端(StdIO 传输、工具发现、资源读取)
|
||||||
|
- 🧩 **插件系统** — JAR 插件加载(ClassLoader 隔离、工具/命令扩展)
|
||||||
|
- 📋 **任务管理** — 后台任务创建、查询、更新(4 个工具)
|
||||||
|
- 🔀 **彩色 Diff** — unified diff 渲染(行号、stat 摘要、颜色标注)
|
||||||
|
- 🌿 **对话分支** — 保存/恢复/标签对话状态
|
||||||
|
- 🛡️ **安全审查** — AI 驱动的安全漏洞检测
|
||||||
|
|
||||||
## 📦 技术栈
|
## 📦 技术栈
|
||||||
|
|
||||||
@@ -85,7 +104,7 @@ mvn spring-boot:run
|
|||||||
Provider: OPENAI Model: deepseek-chat
|
Provider: OPENAI Model: deepseek-chat
|
||||||
API URL: https://api.deepseek.com
|
API URL: https://api.deepseek.com
|
||||||
Work Dir: D:\my-project
|
Work Dir: D:\my-project
|
||||||
Tools: 11 registered
|
Tools: 18 | Commands: 28
|
||||||
Terminal: windows-vtp (160×30)
|
Terminal: windows-vtp (160×30)
|
||||||
Tip: Tab to complete commands, ↑↓ to browse history, Ctrl+D to exit
|
Tip: Tab to complete commands, ↑↓ to browse history, Ctrl+D to exit
|
||||||
|
|
||||||
@@ -113,24 +132,60 @@ mvn spring-boot:run
|
|||||||
|
|
||||||
### 斜杠命令
|
### 斜杠命令
|
||||||
|
|
||||||
| 命令 | 说明 |
|
#### 基础命令
|
||||||
|------|------|
|
|
||||||
| `/help` | 显示所有可用命令 |
|
| 命令 | 别名 | 说明 |
|
||||||
| `/clear` | 清屏 |
|
|------|------|------|
|
||||||
| `/compact` | AI 摘要压缩对话上下文 |
|
| `/help` | | 显示所有可用命令 |
|
||||||
| `/cost` | 显示 Token 使用量和费用 |
|
| `/clear` | | 清屏 |
|
||||||
| `/model [name]` | 查看/切换模型 |
|
| `/compact` | | AI 摘要压缩对话上下文 |
|
||||||
| `/status` | 显示会话状态(消息数、Token、模型) |
|
| `/cost` | | 显示 Token 使用量和费用 |
|
||||||
| `/context` | 显示已加载的上下文(CLAUDE.md、Skills、Git) |
|
| `/model [name]` | | 查看/切换模型 |
|
||||||
| `/config` | 查看配置信息 |
|
| `/status` | | 显示会话状态 |
|
||||||
| `/init` | 初始化 CLAUDE.md 配置文件 |
|
| `/context` | | 显示已加载的上下文 |
|
||||||
| `/history` | 列出保存的对话历史 |
|
| `/config` | | 查看配置信息 |
|
||||||
| `/exit` | 退出 |
|
| `/init` | | 初始化 CLAUDE.md 配置文件 |
|
||||||
|
| `/history` | | 列出保存的对话历史 |
|
||||||
|
| `/exit` | `/quit` | 退出 |
|
||||||
|
|
||||||
|
#### P0 命令
|
||||||
|
|
||||||
|
| 命令 | 别名 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `/diff` | | 显示 Git 变更(支持 `--staged`, `--stat`) |
|
||||||
|
| `/version` | `/ver` | 显示版本和环境信息 |
|
||||||
|
| `/skills` | | 列出已加载的技能 |
|
||||||
|
| `/memory` | `/mem` | 查看/编辑 CLAUDE.md |
|
||||||
|
| `/copy` | | 复制最近回复到剪贴板 |
|
||||||
|
|
||||||
|
#### P1 命令
|
||||||
|
|
||||||
|
| 命令 | 别名 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `/resume` | | 恢复已保存的对话 |
|
||||||
|
| `/export` | | 导出对话为 Markdown 文件 |
|
||||||
|
| `/commit` | | AI 生成 commit message 并提交 |
|
||||||
|
|
||||||
|
#### P2 命令
|
||||||
|
|
||||||
|
| 命令 | 别名 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `/hooks` | | 查看已注册的 Hook |
|
||||||
|
| `/review` | `/rev` | AI 代码审查(支持 `--staged`、文件路径) |
|
||||||
|
| `/stats` | | 使用统计(Token、费用、API调用、运行时长) |
|
||||||
|
| `/branch` | | 对话分支(`save/load/list/delete`) |
|
||||||
|
| `/rewind [n]` | | 回退对话历史(默认回退1轮) |
|
||||||
|
| `/tag` | | 对话标签(`<name>/list/goto <name>`) |
|
||||||
|
| `/security-review` | `/sec` | AI 安全漏洞审查 |
|
||||||
|
| `/mcp` | | MCP 服务器管理(`connect/disconnect/tools/resources`) |
|
||||||
|
| `/plugin` | | 插件管理(`load/unload/reload/info`) |
|
||||||
|
|
||||||
### 内置工具
|
### 内置工具
|
||||||
|
|
||||||
AI 可以自动调用以下工具:
|
AI 可以自动调用以下工具:
|
||||||
|
|
||||||
|
#### 核心工具(Phase 1-3)
|
||||||
|
|
||||||
| 工具 | 说明 |
|
| 工具 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `bash` | 执行 Shell 命令 |
|
| `bash` | 执行 Shell 命令 |
|
||||||
@@ -145,6 +200,24 @@ AI 可以自动调用以下工具:
|
|||||||
| `agent` | 启动子 Agent 处理复杂任务 |
|
| `agent` | 启动子 Agent 处理复杂任务 |
|
||||||
| `notebook_edit` | 编辑 Jupyter Notebook |
|
| `notebook_edit` | 编辑 Jupyter Notebook |
|
||||||
|
|
||||||
|
#### P0 工具
|
||||||
|
|
||||||
|
| 工具 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `web_search` | DuckDuckGo 网络搜索(无需 API Key) |
|
||||||
|
| `ask_user_question` | AI 向用户提问(暂停 agent loop 等待输入) |
|
||||||
|
|
||||||
|
#### P2 工具
|
||||||
|
|
||||||
|
| 工具 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `TaskCreate` | 创建后台任务 |
|
||||||
|
| `TaskGet` | 查询任务详情 |
|
||||||
|
| `TaskList` | 列出任务(支持状态过滤) |
|
||||||
|
| `TaskUpdate` | 更新任务状态和结果 |
|
||||||
|
| `Config` | 读写配置值 |
|
||||||
|
| `mcp__*` | MCP 远程工具桥接(动态注册) |
|
||||||
|
|
||||||
### CLAUDE.md 记忆文件
|
### CLAUDE.md 记忆文件
|
||||||
|
|
||||||
创建 `CLAUDE.md` 文件来给 AI 提供项目上下文:
|
创建 `CLAUDE.md` 文件来给 AI 提供项目上下文:
|
||||||
@@ -185,6 +258,81 @@ description: 代码审查技能
|
|||||||
3. 性能考量
|
3. 性能考量
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### MCP 服务器集成
|
||||||
|
|
||||||
|
配置 MCP 服务器,在项目根目录创建 `.mcp.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": {
|
||||||
|
"filesystem": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
||||||
|
},
|
||||||
|
"my-server": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["my_mcp_server.py"],
|
||||||
|
"env": { "API_KEY": "xxx" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
或放在全局目录 `~/.claude-code-java/mcp.json`。
|
||||||
|
|
||||||
|
使用 `/mcp` 命令管理:
|
||||||
|
```
|
||||||
|
❯ /mcp # 列出所有 MCP 服务器
|
||||||
|
❯ /mcp tools # 列出所有 MCP 工具
|
||||||
|
❯ /mcp connect myserver cmd args # 连接新服务器
|
||||||
|
❯ /mcp disconnect myserver # 断开服务器
|
||||||
|
```
|
||||||
|
|
||||||
|
### 插件系统
|
||||||
|
|
||||||
|
JAR 插件放在以下目录即可自动加载:
|
||||||
|
- `~/.claude-code-java/plugins/` — 全局插件
|
||||||
|
- `.claude-code/plugins/` — 项目级插件
|
||||||
|
|
||||||
|
JAR 要求:
|
||||||
|
- `META-INF/MANIFEST.MF` 中包含 `Plugin-Class` 属性
|
||||||
|
- 实现 `com.claudecode.plugin.Plugin` 接口
|
||||||
|
|
||||||
|
使用 `/plugin` 命令管理:
|
||||||
|
```
|
||||||
|
❯ /plugin # 列出已加载插件
|
||||||
|
❯ /plugin info output-style # 查看插件详情
|
||||||
|
❯ /plugin unload my-plugin # 卸载插件
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vim 模式
|
||||||
|
|
||||||
|
设置环境变量启用 JLine vi 编辑模式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CLAUDE_CODE_VIM=1
|
||||||
|
```
|
||||||
|
|
||||||
|
启用后 Banner 会显示 `[vim]` 标识,输入行支持 vi 按键绑定。
|
||||||
|
|
||||||
|
### Hook 系统
|
||||||
|
|
||||||
|
通过代码注册 Hook 来拦截工具调用:
|
||||||
|
|
||||||
|
```java
|
||||||
|
agentLoop.getHookManager().register(HookManager.HookType.PRE_TOOL_USE, new Hook() {
|
||||||
|
public String name() { return "my-hook"; }
|
||||||
|
public int priority() { return 10; }
|
||||||
|
public HookResult execute(HookContext ctx) {
|
||||||
|
// 可检查 ctx.getToolName(), ctx.getArguments()
|
||||||
|
// 返回 ABORT 可阻止工具执行
|
||||||
|
return HookResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
4 种钩子类型:`PRE_TOOL_USE`、`POST_TOOL_USE`、`PRE_PROMPT`、`POST_RESPONSE`
|
||||||
|
|
||||||
## 🏗️ 架构设计
|
## 🏗️ 架构设计
|
||||||
|
|
||||||
### 模块结构
|
### 模块结构
|
||||||
@@ -195,32 +343,54 @@ com.claudecode
|
|||||||
├── cli/
|
├── cli/
|
||||||
│ └── ClaudeCodeRunner // 启动编排(CommandLineRunner)
|
│ └── ClaudeCodeRunner // 启动编排(CommandLineRunner)
|
||||||
├── config/
|
├── config/
|
||||||
│ └── AppConfig // Bean 装配、Provider 切换
|
│ └── AppConfig // Bean 装配、Provider 切换、组件注册
|
||||||
├── core/
|
├── core/
|
||||||
│ ├── AgentLoop // Agent 循环(阻塞 + 流式)
|
│ ├── AgentLoop // Agent 循环(阻塞 + 流式 + Hook集成)
|
||||||
│ ├── TokenTracker // Token 使用追踪
|
│ ├── TokenTracker // Token 使用追踪
|
||||||
│ └── ConversationPersistence // 对话持久化
|
│ ├── ConversationPersistence // 对话持久化
|
||||||
|
│ ├── HookManager // Hook 系统(4种钩子类型)
|
||||||
|
│ └── TaskManager // 后台任务管理
|
||||||
├── tool/
|
├── tool/
|
||||||
│ ├── Tool // 工具协议接口
|
│ ├── Tool // 工具协议接口
|
||||||
│ ├── ToolRegistry // 工具注册中心
|
│ ├── ToolRegistry // 工具注册中心
|
||||||
│ ├── ToolCallbackAdapter // Spring AI 适配器
|
│ ├── ToolCallbackAdapter // Spring AI 适配器
|
||||||
│ └── impl/ // 11 个工具实现
|
│ └── impl/ // 18 个工具实现
|
||||||
|
│ ├── BashTool, FileReadTool, FileWriteTool, FileEditTool
|
||||||
|
│ ├── GlobTool, GrepTool, ListFilesTool, WebFetchTool
|
||||||
|
│ ├── TodoWriteTool, AgentTool, NotebookEditTool
|
||||||
|
│ ├── WebSearchTool, AskUserQuestionTool
|
||||||
|
│ ├── TaskCreateTool, TaskGetTool, TaskListTool, TaskUpdateTool
|
||||||
|
│ ├── ConfigTool
|
||||||
|
│ └── McpToolBridge // MCP 远程工具桥接
|
||||||
├── command/
|
├── command/
|
||||||
│ ├── SlashCommand // 命令接口
|
│ ├── SlashCommand // 命令接口
|
||||||
│ ├── CommandRegistry // 命令注册中心
|
│ ├── CommandRegistry // 命令注册中心
|
||||||
│ └── impl/ // 11 个命令实现
|
│ └── impl/ // 28 个命令实现
|
||||||
├── console/
|
├── console/
|
||||||
│ ├── BannerPrinter // 启动 Banner
|
│ ├── BannerPrinter // 启动 Banner
|
||||||
│ ├── ToolStatusRenderer // 工具状态渲染
|
│ ├── ToolStatusRenderer // 工具状态渲染
|
||||||
│ ├── ThinkingRenderer // Thinking 渲染
|
│ ├── ThinkingRenderer // Thinking 渲染
|
||||||
│ ├── SpinnerAnimation // 加载动画
|
│ ├── SpinnerAnimation // 加载动画
|
||||||
│ ├── MarkdownRenderer // Markdown 渲染
|
│ ├── MarkdownRenderer // Markdown 渲染(含语法高亮)
|
||||||
|
│ ├── DiffRenderer // 彩色 Diff 渲染
|
||||||
|
│ ├── StatusLine // 底部状态行
|
||||||
│ └── AnsiStyle // ANSI 样式工具
|
│ └── AnsiStyle // ANSI 样式工具
|
||||||
├── context/
|
├── context/
|
||||||
│ ├── SystemPromptBuilder // 系统提示词构建
|
│ ├── SystemPromptBuilder // 系统提示词构建
|
||||||
│ ├── ClaudeMdLoader // CLAUDE.md 加载
|
│ ├── ClaudeMdLoader // CLAUDE.md 加载
|
||||||
│ ├── SkillLoader // Skills 加载
|
│ ├── SkillLoader // Skills 加载
|
||||||
│ └── GitContext // Git 上下文收集
|
│ └── GitContext // Git 上下文收集
|
||||||
|
├── mcp/
|
||||||
|
│ ├── McpClient // MCP 客户端(JSON-RPC 2.0)
|
||||||
|
│ ├── McpTransport // 传输层接口
|
||||||
|
│ ├── StdioTransport // StdIO 传输实现
|
||||||
|
│ ├── McpManager // 多服务器管理
|
||||||
|
│ └── McpException // MCP 异常
|
||||||
|
├── plugin/
|
||||||
|
│ ├── Plugin // 插件接口
|
||||||
|
│ ├── PluginContext // 插件上下文
|
||||||
|
│ ├── PluginManager // 插件加载/管理
|
||||||
|
│ └── OutputStylePlugin // 内置输出样式插件
|
||||||
└── repl/
|
└── repl/
|
||||||
├── ReplSession // REPL 会话管理
|
├── ReplSession // REPL 会话管理
|
||||||
└── ClaudeCodeCompleter // Tab 补全
|
└── ClaudeCodeCompleter // Tab 补全
|
||||||
@@ -235,11 +405,39 @@ com.claudecode
|
|||||||
↓
|
↓
|
||||||
逐token实时输出到终端
|
逐token实时输出到终端
|
||||||
↓
|
↓
|
||||||
检测工具调用 → 执行工具 → 结果回传
|
检测工具调用 → PreToolUse Hook → 权限确认 → 执行工具 → PostToolUse Hook → 结果回传
|
||||||
↓
|
↓
|
||||||
继续循环或结束
|
继续循环或结束
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### MCP 协议架构
|
||||||
|
|
||||||
|
```
|
||||||
|
McpManager ─── 配置加载 (.mcp.json)
|
||||||
|
│
|
||||||
|
├── McpClient("server-a") ── StdioTransport ── 子进程 (npx server-a)
|
||||||
|
│ ├── tools/list → 发现工具
|
||||||
|
│ ├── tools/call → 调用工具
|
||||||
|
│ └── resources/read → 读取资源
|
||||||
|
│
|
||||||
|
└── McpClient("server-b") ── StdioTransport ── 子进程 (python server-b)
|
||||||
|
└── ... (同上)
|
||||||
|
|
||||||
|
McpToolBridge → 将 MCP 工具映射为本地 Tool → 注册到 ToolRegistry → AI 可调用
|
||||||
|
```
|
||||||
|
|
||||||
|
### 插件系统架构
|
||||||
|
|
||||||
|
```
|
||||||
|
PluginManager
|
||||||
|
├── 全局插件: ~/.claude-code-java/plugins/*.jar
|
||||||
|
├── 项目插件: .claude-code/plugins/*.jar
|
||||||
|
└── 内置插件: OutputStylePlugin
|
||||||
|
│
|
||||||
|
├── Plugin.getTools() → 注册到 ToolRegistry
|
||||||
|
└── Plugin.getCommands() → 注册到 CommandRegistry
|
||||||
|
```
|
||||||
|
|
||||||
### 双 API 提供者架构
|
### 双 API 提供者架构
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -279,6 +477,7 @@ claude-code:
|
|||||||
| `AI_BASE_URL` | ❌ | API 基础 URL | 按提供者不同 |
|
| `AI_BASE_URL` | ❌ | API 基础 URL | 按提供者不同 |
|
||||||
| `AI_MODEL` | ❌ | 模型名称 | 按提供者不同 |
|
| `AI_MODEL` | ❌ | 模型名称 | 按提供者不同 |
|
||||||
| `AI_MAX_TOKENS` | ❌ | 最大 Token 数 | `8096` |
|
| `AI_MAX_TOKENS` | ❌ | 最大 Token 数 | `8096` |
|
||||||
|
| `CLAUDE_CODE_VIM` | ❌ | 启用 Vim 编辑模式 | `0` |
|
||||||
|
|
||||||
## 🔧 开发
|
## 🔧 开发
|
||||||
|
|
||||||
@@ -308,11 +507,15 @@ java -jar target/claude-code-java-0.1.0-SNAPSHOT.jar
|
|||||||
| `cli.tsx` → `main.tsx` | `ClaudeCodeApplication` + `ClaudeCodeRunner` | 入口 |
|
| `cli.tsx` → `main.tsx` | `ClaudeCodeApplication` + `ClaudeCodeRunner` | 入口 |
|
||||||
| `REPL.tsx` | `ReplSession` + JLine 3 | 交互循环 |
|
| `REPL.tsx` | `ReplSession` + JLine 3 | 交互循环 |
|
||||||
| `query.ts` | `AgentLoop` | Agent 循环 |
|
| `query.ts` | `AgentLoop` | Agent 循环 |
|
||||||
| `Tool.ts` + `tools/*` | `Tool` 接口 + `impl/*` | 工具系统 |
|
| `Tool.ts` + `tools/*` | `Tool` 接口 + `impl/*` (18个) | 工具系统 |
|
||||||
| `commands.ts` | `SlashCommand` + `impl/*` | 命令系统 |
|
| `commands.ts` | `SlashCommand` + `impl/*` (28个) | 命令系统 |
|
||||||
| `context.ts` + `prompts.ts` | `SystemPromptBuilder` + loaders | 上下文 |
|
| `context.ts` + `prompts.ts` | `SystemPromptBuilder` + loaders | 上下文 |
|
||||||
| `CLAUDE.md` + `skills/` | `ClaudeMdLoader` + `SkillLoader` | 记忆/技能 |
|
| `CLAUDE.md` + `skills/` | `ClaudeMdLoader` + `SkillLoader` | 记忆/技能 |
|
||||||
| Ink Components | `console/*` 渲染器 | 终端 UI |
|
| Ink Components | `console/*` 渲染器 (8个) | 终端 UI |
|
||||||
|
| `mcp/*` (22文件) | `mcp/*` (McpClient/Manager/Transport) | MCP 协议 |
|
||||||
|
| `plugins/*` (38文件) | `plugin/*` (Plugin/Manager/Context) | 插件系统 |
|
||||||
|
| `hooks/*` | `HookManager` | Hook 系统 |
|
||||||
|
| `tasks/*` | `TaskManager` + Task工具 | 任务管理 |
|
||||||
|
|
||||||
## 📄 License
|
## 📄 License
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.claudecode.mcp;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -47,10 +46,10 @@ public class McpClient implements AutoCloseable {
|
|||||||
private final Map<String, McpResource> resources = new ConcurrentHashMap<>();
|
private final Map<String, McpResource> resources = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** 服务器能力信息 */
|
/** 服务器能力信息 */
|
||||||
private JsonNode serverCapabilities;
|
private volatile JsonNode serverCapabilities;
|
||||||
|
|
||||||
/** 服务器信息 */
|
/** 服务器信息 */
|
||||||
private JsonNode serverInfo;
|
private volatile JsonNode serverInfo;
|
||||||
|
|
||||||
/** 是否已完成初始化 */
|
/** 是否已完成初始化 */
|
||||||
private volatile boolean initialized = false;
|
private volatile boolean initialized = false;
|
||||||
@@ -165,15 +164,17 @@ public class McpClient implements AutoCloseable {
|
|||||||
JsonNode response = transport.sendRequest(MAPPER.writeValueAsString(request));
|
JsonNode response = transport.sendRequest(MAPPER.writeValueAsString(request));
|
||||||
JsonNode result = response.get("result");
|
JsonNode result = response.get("result");
|
||||||
if (result != null && result.has("tools")) {
|
if (result != null && result.has("tools")) {
|
||||||
ArrayNode toolsArray = (ArrayNode) result.get("tools");
|
JsonNode toolsNode = result.get("tools");
|
||||||
for (JsonNode toolNode : toolsArray) {
|
if (toolsNode != null && toolsNode.isArray()) {
|
||||||
String name = toolNode.get("name").asText();
|
for (JsonNode toolNode : toolsNode) {
|
||||||
String description = toolNode.has("description")
|
String name = toolNode.get("name").asText();
|
||||||
? toolNode.get("description").asText() : "";
|
String description = toolNode.has("description")
|
||||||
JsonNode inputSchema = toolNode.get("inputSchema");
|
? toolNode.get("description").asText() : "";
|
||||||
|
JsonNode inputSchema = toolNode.get("inputSchema");
|
||||||
|
|
||||||
tools.put(name, new McpTool(name, description, inputSchema));
|
tools.put(name, new McpTool(name, description, inputSchema));
|
||||||
log.debug("发现 MCP 工具: {} - {}", name, description);
|
log.debug("发现 MCP 工具: {} - {}", name, description);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (McpException e) {
|
} catch (McpException e) {
|
||||||
@@ -214,17 +215,19 @@ public class McpClient implements AutoCloseable {
|
|||||||
JsonNode response = transport.sendRequest(MAPPER.writeValueAsString(request));
|
JsonNode response = transport.sendRequest(MAPPER.writeValueAsString(request));
|
||||||
JsonNode result = response.get("result");
|
JsonNode result = response.get("result");
|
||||||
if (result != null && result.has("resources")) {
|
if (result != null && result.has("resources")) {
|
||||||
ArrayNode resourcesArray = (ArrayNode) result.get("resources");
|
JsonNode resourcesNode = result.get("resources");
|
||||||
for (JsonNode resNode : resourcesArray) {
|
if (resourcesNode != null && resourcesNode.isArray()) {
|
||||||
String uri = resNode.get("uri").asText();
|
for (JsonNode resNode : resourcesNode) {
|
||||||
String name = resNode.has("name") ? resNode.get("name").asText() : uri;
|
String uri = resNode.get("uri").asText();
|
||||||
String description = resNode.has("description")
|
String name = resNode.has("name") ? resNode.get("name").asText() : uri;
|
||||||
? resNode.get("description").asText() : "";
|
String description = resNode.has("description")
|
||||||
String mimeType = resNode.has("mimeType")
|
? resNode.get("description").asText() : "";
|
||||||
? resNode.get("mimeType").asText() : "text/plain";
|
String mimeType = resNode.has("mimeType")
|
||||||
|
? resNode.get("mimeType").asText() : "text/plain";
|
||||||
|
|
||||||
resources.put(uri, new McpResource(uri, name, description, mimeType));
|
resources.put(uri, new McpResource(uri, name, description, mimeType));
|
||||||
log.debug("发现 MCP 资源: {} ({})", name, uri);
|
log.debug("发现 MCP 资源: {} ({})", name, uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (McpException e) {
|
} catch (McpException e) {
|
||||||
@@ -409,6 +412,8 @@ public class McpClient implements AutoCloseable {
|
|||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
tools.clear();
|
||||||
|
resources.clear();
|
||||||
transport.close();
|
transport.close();
|
||||||
log.info("MCP 客户端 '{}' 已关闭", serverName);
|
log.info("MCP 客户端 '{}' 已关闭", serverName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MCP 管理器 —— 管理多个 MCP 服务器连接的统一入口。
|
* MCP 管理器 —— 管理多个 MCP 服务器连接的统一入口。
|
||||||
@@ -165,13 +164,23 @@ public class McpManager implements AutoCloseable {
|
|||||||
|
|
||||||
log.info("连接 MCP 服务器 '{}': {} {}", name, command, String.join(" ", args));
|
log.info("连接 MCP 服务器 '{}': {} {}", name, command, String.join(" ", args));
|
||||||
|
|
||||||
// 创建传输层并启动
|
// 创建传输层并启动(确保初始化失败时清理资源)
|
||||||
StdioTransport transport = new StdioTransport(command, args, env);
|
StdioTransport transport = new StdioTransport(command, args, env);
|
||||||
transport.start();
|
McpClient client;
|
||||||
|
try {
|
||||||
// 创建客户端并初始化
|
transport.start();
|
||||||
McpClient client = new McpClient(name, transport);
|
client = new McpClient(name, transport);
|
||||||
client.initialize();
|
client.initialize();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 初始化失败时必须关闭传输层,防止子进程泄漏
|
||||||
|
try {
|
||||||
|
transport.close();
|
||||||
|
} catch (Exception suppressed) {
|
||||||
|
e.addSuppressed(suppressed);
|
||||||
|
}
|
||||||
|
throw (e instanceof McpException mcp) ? mcp
|
||||||
|
: new McpException("连接 MCP 服务器 '" + name + "' 失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
// 注册客户端
|
// 注册客户端
|
||||||
clients.put(name, client);
|
clients.put(name, client);
|
||||||
@@ -239,7 +248,7 @@ public class McpManager implements AutoCloseable {
|
|||||||
return clients.values().stream()
|
return clients.values().stream()
|
||||||
.filter(McpClient::isInitialized)
|
.filter(McpClient::isInitialized)
|
||||||
.flatMap(client -> client.getTools().stream())
|
.flatMap(client -> client.getTools().stream())
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,7 +274,7 @@ public class McpManager implements AutoCloseable {
|
|||||||
return clients.values().stream()
|
return clients.values().stream()
|
||||||
.filter(McpClient::isInitialized)
|
.filter(McpClient::isInitialized)
|
||||||
.flatMap(client -> client.getResources().stream())
|
.flatMap(client -> client.getResources().stream())
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,11 +38,14 @@ public class StdioTransport implements McpTransport {
|
|||||||
/** 子进程 stdin 写入流 */
|
/** 子进程 stdin 写入流 */
|
||||||
private BufferedWriter processStdin;
|
private BufferedWriter processStdin;
|
||||||
|
|
||||||
/** 异步读取线程 */
|
/** 异步读取线程(stdout) */
|
||||||
private Thread readerThread;
|
private Thread readerThread;
|
||||||
|
|
||||||
/** 待匹配的请求:id -> CompletableFuture */
|
/** 异步读取线程(stderr) */
|
||||||
private final ConcurrentHashMap<Object, CompletableFuture<JsonNode>> pendingRequests =
|
private Thread stderrThread;
|
||||||
|
|
||||||
|
/** 待匹配的请求:id(String) -> CompletableFuture */
|
||||||
|
private final ConcurrentHashMap<String, CompletableFuture<JsonNode>> pendingRequests =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** 启动命令 */
|
/** 启动命令 */
|
||||||
@@ -102,7 +105,7 @@ public class StdioTransport implements McpTransport {
|
|||||||
readerThread = Thread.ofVirtual().name("mcp-stdio-reader").start(this::readLoop);
|
readerThread = Thread.ofVirtual().name("mcp-stdio-reader").start(this::readLoop);
|
||||||
|
|
||||||
// 启动 stderr 日志线程(仅记录日志,不参与协议通信)
|
// 启动 stderr 日志线程(仅记录日志,不参与协议通信)
|
||||||
Thread.ofVirtual().name("mcp-stdio-stderr").start(this::stderrLoop);
|
stderrThread = Thread.ofVirtual().name("mcp-stdio-stderr").start(this::stderrLoop);
|
||||||
|
|
||||||
connected = true;
|
connected = true;
|
||||||
log.info("MCP 服务器进程已启动 (PID: {})", process.pid());
|
log.info("MCP 服务器进程已启动 (PID: {})", process.pid());
|
||||||
@@ -172,12 +175,8 @@ public class StdioTransport implements McpTransport {
|
|||||||
// 检查是否有 id 字段(响应消息)
|
// 检查是否有 id 字段(响应消息)
|
||||||
JsonNode idNode = message.get("id");
|
JsonNode idNode = message.get("id");
|
||||||
if (idNode != null && !idNode.isNull()) {
|
if (idNode != null && !idNode.isNull()) {
|
||||||
Object id;
|
// 统一转为 String,避免 Integer/String 类型不匹配导致的查找失败
|
||||||
if (idNode.isNumber()) {
|
String id = idNode.asText();
|
||||||
id = idNode.asInt();
|
|
||||||
} else {
|
|
||||||
id = idNode.asText();
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<JsonNode> future = pendingRequests.remove(id);
|
CompletableFuture<JsonNode> future = pendingRequests.remove(id);
|
||||||
if (future != null) {
|
if (future != null) {
|
||||||
@@ -198,20 +197,15 @@ public class StdioTransport implements McpTransport {
|
|||||||
throw new McpException("MCP 传输层未连接");
|
throw new McpException("MCP 传输层未连接");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String id = null;
|
||||||
try {
|
try {
|
||||||
// 解析出请求 id
|
// 解析出请求 id(统一转为 String)
|
||||||
JsonNode requestNode = MAPPER.readTree(jsonRpcRequest);
|
JsonNode requestNode = MAPPER.readTree(jsonRpcRequest);
|
||||||
JsonNode idNode = requestNode.get("id");
|
JsonNode idNode = requestNode.get("id");
|
||||||
if (idNode == null || idNode.isNull()) {
|
if (idNode == null || idNode.isNull()) {
|
||||||
throw new McpException("JSON-RPC 请求缺少 id 字段");
|
throw new McpException("JSON-RPC 请求缺少 id 字段");
|
||||||
}
|
}
|
||||||
|
id = idNode.asText();
|
||||||
Object id;
|
|
||||||
if (idNode.isNumber()) {
|
|
||||||
id = idNode.asInt();
|
|
||||||
} else {
|
|
||||||
id = idNode.asText();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册 Future
|
// 注册 Future
|
||||||
CompletableFuture<JsonNode> future = new CompletableFuture<>();
|
CompletableFuture<JsonNode> future = new CompletableFuture<>();
|
||||||
@@ -251,6 +245,11 @@ public class StdioTransport implements McpTransport {
|
|||||||
throw new McpException("MCP 请求执行异常: " + cause.getMessage(), cause);
|
throw new McpException("MCP 请求执行异常: " + cause.getMessage(), cause);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new McpException("MCP 请求发送失败: " + e.getMessage(), e);
|
throw new McpException("MCP 请求发送失败: " + e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
// 无论成功、超时或异常,都清理待处理请求,防止内存泄漏
|
||||||
|
if (id != null) {
|
||||||
|
pendingRequests.remove(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,6 +304,9 @@ public class StdioTransport implements McpTransport {
|
|||||||
if (readerThread != null && readerThread.isAlive()) {
|
if (readerThread != null && readerThread.isAlive()) {
|
||||||
readerThread.interrupt();
|
readerThread.interrupt();
|
||||||
}
|
}
|
||||||
|
if (stderrThread != null && stderrThread.isAlive()) {
|
||||||
|
stderrThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
// 清理待处理请求
|
// 清理待处理请求
|
||||||
pendingRequests.forEach((id, future) ->
|
pendingRequests.forEach((id, future) ->
|
||||||
|
|||||||
@@ -1,5 +1,73 @@
|
|||||||
# 修改记录
|
# 修改记录
|
||||||
|
|
||||||
|
## [2026-04-03] - P2: MCP协议 + 插件系统 + 任务管理 + CLI增强
|
||||||
|
|
||||||
|
- **修改类型**: 功能新增
|
||||||
|
- **修改详情**:
|
||||||
|
- **A组 CLI增强**:
|
||||||
|
- 新增 `DiffRenderer` 彩色 diff 渲染器(行号、stat摘要、unified格式解析)
|
||||||
|
- 新增 7 个命令: `/hooks`, `/review`(rev), `/stats`, `/branch`, `/rewind`, `/tag`, `/security-review`(sec)
|
||||||
|
- `/review` 支持 `--staged` 标志和文件路径参数
|
||||||
|
- `/branch` 支持 save/load/list/delete 子命令管理对话分支
|
||||||
|
- `/tag` 支持对话位置标签和 goto 跳转
|
||||||
|
- `/security-review` 发送 AI 安全审查(SQL注入/XSS/认证/凭证泄露检测)
|
||||||
|
- **B组 任务系统**:
|
||||||
|
- 新增 `TaskManager` 后台任务管理器(线程安全、ConcurrentHashMap、CachedThreadPool)
|
||||||
|
- 新增 4 个工具: `TaskCreate`/`TaskGet`/`TaskList`/`TaskUpdate`
|
||||||
|
- 新增 `ConfigTool` 配置读写工具
|
||||||
|
- 支持自动执行模式和手动状态管理模式
|
||||||
|
- **C组 MCP协议**:
|
||||||
|
- 新增 `mcp/` 包: `McpClient`、`McpTransport`、`StdioTransport`、`McpManager`、`McpException`
|
||||||
|
- MCP 客户端支持 JSON-RPC 2.0 协议(initialize 握手、tools/list、tools/call、resources/read)
|
||||||
|
- StdIO 传输实现(子进程管理、异步读写、CompletableFuture 请求-响应关联)
|
||||||
|
- `McpManager` 多服务器管理(从 `.mcp.json` 配置加载、生命周期管理)
|
||||||
|
- `McpToolBridge` 将 MCP 工具桥接为本地 Tool(名称格式: `mcp__{server}__{tool}`)
|
||||||
|
- 新增 `/mcp` 命令(connect/disconnect/tools/resources/reload)
|
||||||
|
- **D组 插件系统**:
|
||||||
|
- 新增 `plugin/` 包: `Plugin` 接口、`PluginContext`、`PluginManager`
|
||||||
|
- JAR 插件加载(URLClassLoader 隔离、Manifest Plugin-Class 读取)
|
||||||
|
- 支持全局插件 (`~/.claude-code-java/plugins/`) 和项目插件 (`.claude-code/plugins/`)
|
||||||
|
- 新增 `OutputStylePlugin` 内置输出样式插件(default/minimal/verbose/markdown)
|
||||||
|
- 新增 `/plugin` 命令(load/unload/reload/info)
|
||||||
|
- **集成**: AppConfig 注册全部 18 工具 + 28 命令 + TaskManager + McpManager + PluginManager
|
||||||
|
- **关联需求**: 5.2 P2 扩展功能
|
||||||
|
|
||||||
|
## [2026-04-03] - P1: Hook系统 + Vim模式 + Banner增强
|
||||||
|
|
||||||
|
- **修改类型**: 功能新增
|
||||||
|
- **修改详情**:
|
||||||
|
- 新增 `HookManager`: 支持 PreToolUse/PostToolUse/PrePrompt/PostResponse 4 种钩子
|
||||||
|
- Hook 优先级排序(数字越小优先级越高),PreToolUse 可中止工具执行
|
||||||
|
- AgentLoop 集成 Hook 系统到 executeToolCalls() 流程
|
||||||
|
- ReplSession 支持 Vim 编辑模式(`CLAUDE_CODE_VIM=1` 环境变量启用)
|
||||||
|
- Banner 增强:显示命令数量和 Vim 模式标识
|
||||||
|
- 修复重复 isDumb 变量
|
||||||
|
- **关联需求**: 5.2 P1 重要功能
|
||||||
|
|
||||||
|
## [2026-04-03] - P1: 3命令 + 代码高亮 + 状态行
|
||||||
|
|
||||||
|
- **修改类型**: 功能新增
|
||||||
|
- **修改详情**:
|
||||||
|
- 新增 3 个命令: `/resume`(恢复对话), `/export`(导出Markdown), `/commit`(AI生成commit)
|
||||||
|
- `MarkdownRenderer` 完全重写:支持 Java/JS/TS/Python/Bash/SQL 6 种语言语法高亮
|
||||||
|
- 高亮处理:注释 → 字符串保护 → 注解 → 关键字 → 数字 → 布尔/null
|
||||||
|
- 新增 `StatusLine` 底部状态行(模型、token、费用、API调用、工作目录)
|
||||||
|
- AppConfig 注册总数达 19 命令
|
||||||
|
- **关联需求**: 5.2 P1 重要功能
|
||||||
|
|
||||||
|
## [2026-04-03] - P0: 5命令 + 2工具 + 权限确认 + Thinking显示
|
||||||
|
|
||||||
|
- **修改类型**: 功能新增
|
||||||
|
- **修改详情**:
|
||||||
|
- 新增 5 个命令: `/diff`, `/version`(ver), `/skills`, `/memory`(mem), `/copy`
|
||||||
|
- 新增 `WebSearchTool`: DuckDuckGo HTML 搜索(无需 API Key)
|
||||||
|
- 新增 `AskUserQuestionTool`: AI 向用户提问(通过 ToolContext 回调暂停 agent loop)
|
||||||
|
- AgentLoop 新增权限确认机制: 非只读工具调用前提示 [Y/n/always]
|
||||||
|
- AgentLoop 新增 Thinking 内容提取和显示(从 ChatResponse metadata 读取)
|
||||||
|
- 新增 `PermissionRequest` record 和 `onPermissionRequest`/`onThinkingContent` 回调
|
||||||
|
- ReplSession 新增 `promptPermission()` UI 和 `readUserInputDuringAgentLoop()` 方法
|
||||||
|
- **关联需求**: 5.2 P0 核心功能
|
||||||
|
|
||||||
## [2026-04-02] - Phase 5: 流式输出与高级功能
|
## [2026-04-02] - Phase 5: 流式输出与高级功能
|
||||||
|
|
||||||
- **修改类型**: 功能新增
|
- **修改类型**: 功能新增
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ allowed-tools: [BashTool, FileReadTool]
|
|||||||
| | 最大迭代限制 (50轮) | ✅ |
|
| | 最大迭代限制 (50轮) | ✅ |
|
||||||
| | 消息历史管理 | ✅ |
|
| | 消息历史管理 | ✅ |
|
||||||
| | 对话持久化 | ✅ |
|
| | 对话持久化 | ✅ |
|
||||||
| **工具系统 (11个)** | BashTool | ✅ |
|
| **工具系统 (18个)** | BashTool | ✅ |
|
||||||
| | FileReadTool | ✅ |
|
| | FileReadTool | ✅ |
|
||||||
| | FileWriteTool | ✅ |
|
| | FileWriteTool | ✅ |
|
||||||
| | FileEditTool | ✅ |
|
| | FileEditTool | ✅ |
|
||||||
@@ -329,6 +329,48 @@ allowed-tools: [BashTool, FileReadTool]
|
|||||||
| | ListFilesTool | ✅ |
|
| | ListFilesTool | ✅ |
|
||||||
| | AgentTool | ✅ |
|
| | AgentTool | ✅ |
|
||||||
| | NotebookEditTool | ✅ |
|
| | NotebookEditTool | ✅ |
|
||||||
|
| | WebSearchTool (P0) | ✅ |
|
||||||
|
| | AskUserQuestionTool (P0) | ✅ |
|
||||||
|
| | TaskCreate/Get/List/Update (P2) | ✅ |
|
||||||
|
| | ConfigTool (P2) | ✅ |
|
||||||
|
| | McpToolBridge (P2) | ✅ |
|
||||||
|
| **命令系统 (28个)** | 基础: /help, /clear, /exit 等 11个 | ✅ |
|
||||||
|
| | P0: /diff, /version, /skills, /memory, /copy | ✅ |
|
||||||
|
| | P1: /resume, /export, /commit | ✅ |
|
||||||
|
| | P2: /hooks, /review, /stats, /branch, /rewind, /tag | ✅ |
|
||||||
|
| | P2: /security-review, /mcp, /plugin | ✅ |
|
||||||
|
| **上下文** | CLAUDE.md 加载 | ✅ |
|
||||||
|
| | Skills 技能加载 | ✅ |
|
||||||
|
| | Git 上下文收集 | ✅ |
|
||||||
|
| | 系统提示词构建 | ✅ |
|
||||||
|
| **终端 UI** | Banner + Provider 信息 | ✅ |
|
||||||
|
| | JLine 行编辑/历史/Tab补全 | ✅ |
|
||||||
|
| | 多行输入 | ✅ |
|
||||||
|
| | Spinner 动画 | ✅ |
|
||||||
|
| | 工具状态渲染 | ✅ |
|
||||||
|
| | ANSI 颜色 | ✅ |
|
||||||
|
| | Markdown 渲染 | ✅ |
|
||||||
|
| | 代码语法高亮 (P1) | ✅ |
|
||||||
|
| | 底部状态行 (P1) | ✅ |
|
||||||
|
| | DiffRenderer 彩色diff (P2) | ✅ |
|
||||||
|
| **配置** | 双 API 提供者切换 | ✅ |
|
||||||
|
| | 环境变量统一 | ✅ |
|
||||||
|
| | Token/费用追踪 | ✅ |
|
||||||
|
| **P0 核心增强** | 权限确认机制 | ✅ |
|
||||||
|
| | Thinking 内容显示 | ✅ |
|
||||||
|
| **P1 体验增强** | Hook 系统 (4种钩子) | ✅ |
|
||||||
|
| | Vim 模式输入 | ✅ |
|
||||||
|
| **P2 扩展** | MCP 客户端 (JSON-RPC/StdIO) | ✅ |
|
||||||
|
| | MCP 多服务器管理 | ✅ |
|
||||||
|
| | 插件系统 (JAR加载) | ✅ |
|
||||||
|
| | 任务管理系统 | ✅ |
|
||||||
|
| | 对话分支/标签/回退 | ✅ |
|
||||||
|
| | GrepTool | ✅ |
|
||||||
|
| | WebFetchTool | ✅ |
|
||||||
|
| | TodoWriteTool | ✅ |
|
||||||
|
| | ListFilesTool | ✅ |
|
||||||
|
| | AgentTool | ✅ |
|
||||||
|
| | NotebookEditTool | ✅ |
|
||||||
| **命令系统 (11个)** | /help, /clear, /exit | ✅ |
|
| **命令系统 (11个)** | /help, /clear, /exit | ✅ |
|
||||||
| | /compact (AI摘要) | ✅ |
|
| | /compact (AI摘要) | ✅ |
|
||||||
| | /cost, /model, /status | ✅ |
|
| | /cost, /model, /status | ✅ |
|
||||||
@@ -351,43 +393,13 @@ allowed-tools: [BashTool, FileReadTool]
|
|||||||
|
|
||||||
### 5.2 未实现功能清单
|
### 5.2 未实现功能清单
|
||||||
|
|
||||||
#### 🔴 P0 核心(建议实现)
|
> ⚠️ P0、P1、P2 已全部实现。以下仅列出 P3(跳过)项目。
|
||||||
|
|
||||||
| 功能 | 难度 | 说明 |
|
#### 🔴 P0 核心 — ✅ 已全部实现
|
||||||
|------|------|------|
|
|
||||||
| **WebSearchTool** | 中 | 网络搜索工具,需要搜索 API(可用 DuckDuckGo 免费 API) |
|
|
||||||
| **AskUserQuestionTool** | 中 | AI 向用户提问工具,需要在 agent loop 中暂停等待用户输入 |
|
|
||||||
| **/diff 命令** | 低 | 显示未提交的 Git 变更,可复用 GitContext |
|
|
||||||
| **/version 命令** | 低 | 显示版本号,直接读取 pom.xml 版本 |
|
|
||||||
| **/skills 命令** | 低 | 列出可用技能,已有 SkillLoader |
|
|
||||||
| **/memory 命令** | 低 | 编辑 CLAUDE.md,打开编辑器或直接编辑 |
|
|
||||||
| **/copy 命令** | 低 | 复制最近回复到剪贴板 |
|
|
||||||
| **权限确认机制** | 中 | 危险操作前要求用户确认(如文件写入、bash 执行) |
|
|
||||||
| **Thinking 内容显示** | 高 | 显示 AI 思考过程(需要 Anthropic extended thinking API 支持) |
|
|
||||||
|
|
||||||
#### 🟡 P1 重要(体验增强)
|
#### 🟡 P1 重要 — ✅ 已全部实现
|
||||||
|
|
||||||
| 功能 | 难度 | 说明 |
|
#### 🟢 P2 扩展 — ✅ 已全部实现
|
||||||
|------|------|------|
|
|
||||||
| CLAUDE.local.md 支持 | 低 | 本地级记忆文件 |
|
|
||||||
| 底部状态行 | 中 | 持续显示模型、token、工作目录 |
|
|
||||||
| Hook 系统 (PreToolUse) | 中 | 工具调用前后钩子 |
|
|
||||||
| /resume 恢复对话 | 低 | 从持久化文件恢复对话 |
|
|
||||||
| /export 导出对话 | 低 | 导出为 Markdown 文件 |
|
|
||||||
| /commit 命令 | 中 | 直接创建 Git commit |
|
|
||||||
| Vim 模式输入 | 高 | JLine Vim 模式绑定 |
|
|
||||||
| 代码语法高亮 | 中 | MarkdownRenderer 中的代码块着色 |
|
|
||||||
|
|
||||||
#### 🟢 P2 扩展(可后续迭代)
|
|
||||||
|
|
||||||
| 功能 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| MCP 客户端集成 | Model Context Protocol 支持 |
|
|
||||||
| 插件系统 | 可扩展的工具/命令加载 |
|
|
||||||
| LSP 集成 | 语言服务器协议 |
|
|
||||||
| 差异视图 (DiffRenderer) | 文件变更的彩色diff显示 |
|
|
||||||
| OAuth 认证流程 | 第三方认证 |
|
|
||||||
| 多代理协调 | Agent Swarm 模式 |
|
|
||||||
|
|
||||||
#### ⚪ P3 跳过(不适用于 Java CLI)
|
#### ⚪ P3 跳过(不适用于 Java CLI)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user