|
1 | 1 | # memo-cli |
2 | 2 |
|
3 | | -在终端运行的 ReAct Agent,基于 Bun + TypeScript。支持多轮对话(Session/Turn)、JSONL 结构化日志、内置工具调用,默认使用 DeepSeek(OpenAI 兼容接口)。 |
| 3 | +终端内的 ReAct Agent,基于 Bun + TypeScript。它附带 Session/Turn 状态机、标准 JSON 协议提示、结构化 JSONL 日志、内置工具编排,并默认对接 DeepSeek(OpenAI 兼容接口)。你可以按需接入任意 OpenAI 兼容 Provider 以及 MCP 工具。 |
4 | 4 |
|
5 | | -## 特性 |
| 5 | +**全新 TUI 界面**:提供现代化的终端用户界面,支持实时流式输出、工具调用可视化、token 使用统计和交互式命令。 |
6 | 6 |
|
7 | | -- 多轮对话:交互式 REPL,`--once` 支持单轮退出。 |
8 | | -- 工具驱动:内置 bash/run_bun/read/write/edit/glob/grep/webfetch(HTML 自动转纯文本)、time、save_memory、todo,按 ReAct 协议调用。 |
9 | | -- 结构化日志:默认写入 `history/<sessionId>.jsonl`,可携带 token 计数与事件。 |
10 | | -- 可配置 token 预算:本地 tiktoken 预估 + LLM usage 对账,支持提示超限预警/拒绝。 |
| 7 | +## 预备知识 |
| 8 | + |
| 9 | +- 需要 [Bun](https://bun.sh/)(建议 1.1+)和可用的 OpenAI 兼容 API Key。 |
| 10 | +- 配置、历史日志与缓存写在 `~/.memo/`,设置 `MEMO_HOME` 可以迁移目录。 |
| 11 | +- 第一次运行会引导生成 `~/.memo/config.toml` 并选择默认 Provider。 |
| 12 | + |
| 13 | +## 核心特性 |
| 14 | + |
| 15 | +- **现代化 TUI 界面**:基于 React + Ink 构建的终端用户界面,支持实时流式输出、工具调用可视化、token 使用统计和交互式命令。 |
| 16 | +- **Session/Turn 多轮控制**:交互式 TUI + `--once` 单轮模式,支持会话恢复。 |
| 17 | +- **JSON 协议 ReAct**:强制模型输出 `{"thought":"","action":{...}}` 或 `{"final":""}`,驱动工具调用与回答。 |
| 18 | +- **结构化日志**:所有事件写入 JSONL(token 计数、工具 observation、LLM 元数据)。 |
| 19 | +- **Token 预算**:用 `tiktoken` 估算 prompt,结合 LLM usage,对超限做提示或拒绝。 |
| 20 | +- **内置工具 + MCP 扩展**:提供文件/系统/网络/记忆工具,并自动注入配置的 MCP 工具前缀。 |
| 21 | +- **智能交互**:支持命令补全、输入历史、快捷键操作和丰富的 Slash 命令。 |
| 22 | + |
| 23 | +## 架构概览 |
| 24 | + |
| 25 | +采用清晰的关注点分离架构:核心逻辑位于 `packages/core`,UI 层负责交互与可视化。 |
| 26 | + |
| 27 | +1. **配置层**(`config/`):读取/写入 `~/.memo/config.toml`,选择 Provider,生成会话路径。 |
| 28 | +2. **运行时**(`runtime/`):`session.ts` 执行 ReAct 循环,`history.ts` 写事件,`prompt.ts` 维护 JSON 协议提示。 |
| 29 | +3. **默认依赖**(`runtime/defaults.ts`):拼装工具注册表、OpenAI SDK 的 `callLLM`、token counter、`maxSteps` 与日志 sink。 |
| 30 | +4. **Hooks & Middlewares**:通过 `createAgentSession` 的 `onAssistantStep`、`hooks.onAction`、`onFinal` 等回调订阅生命周期。 |
| 31 | +5. **UI 层**(`packages/ui/`):基于 React + Ink 的 TUI 界面,提供实时可视化、交互式命令和状态管理。 |
| 32 | + |
| 33 | +```ts |
| 34 | +import { createAgentSession } from '@memo/core' |
| 35 | + |
| 36 | +const session = await createAgentSession({ onAssistantStep: console.log }) |
| 37 | +await session.runTurn('你好') // 运行完整 ReAct 循环 |
| 38 | +await session.close() |
| 39 | +``` |
| 40 | + |
| 41 | +## TUI 界面特性 |
| 42 | + |
| 43 | +memo-cli 提供现代化的终端用户界面,包含以下特性: |
| 44 | + |
| 45 | +### 界面布局 |
| 46 | + |
| 47 | +- **HeaderBar**:显示会话信息、Provider/Model、当前目录 |
| 48 | +- **MainContent**:展示对话历史、工具调用、流式输出 |
| 49 | +- **StatusBar**:实时显示 Token 使用情况、步骤计数 |
| 50 | +- **InputPrompt**:智能输入框,支持命令补全和历史搜索 |
| 51 | + |
| 52 | +### 可视化功能 |
| 53 | + |
| 54 | +- **实时流式输出**:助手回答逐字显示,支持打字机效果 |
| 55 | +- **工具调用卡片**:工具执行状态可视化(pending/executing/success/error) |
| 56 | +- **Token 统计**:实时显示 prompt/completion/total token 使用量 |
| 57 | +- **执行时长**:显示每个 Turn 的处理时间 |
| 58 | + |
| 59 | +### 交互设计 |
| 60 | + |
| 61 | +- **快捷键支持**:Ctrl+C(中断/退出)、Ctrl+L(清屏)、上下键(历史) |
| 62 | +- **Slash 命令**:`/help`、`/exit`、`/clear`、`/tools`、`/config` 等 |
| 63 | +- **智能补全**:输入时自动提示可用命令和工具 |
| 64 | +- **历史管理**:保存和检索输入历史 |
| 65 | + |
| 66 | +## 内置工具概览 |
| 67 | + |
| 68 | +- **文件系统**:`read` / `write` / `edit` / `glob` / `grep`,提供偏移、上下文、全局替换等能力。 |
| 69 | +- **系统执行**:`bash` 直接运行 Shell;`run_bun` 在沙箱里执行 JS/TS(bubblewrap 或 `sandbox-exec`,可配置网络)。 |
| 70 | +- **网络获取**:`webfetch` 支持 http/https/data,10 秒超时、512 KB 限制,自动清洗 HTML。 |
| 71 | +- **辅助工具**:`save_memory`(写入 `~/.memo/memo.md`)、`todo` 管理、`time` 查询。 |
| 72 | +- **MCP 外部工具**:支持 stdio 或 Streamable HTTP,工具名前会加 `<server>_` 前缀自动注入系统提示词。 |
| 73 | + |
| 74 | +详见 `docs/tool/*.md`。 |
11 | 75 |
|
12 | 76 | ## 快速开始 |
13 | 77 |
|
14 | | -1. 安装依赖 |
| 78 | +1. **安装依赖** |
| 79 | + |
15 | 80 | ```bash |
16 | 81 | bun install |
17 | 82 | ``` |
18 | | -2. 配置 API Key(优先 OPENAI_API_KEY,回退 DEEPSEEK_API_KEY) |
19 | | - ```bash |
20 | | - export DEEPSEEK_API_KEY=your_key_here |
21 | | - ``` |
22 | | -3. 启动一次性对话 |
| 83 | + |
| 84 | +2. **配置 API Key** |
| 85 | + |
23 | 86 | ```bash |
24 | | - bun start "你的问题" --once |
| 87 | + export OPENAI_API_KEY=your_key # 或 DEEPSEEK_API_KEY |
25 | 88 | ``` |
26 | | -4. 进入交互式 REPL(多轮) |
| 89 | + |
| 90 | +3. **首次运行** |
| 91 | + |
27 | 92 | ```bash |
28 | 93 | bun start |
29 | | - # 输入 /exit 退出 |
| 94 | + # 将引导填写 provider/model/base_url,并在 ~/.memo/config.toml 保存 |
30 | 95 | ``` |
31 | 96 |
|
32 | | -### CLI 参数 |
| 97 | +## CLI 使用 |
33 | 98 |
|
34 | | -- `--once`:单轮对话后退出(默认交互式多轮)。 |
| 99 | +memo-cli 支持两种运行模式,根据终端环境自动选择: |
35 | 100 |
|
36 | | -### 工具说明 |
| 101 | +### 交互式 TUI 模式(默认) |
37 | 102 |
|
38 | | -- **run_bun**:代码解释器工具,可以在临时文件中运行任意 Bun (JS/TS) 代码,支持 top-level await,使用 `console.log` 输出结果。 |
39 | | -- **webfetch**:网页抓取工具,支持 http/https/data 协议,具有 10 秒超时和 512KB 大小限制,能自动将 HTML 转换为纯文本。 |
40 | | -- 更多工具详情请查看 `docs/tool/` 目录下的文档。 |
| 103 | +在支持 TTY 的终端中,自动启动现代化 TUI 界面: |
41 | 104 |
|
42 | | -## 外部 MCP Server |
| 105 | +```bash |
| 106 | +bun start |
| 107 | +``` |
43 | 108 |
|
44 | | -- 配置文件:`~/.memo/config.toml`(可用 `MEMO_HOME` 覆盖)。在 `[mcp_servers.<name>]` 下添加条目。 |
45 | | -- 本地 stdio 服务器(已有可执行文件): |
46 | | - ```toml |
47 | | - [mcp_servers.local_tools] |
48 | | - command = "/path/to/mcp-server" |
49 | | - args = [] |
50 | | - ``` |
51 | | -- 远程 HTTP 服务器(Streamable HTTP,失败会自动回退 SSE): |
52 | | - ```toml |
53 | | - [mcp_servers.bing_cn] |
54 | | - type = "streamable_http" |
55 | | - url = "https://mcp.api-inference.modelscope.net/496703c5b3ff47/mcp" |
56 | | - # 可选:headers = { Authorization = "Bearer xxx" } |
57 | | - # 可选:fallback_to_sse = true # 默认开启 |
58 | | - ``` |
59 | | -- 保存配置后重启 memo,会在系统提示词中注入外部工具列表(工具名前会带 `<server>_` 前缀)。 |
| 109 | +**TUI 特性**: |
| 110 | + |
| 111 | +- 实时流式输出显示 |
| 112 | +- 工具调用可视化 |
| 113 | +- Token 使用统计 |
| 114 | +- 交互式 Slash 命令 |
| 115 | +- 输入历史和补全 |
| 116 | + |
| 117 | +### 单轮纯文本模式 |
| 118 | + |
| 119 | +使用 `--once` 参数或非 TTY 环境时,输出纯文本结果: |
| 120 | + |
| 121 | +```bash |
| 122 | +bun start "你的问题" --once |
| 123 | +``` |
| 124 | + |
| 125 | +**纯文本模式**: |
| 126 | + |
| 127 | +- 简洁的文本输出 |
| 128 | +- 适合脚本集成 |
| 129 | +- 便于日志记录 |
| 130 | +- 保持向后兼容 |
| 131 | + |
| 132 | +### 构建与部署 |
| 133 | + |
| 134 | +```bash |
| 135 | +# 构建 CLI 应用 |
| 136 | +bun build |
| 137 | +
|
| 138 | +# 生成独立二进制文件 |
| 139 | +bun run build:binary # 输出 ./memo |
| 140 | +``` |
| 141 | + |
| 142 | +常用参数:`--once` 控制单轮模式;`--session <id>`(若 UI 已暴露)可恢复历史 session。 |
| 143 | + |
| 144 | +## TUI 快捷键与命令 |
| 145 | + |
| 146 | +### 快捷键 |
| 147 | + |
| 148 | +- **Enter**:提交输入 |
| 149 | +- **Shift+Enter**:输入换行 |
| 150 | +- **Up/Down**:浏览输入历史 |
| 151 | +- **Ctrl+C**:中断当前操作或退出程序 |
| 152 | +- **Ctrl+L**:清屏 |
| 153 | + |
| 154 | +### Slash 命令 |
| 155 | + |
| 156 | +- `/help`:显示帮助信息和可用命令 |
| 157 | +- `/exit`:退出当前会话 |
| 158 | +- `/clear`:清除屏幕内容 |
| 159 | +- `/tools`:列出所有可用工具(内置 + MCP) |
| 160 | +- `/config`:显示配置文件路径和当前 Provider 信息 |
| 161 | +- `/memory`:显示记忆文件位置和摘要(如有) |
| 162 | + |
| 163 | +### 输入特性 |
| 164 | + |
| 165 | +- **智能补全**:输入时自动提示命令和工具名 |
| 166 | +- **历史搜索**:支持输入历史检索 |
| 167 | +- **多行输入**:支持 Shift+Enter 输入多行内容 |
| 168 | + |
| 169 | +## 配置详解 |
| 170 | + |
| 171 | +`~/.memo/config.toml` 管理 Provider、MCP 与运行选项,`MEMO_HOME` 可以重定向路径。 |
| 172 | + |
| 173 | +```toml |
| 174 | +current_provider = "deepseek" |
| 175 | +max_steps = 100 |
| 176 | +stream_output = false |
| 177 | +
|
| 178 | +[[providers]] |
| 179 | +name = "deepseek" |
| 180 | +env_api_key = "DEEPSEEK_API_KEY" |
| 181 | +model = "deepseek-chat" |
| 182 | +base_url = "https://api.deepseek.com" |
| 183 | +``` |
| 184 | + |
| 185 | +MCP 服务器示例: |
| 186 | + |
| 187 | +```toml |
| 188 | +[mcp_servers.local_tools] |
| 189 | +command = "/path/to/mcp-server" |
| 190 | +args = [] |
| 191 | +
|
| 192 | +[mcp_servers.bing_cn] |
| 193 | +type = "streamable_http" |
| 194 | +url = "https://mcp.api-inference.modelscope.net/496703c5b3ff47/mcp" |
| 195 | +# headers = { Authorization = "Bearer xxx" } |
| 196 | +# fallback_to_sse = true # 默认开启 |
| 197 | +``` |
| 198 | + |
| 199 | +API Key 优先级:`当前 provider 的 env_api_key` > `OPENAI_API_KEY` > `DEEPSEEK_API_KEY`。缺失时 CLI 会提示交互输入并写入配置。 |
| 200 | + |
| 201 | +## Session、日志与 Token |
| 202 | + |
| 203 | +- **日志路径**:`~/.memo/sessions/<sanitized-cwd>/<yyyy-mm-dd>_<HHMMss>_<id>.jsonl`。 |
| 204 | +- **事件类型**:`session_start/turn_start/assistant/action/observation/final/turn_end/session_end`,可回放任意一步。 |
| 205 | +- **Token 统计**:Prompt & completion 通过 `tiktoken` 估算,并在 UI 中展示本轮预算。 |
| 206 | +- **Max Steps 防护**:默认 100,可在配置文件调整以避免无限工具循环。 |
60 | 207 |
|
61 | 208 | ## 项目结构 |
62 | 209 |
|
63 | | -- `packages/core` |
64 | | - - `config/`:常量、配置加载(~/.memo/config.toml)、路径工具。 |
65 | | - - `runtime/`:Session/Turn 运行时(日志、提示词加载、历史事件、默认依赖补全)。 |
66 | | - - `llm/`:模型适配与 tokenizer(OpenAI 兼容 DeepSeek、tiktoken)。 |
67 | | - - `utils/`:解析工具。 |
68 | | -- `packages/tools`:内置工具集合,统一导出 `TOOLKIT`。 |
69 | | -- `packages/ui`:CLI 入口,组装 Core + Tools 并处理交互。 |
70 | | -- `docs/`:架构与设计文档。 |
71 | | - - `tool/`:每个工具的详细使用说明。 |
| 210 | +``` |
| 211 | +memo-cli/ |
| 212 | +├── packages/ |
| 213 | +│ ├── core/ # 配置、Session/Turn 状态机、LLM/工具适配 |
| 214 | +│ ├── tools/ # 内置工具实现 |
| 215 | +│ └── ui/ # CLI 入口和 TUI 界面 |
| 216 | +│ ├── src/ |
| 217 | +│ │ ├── tui/ # React + Ink TUI 组件 |
| 218 | +│ │ │ ├── components/ # UI 组件 |
| 219 | +│ │ │ ├── commands/ # Slash 命令处理 |
| 220 | +│ │ │ └── utils/ # 工具函数 |
| 221 | +│ │ └── index.tsx # CLI 入口点 |
| 222 | +├── docs/ # 架构、设计、内置工具与未来计划 |
| 223 | +├── history/ # 运行期生成的 JSONL 示例 |
| 224 | +├── dist/ # bun build 输出 |
| 225 | +└── memo # bun build --compile 生成的可执行文件 |
| 226 | +``` |
72 | 227 |
|
73 | 228 | ## 开发脚本 |
74 | 229 |
|
75 | | -- 安装依赖:`bun install` |
76 | | -- 运行 CLI:`bun start "问题" --once` |
77 | | -- 格式化:`bun run format` / `bun run format:check` |
78 | | -- 构建:`bun build` |
79 | | -- 构建二进制文件:`bun run build:binary` |
| 230 | +### 基础开发 |
| 231 | +
|
| 232 | +- `bun install`:安装所有依赖 |
| 233 | +- `bun start`:启动交互式 TUI |
| 234 | +- `bun start "问题" --once`:运行单轮纯文本模式 |
| 235 | +
|
| 236 | +### 构建与部署 |
| 237 | +
|
| 238 | +- `bun build`:构建 CLI 应用(产物位于 `dist/`) |
| 239 | +- `bun run build:binary`:生成独立二进制文件 `./memo` |
| 240 | +
|
| 241 | +### 代码质量 |
| 242 | +
|
| 243 | +- `bun run format`:使用 Prettier 格式化代码 |
| 244 | +- `bun run format:check`:检查代码格式 |
| 245 | +
|
| 246 | +### UI 开发 |
| 247 | +
|
| 248 | +- 修改 `packages/ui/src/tui/` 下的文件来调整 TUI 界面 |
| 249 | +- 添加新的 Slash 命令到 `packages/ui/src/tui/commands.ts` |
| 250 | +- 自定义组件样式在对应的组件文件中 |
| 251 | +
|
| 252 | +## 文档索引 |
| 253 | +
|
| 254 | +### 核心架构 |
| 255 | +
|
| 256 | +- `docs/core.md`:核心状态机与 Session API |
| 257 | +- `docs/multi-turn.md`:多轮策略与会话管理 |
| 258 | +- `docs/token-counting.md`:token 计费与估算机制 |
| 259 | +
|
| 260 | +### UI 与设计 |
| 261 | +
|
| 262 | +- `docs/design/memo-cli-ui-design.md`:TUI 界面设计与实现 |
| 263 | +- `docs/design/hooks-and-middleware.md`:Hooks 与中间件系统 |
| 264 | +- `docs/design/gemini-cli.md`:设计参考与灵感 |
| 265 | +
|
| 266 | +### 工具文档 |
| 267 | +
|
| 268 | +- `docs/tool/*.md`:各内置工具的详细参数与返回值 |
| 269 | +- `docs/tool/save_memory.md`:记忆管理工具 |
| 270 | +- `docs/tool/glob.md`:文件搜索工具 |
| 271 | +
|
| 272 | +### 未来发展 |
| 273 | +
|
| 274 | +- `docs/future-plan.md`:项目路线图与计划 |
| 275 | +- `docs/dev-direction.md`:开发方向与架构演进 |
| 276 | +
|
| 277 | +## 安全特性 |
| 278 | +
|
| 279 | +- `run_bun` 依赖 bubblewrap 或 `sandbox-exec`,并可控制网络访问。 |
| 280 | +- `webfetch`、`bash` 等工具限制超时时间、输出大小与允许路径,降低风险。 |
| 281 | +- MCP 工具统一通过配置注入,避免在提示词中硬编码密钥。 |
| 282 | +
|
| 283 | +## 贡献与许可证 |
| 284 | +
|
| 285 | +- 贡献流程参见 [CONTRIBUTING.md](CONTRIBUTING.md)。 |
| 286 | +- 采用 MIT 许可证。 |
0 commit comments