focus/README.md

172 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# focus — 纯 Rust 实现的 LLM Agent 框架
> 参考 [pi](https://github.com/earendil-works/pi)TypeScript 原版)与
> [pi_agent_rust](https://github.com/Dicklesworthstone/pi_agent_rust)Rust 移植)实现的
> 分层、极简依赖的 LLM agent 框架。**核心目标**:以最小的依赖面实现一个分层清晰、
> 可独立测试的 agent 框架,重点学习 pi 的核心设计——agent 循环、消息类型、工具抽象、流式协议。
## ✨ 核心特性
- **双层 agent 循环**:外层 follow-up、内层 steering + 工具执行,支持 sequential / parallel 两种工具执行模式
- **流式输出**SSE 增量解析,流式 assistant 消息随 delta 原地更新;`Esc` 随时中止
- **多 provider 支持**AnthropicMessages API+ OpenAIResponses API 与 Chat Completions 双协议),统一翻译为 `StreamEvent` 事件流,错误编码进事件而非中断循环
- **内置工具**`read` / `write` / `edit`pi 风格精确替换)/ `shell`跨平台Windows + Linux
- **会话管理**:树形会话结构(`id` + `parentId`+ JSONL 追加写,支持分支与会话切换
- **上下文压缩**token 估算 + 压缩方案(切点 + 摘要指令),自动执行滚动总结
- **交互式 TUI**多行输入、Markdown 渲染、实时 transcript、折叠的思考/工具块、跨平台滚轮滚动
- **类型安全**:自研 `focus-json` 手写 JSON 编解码,不依赖 serde / serde_json
- **依赖极简**:运行时依赖仅 tokio + rustls 生态(另为 TUI 特批 ratatui + crossterm
## 🏗️ 架构设计
细粒度 **7-crate workspace** 拆分,每个 crate 职责单一、边界清晰、可独立测试。依赖严格单向向下,禁止循环。
```text
focus/
├── Cargo.toml # workspace 清单
├── README.md # 本文件
├── AGENTS.md # 工程规范(依赖白名单、代码/测试/提交规范)
├── LICENSE # MIT
├── docs/architecture/ # 架构解读文档(三份精读笔记)
└── crates/
├── focus-json/ # 极简 JSON 解析器 / 序列化器(零外部依赖)
├── focus-core/ # ★ 核心层:领域类型 + Agent 循环 + Tool / StreamProvider trait纯同步无 tokio
├── focus-transport/ # 传输层HTTPS 客户端tokio + rustls、HTTP/1.1、SSE 解析
├── focus-providers/ # Provider 实现Anthropic / OpenAI
├── focus-tools/ # 文件工具read / write / edit / shell
├── focus-harness/ # 会话持久化 + 上下文压缩 + 系统提示模板
└── focus-tui/ # 终端交互层ratatui + crossterm组装所有模块
```
### 分层依赖图
```text
focus-json ← 零外部依赖,纯 std
focus-core ← focus-json纯同步逻辑不依赖 tokio
focus-transport ← focus-json, tokio, rustls, tokio-rustls, rustls-native-certs
focus-providers ← focus-core, focus-transport, focus-json, tokio
focus-tools ← focus-core, focus-json
focus-harness ← focus-core, focus-json
focus-tui ← focus-core, focus-providers, focus-tools, focus-harness, focus-json, ratatui, crossterm
```
### 核心设计要点
- **I/O 边界注入**`focus-core` 是纯逻辑层,不碰网络 / 文件系统provider 与工具都通过 trait 注入
- **`content` / `details` 分离**:工具结果的 `content`(模型可见)与 `details`UI / 日志可见)分开
- **错误编码而非抛出**`StreamProvider` 绝不用 `Err` 中断循环,错误编码进 `StreamEvent::Error`
- **压缩只出方案**harness 产出「压缩方案」,真正的摘要 LLM 调用由上层TUI执行——遵守依赖图约束
## 🚀 快速开始
### 构建与测试
```bash
# 构建整个 workspace
cargo build --workspace
# 运行全部测试181 个用例,全绿)
cargo test --workspace
# 代码质量检查
cargo fmt --all --check
cargo clippy --workspace -- -D warnings
```
### 运行 TUI
```bash
cargo run -p focus-tui
```
> 或直接运行构建产物 `target/debug/focus`。
首次启动后先配置 provider
1. 在 TUI 中输入 `/config` 打开配置表单(或直接编辑 `~/.focus/config.json`
2. 填写 `apiKey`、选择 provider 与模型
3. 回到输入框即可开始对话
## ⚙️ 配置
配置文件位于 `<data>/config.json``<data>` 默认为 `~/.focus`
Windows 为 `%USERPROFILE%\.focus`),可用环境变量 `FOCUS_DATA_DIR` 覆盖。
```json
{
"provider": "anthropic",
"openaiProtocol": "responses",
"baseUrl": "https://api.anthropic.com",
"apiKey": "sk-...",
"model": "claude-sonnet-4-5",
"contextWindow": 200000
}
```
| 字段 | 说明 |
|---|---|
| `provider` | `anthropic``openai` |
| `openaiProtocol` | OpenAI 协议:`responses`(默认)或 `chatCompletions` |
| `baseUrl` | API 基址(可选,缺省用默认端点;具体端点路径由 provider 自行拼接) |
| `apiKey` | API 密钥 |
| `model` | 模型 id |
| `contextWindow` | 上下文窗口(可选,缺省按已知模型表自动查询,未知模型兜底 128k |
### 数据目录
| 内容 | 位置 |
|---|---|
| 配置 | `<data>/config.json` |
| 会话 | `<data>/sessions/<session-id>.jsonl`JSONL 追加写,树结构) |
### 环境变量
| 变量 | 说明 |
|---|---|
| `FOCUS_DATA_DIR` | 覆盖数据根目录(默认 `~/.focus` |
| `FOCUS_SHELL` | 覆盖 `shell` 工具使用的 shell 程序Windows 默认 PowerShell、可回退 cmdLinux 默认 bash |
| `FOCUS_DEBUG_FILE` | 设置后providers 把每个原始网络 chunk 追加到该文件(排查协议不兼容,如推理字段名差异) |
## ⌨️ TUI 使用
### 命令
| 命令 | 功能 |
|---|---|
| `/new` | 新建会话 |
| `/sessions` | 查看 / 切换历史会话 |
| `/config` | 编辑配置provider / 模型 / 密钥) |
| `/compact` | 手动触发上下文压缩 |
| `/help` | 显示帮助 |
### 键盘
| 按键 | 功能 |
|---|---|
| `Enter` | 发送消息 |
| `Shift+Enter` | 换行 |
| `Esc` | 运行中中止任务;空闲时退出 |
| `Ctrl+C` | 退出 |
| `Ctrl+D` | 继续(追问一轮) |
| `Tab` | 展开 / 折叠最近的思考或工具块(两级:先预览,再全量) |
| 鼠标滚轮 | 逐行滚动Linux / Windows 均支持;上滚暂停自动跟随) |
| `Ctrl+U` / `PageUp` / `PageDown` | 滚动消息区(输入为空时 `↑` `↓` 也可滚动) |
## 🧪 测试
- 所有测试位于各 crate 的 `crates/<name>/tests/`,禁止在 `src/` 内联测试
- 核心层(`focus-core`)测试**零网络依赖**,用 mock provider 驱动
- provider 测试用**录制 / 回放**的 mock transport不打真实 API真实 API 测试用 `#[ignore]` 标记)
- 当前共 **181 个测试用例**`cargo test --workspace` 全绿
## 📚 文档
- [`AGENTS.md`](./AGENTS.md) — 工程规范:依赖白名单、双语注释规则、代码 / 测试 / Git 提交规范
- [`docs/architecture/00-pi-architecture-overview.md`](./docs/architecture/00-pi-architecture-overview.md) — 参考项目架构全景总览
- [`docs/architecture/01-types-and-protocol.md`](./docs/architecture/01-types-and-protocol.md) — 类型契约逐行精读
- [`docs/architecture/02-agent-loop.md`](./docs/architecture/02-agent-loop.md) — 核心循环逐行精读
## 📄 许可证
[MIT](./Cargo.toml)