# AGENTS.md --- ## 交互要求 - 思考过程全程必须使用中文,包括需求分析、逻辑拆解、方案选择等所有推理环节 - 最终输出内容必须全部使用中文,除代码语法本身和英文关键词以外 --- ## 核心原则 (Karpathy) ### 1. 先思考再编码 (Think Before Coding) **不要预设。不要隐藏困惑。呈现权衡。** - 明确陈述你的假设。如果不确定,就问。 - 如果存在多种解释,全部列出——不要默默选择其一。 - 如果有更简单的方法,就说出来。在必要时提出反对。 - 如果某件事不清楚,停下来。说出困惑所在。然后提问。 ### 2. 简洁优先 (Simplicity First) **解决问题的最小代码量。不写任何推测性代码。** - 不实现超出需求的特性。 - 不为只用一次的代码创建抽象。 - 不添加未经要求的"灵活性"或"可配置性"。 - 不为不可能发生的场景做错误处理。 - 如果你写了 200 行而它本可以用 50 行完成,重写它。 ### 3. 精准变更 (Surgical Changes) **只改动必须改的。只清理你自己造成的混乱。** - 未明确要求时不修改已有文件 - 先确认意图再动手 - 不要"优化"相邻的代码、注释或格式。 - 不要重构没有问题的代码。 - 遵循已有风格,即使你自己的写法不同。 - 如果你注意到不相关的死代码,提出来——但不要删除它。 - 删除你的改动导致的未使用的导入/变量/函数。 ### 4. 目标驱动执行 (Goal-Driven Execution) **定义成功标准。迭代直至验证通过。** - "添加验证" → "通过测试验证已有实现的正确性" - "修复缺陷" → "编写测试复现问题,验证修复" - "重构 X" → "确保重构后测试仍然通过" 对于多步骤任务,简要列出计划: ``` 1. [步骤] → 验证:[检查项] 2. [步骤] → 验证:[检查项] ``` --- ## 技术栈规范 ### 通用规范 **包管理器**: `cargo` **代码风格** - 文件/文件夹命名:`kebab-case` - 类/组件命名:`PascalCase` - 变量/函数命名:`snake_case` **测试要求** - 核心业务逻辑需测试(关键算法、边界条件、错误处理) - 简单逻辑不需要测试(枚举字面值、Getter、无分支的简单转换) - 不主动补测试(除非用户明确要求) **错误处理** - 优先使用 `Result` 处理错误,避免 `unwrap()` - 异步 API 使用 `?` 传播错误,不在 `catch` 中静默吞掉错误 - 错误按层级组织:公开 API 用全局 Error,内部实现可定义细粒度子错误 **安全规范** - 不硬编码密钥,使用环境变量 - 用户输入必须验证 - 依赖升级策略: - **安全补丁**:立即升级(修复已知漏洞) - **次要版本**:评估后升级(新功能、向后兼容) - **主要版本**:谨慎升级(可能破坏兼容性,需全面测试) - **验证**:升级后运行完整测试套件确保无回归 **Git Commit 规范** - 使用 Conventional Commits 格式:`(): ` - **描述使用中文** - 类型: - `feat` - 新功能 - `fix` - Bug 修复 - `enhance` - 增强现有功能(非新功能) - `docs` - 文档更新 - `style` - 代码格式(不影响功能) - `refactor` - 重构 - `test` - 测试相关 - `chore` - 构建/工具/配置 - 描述使用祈使句、现在时态、句尾无句号 - **Scope 推导规则**: - 从被提交的文件路径中推导出一个最相关的 scope - 一个 commit 只写一个主要 scope,不要罗列多个 - 如果改动涉及多个模块,选择影响范围最大的那个或使用更上层抽象名称 - 如果改动是全局的,可以省略 scope 或使用 `core`/`global` - **示例**: - `feat(llm): 添加流式响应支持`(修改 `src/llm/stream.rs`) - `fix(memory): 修复向量检索边界条件`(修改 `src/memory/vector_store.rs`) - `refactor(core): 统一错误类型定义`(修改多个模块的错误处理) - `docs: 更新 API 文档`(全局文档更新) - `chore(deps): 升级 tokio 到 1.40`(依赖更新) --- ### Rust **包管理器**: `cargo` **代码风格** - `cargo fmt` 格式化,`cargo clippy` 检查 - 变量/函数命名:`snake_case` - 优先使用 `Result` 处理错误,避免 `unwrap()` - 所有权规则:不使用 `&mut` 时不用,引用必须合法 **模块组织** - 按功能领域组织模块(一个模块一个职责) - **2018+ 版风格**:使用 `foo.rs` 作为模块根,子模块放在 `foo/` 目录下 - **扁平优先**:如果模块没有子模块,直接用单个 `foo.rs` 文件 - **需要子模块时才用目录**:只有当模块需要组织多个子模块时才创建 `foo/` 目录 - **避免 `mod.rs`**:不使用 `foo/mod.rs` 风格,统一使用 `foo.rs` 作为模块根 - **公共 API 重导出**:在模块根中使用 `pub use` 重新导出子模块的公共类型,提供清晰的 API 边界 **示例结构图**: ``` src/ ├── lib.rs # crate 根,声明顶层模块 ├── llm.rs # LLM 模块(无子模块,扁平文件) ├── memory.rs # 记忆模块根(有子模块) ├── memory/ │ ├── conversation.rs # ✓ 子模块 │ └── vector_store.rs # ✓ 子模块 ├── prompt.rs # 提示词模块根(有子模块) ├── prompt/ │ ├── template.rs # ✓ 子模块 │ └── optimizer.rs # ✓ 子模块 ├── tool.rs # 工具模块根(有子模块) ├── tool/ │ ├── mcp.rs # ✓ 子模块 │ └── registry.rs # ✓ 子模块 └── agent.rs # Agent 模块根(有子模块) └── agent/ ├── runtime.rs # ✓ 子模块 └── planner.rs # ✓ 子模块 # ❌ 避免的风格 src/ └── memory/ └── mod.rs # ❌ 不使用 mod.rs 风格 # ✅ memory.rs 示例:声明子模块并重导出公共 API pub mod conversation; pub mod vector_store; // 重导出常用类型,提供简洁的公共 API pub use conversation::ConversationMemory; pub use vector_store::VectorStore; ``` **测试文件**: 内联测试(`#[cfg(test)] mod tests {}`)或 `tests/` 目录 **依赖管理**: `Cargo.toml`,语义化版本 --- ## 文档规范 ### 方案规范 (docs/) **编号规则**:创建新方案前必须先通过 shell 命令确认当前实际最大编号(Unix: `ls docs/` / Windows: `dir docs\`),禁止使用上下文中缓存的编号,如遇冲突自动递增 **方案文档结构**(6 项): 1. **背景与目标** - 问题描述、预期目标 2. **需求分析** - 功能需求、非功能需求 3. **方案设计** - 架构设计、模块划分、接口定义 4. **实现计划** - 任务拆解、优先级、时间估算 5. **风险评估** - 潜在风险、缓解措施 6. **验收标准** - 可验证的完成条件 --- ## 项目特定规则 ### 项目结构 - 源代码:`src/`(lib crate) - 测试:内联 `#[cfg(test)] mod tests {}` ### 项目目标 agcore 是一个智能体(Agent)核心工具箱,提供: - **LLM 调用**:完整的请求/响应周期管理 - **提示词工程**:组合、模板化、优化 - **记忆系统**:存储、检索、管理对话/向量记忆 - **工具调用**:MCP 协议集成与自定义工具注册 - **Agent 运行时**:多轮对话、任务编排 ### 设计原则 - **模块化**:每个功能领域独立 module,通过 trait 定义接口 - **可插拔**:LLM 后端、记忆存储、工具注册均通过 trait 抽象 - **无运行时依赖**:core 层尽量少依赖,具体实现在 separate crates - **异步优先**:涉及 IO 的 API 均使用 `async` ### 特殊约定 - 所有公开 API 必须有文档注释(`///`) - 使用 `thiserror` 或 `derive_more` 定义错误类型 - 错误按层级组织:公开 API 用全局 Error,内部实现可定义细粒度子错误 - 跨 module 依赖通过 trait 而非具体类型 - 配置优先从环境变量读取,支持 builder 模式注入 --- **这些指南生效的标志:** - diff 中不必要的改动更少 - 因过度复杂而导致的重写更少 - 澄清问题在实现之前提出 - 干净、精简的 PR