ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ForgeCode Agent 开发指南:基于 AGENTS.md 的 Rust 代码库协作规范与实践

ForgeCode Agent 开发指南:基于 AGENTS.md 的 Rust 代码库协作规范与实践 人工智能AI Agent代码智能体AI 应用CLI开发工具【免费下载链接】forgecodeAI enabled pair programmer for Claude, GPT, O Series, Grok, Deepseek, Gemini and 300 models项目地址https://gitcode.com/gh_mirrors/forge39/forgecode点击查看免费下载导读本文围绕 AGENTS.md 展开系统梳理 ForgeCode一个面向 Claude、GPT、Grok、Gemini 等 300 模型的 AI 结对编程工具代码库中 AI Agent 协作开发的核心规范涵盖错误管理、测试编写、验证流程、领域类型设计、文档要求与服务实现模式。无论你是人类开发者还是 AI Agent遵循这套约定都能让代码风格统一、可测试性更强并为模型驱动的开发流程提供稳定的协作基础。读完本文你将掌握 ForgeCode 仓库内每一条工程约定的背后动机、落地方式与源码佐证。一、错误管理anyhow 与 thiserror 的分层职责AGENTS.md 对错误处理给出三条硬性规则在 service 与 repository 层使用anyhow::Result作为统一返回类型领域错误domain errors使用thiserror派生绝不为领域错误实现From转换必须手工逐层转换。这一设计在仓库中有直接佐证。例如 crates/forge_app/src/agent_provider_resolver.rs 中的AgentProviderResolver::get_provider与get_model均以anyhow::Result返回而Ok(...)内的具体错误则通过forge_domain::Error显式构造如Error::NoDefaultSession。领域错误则统一收敛在 crates/forge_domain/src/error.rs 中// NOTE: Deriving From for error is a really bad idea. This is because you end // up converting errors incorrectly without much context. For eg: You dont want // all serde error to be treated as the same. Instead we want to know exactly // where that serde failure happened and for what kind of value. #[derive(Debug, Error, From)] pub enum Error { ... }文件注释直接解释了禁止From自动转换的原因自动转换会丢失错误来源上下文例如所有 serde 错误会被无差别归为同一类型而手工转换可以精确标记在哪一次序列化、针对哪个值失败。该枚举中#[from(skip)]的显式标注如UnsupportedRole(String)、ToolCallArgument { ... }正是这一约定的落地体现。类似的thiserror领域错误也出现在 crates/forge_fs/src/error.rs其中Error::Utf8ValidationFailed与Error::IoError使用#[from]仅转换标准库错误而业务相关错误如BinaryFileNotSupported、StartBeyondFileSize则保留字段并自定义#[error(...)]消息。实操要点Service 方法签名统一写- anyhow::ResultT不要自行发明业务异常类型领域错误枚举使用#[derive(Error, Debug)]配合thiserror并为每个变体提供#[error(...)]人类可读消息跨层转换时手工映射Err(forge_domain::Error::NoDefaultSession.into())这类写法在源码中频繁出现而非实现Fromforge_domain::Error for anyhow::Error的全局规则。二、测试编写三段式结构、断言与 fixture 约定AGENTS.md 规定所有测试必须按三段式编写use pretty_assertions::assert_eq; // Always use pretty assertions fn test_foo() { let setup ...; // Instantiate a fixture or setup for the test let actual ...; // Execute the fixture to create an output let expected ...; // Define a hand written expected result assert_eq!(actual, expected); // Assert that the actual result matches the expected result }配套约定还包括统一使用pretty_assertions获得更友好的 diff 输出用 fixture 构造测试数据fixture 应通用、可复用相等性判断用assert_eq!布尔判断用assert!(...)测试函数内允许直接unwrap()fixture 内使用anyhow::Result尽量少写样板代码测试函数命名与变量命名使用fixture、actual、expected等词汇测试必须与被测源码写在同一个文件中#[cfg(test)] mod tests内联。仓库中 crates/forge_app/src/agent.rs 的测试模块是这套规范的教科书级示例#[cfg(test)] mod tests { use forge_config::{Effort as ConfigEffort, ReasoningConfig as ConfigReasoningConfig}; use forge_domain::{AgentId, Effort, ModelId, ProviderId, ReasoningConfig}; use pretty_assertions::assert_eq; use super::*; fn fixture_agent() - Agent { Agent::new( AgentId::new(test), ProviderId::ANTHROPIC, ModelId::new(claude-3-5-sonnet-20241022), ) } #[test] fn test_reasoning_applied_from_config_when_agent_has_none() { let config ForgeConfig::default().reasoning(...); let actual fixture_agent().apply_config(config).reasoning; let expected Some(ReasoningConfig::default()...); assert_eq!(actual, expected); } }可以观察到fixture_agent()是一个通用可复用的构造器测试内actual、expected命名清晰对完整对象做assert_eq!而非逐字段断言测试与源码同文件内联。类似模式遍布 crates/forge_app/src/compact.rs、crates/forge_app/src/changed_files.rs 等模块。断言选择速查场景推荐写法对象整体相等assert_eq!(actual, expected)布尔条件assert!(cond)集合/序列预期先构造expected集合再整体assert_eq!错误信息有诊断价值users.first().expect(List should not be empty)错误信息无价值直接unwrap()AGENTS.md 特别强调避免手写if let ... else { panic! }而应优先expect(带上下文的错误消息)同时反对逐字段断言assert_eq!(actual.a, expected.a)再断言b、c因为整对象断言一次即可定位差异配合pretty_assertions能给出结构化 diff。三、验证流程cargo insta test 与构建策略AGENTS.md 要求每次改动后运行测试并 lint运行 crate 级测试并接受快照更新cargo insta test --accept构建约束绝不默认运行cargo build --release除非确有性能测试、发布二进制等需求验证优先使用cargo check最快、cargo insta test或cargo builddebug 模式release 构建耗时显著更长日常验证几乎用不到。这套策略与该仓库的实际工程形态高度契合ForgeCode 使用 insta.yaml 管理快照测试仓库中散落着大量.snap快照文件见 crates/forge_app/src/snapshots 与 crates/forge_display/src/snapshotscargo insta test --accept正是用于批量接受这些快照变更的标准流程。同时工作区根目录的 Cargo.toml 以 workspace 组织多个 crateforge_app、forge_domain、forge_fs等单 crate 验证通常比全量 release 构建更符合日常迭代节奏。四、领域类型derive_setters 的约定用法编写领域类型domain types时AGENTS.md 要求使用derive_setters派生 setter并在结构体类型上使用strip_option与into属性#[derive(derive_setters::Setters)] #[setters(strip_option, into)] pub struct User { ... }strip_optionsetter 接收裸值自动包装为OptionT调用方无需写Some(...)intosetter 参数自动执行IntoT转换支持str→String等免显式转换的写法。由此带来的调用风格是链式、声明式的User::default().age(12).is_happy(true).name(John) User::new(Job).age(12).is_happy() User::test() // Special test constructor反例则包括手写结构体字面量User { name: ... }以及使用with_name这类非标准命名——应统一坚持User::new()或User::test()。这一约定在仓库中同样大量落地。derive_setters出现在 crates/forge_app/Cargo.toml、crates/forge_config/Cargo.toml、crates/forge_ci/Cargo.toml 的依赖声明中并被广泛用于 DTO、配置与领域结构例如 crates/forge_app/src/dto/anthropic/request.rs、crates/forge_app/src/dto/openai/request.rs、crates/forge_config/src/compact.rs 等。上文agent.rs测试中的ForgeConfig::default().reasoning(...)、ReasoningConfig::default().enabled(true).effort(Effort::Medium)链式调用正是该模式的直接应用。实操建议需要默认值 链式覆盖的数据类型配置、请求参数、测试 fixture优先derive_setters字段为OptionT时开启strip_option字段为String/数值等需兼容字面量赋值时开启into构造入口统一为new/Default/ 测试专用test避免创造with_xxx这类不一致命名。五、文档规范面向 LLM 的 Rust 文档AGENTS.md 对文档有两条规定必须为所有公开方法、函数、结构体、枚举与 trait 编写 Rust 文档///参数用# Arguments小节说明错误用# Errors小节说明如适用不要包含代码示例——文档是写给 LLM 看的而非人类应聚焦清晰、简洁的功能描述。仓库源码严格遵守了这一风格。以 crates/forge_services/src/tool_services/plan_create.rs 为例/// Creates a new plan file with the specified name, version, and content. Use /// this tool to create structured project plans, task breakdowns, or /// implementation strategies that can be tracked and referenced throughout /// development sessions. pub struct ForgePlanCreateF(ArcF);以及 crates/forge_app/src/agent_provider_resolver.rs/// Resolver for agent providers and models. /// Handles provider resolution, credential refresh, and model lookup. pub struct AgentProviderResolverS(ArcS);这两段文档都没有代码示例而是用一句话精确描述这是什么、做什么、服务于什么场景这正是为模型上下文system prompt、工具描述渲染优化的写法。实际上ForgeCode 的工具描述tool descriptions正是从这些///文档渲染而来参见 crates/forge_domain/src/tools/descriptions 目录以及 crates/forge_app/src/tool_registry.rs 中对动态工具描述的组装逻辑快照见 crates/forge_app/src/snapshots/forge_app__tool_registry__all_rendered_tool_descriptions.snap。六、重构与 Git 协作约定重构先确认再动手AGENTS.md 规定当被要求修复失败的测试时必须先确认是修改实现还是修改测试。这避免了为了让测试变绿而篡改断言或为了迁就旧实现而跳过重构的两种极端。实践中若失败源于行为变更导致的快照过期通常应走cargo insta test --accept更新快照若失败源于实现缺陷则修正实现代码。Git 操作可安全假设 git 与 GitHub CLIgh已预装所有 git 提交与 GitHub 评论必须携带Co-Authored-By: ForgeCode noreplyforgecode.dev。该署名约定同样被写入了系统提示模板并在仓库快照中可查证见 crates/forge_domain/src/snapshots/forge_domain__conversation_html__tests__conversation.snap.html 中渲染出的原文Always use Co-Authored-By: ForgeCode noreplyforgecode.dev for git commits and Github comments说明该指令会作为 Agent 的常驻系统提示出现在会话上下文中确保每次提交自动带上协作署名。七、Service 实现规范清洁架构与泛型注入AGENTS.md 用最大篇幅规定了 service 层的实现范式核心原则如下核心原则禁止 service 间依赖service 绝不能直接依赖其他 service只依赖基础设施抽象仅在需要时依赖基础设施 trait至多一个泛型参数service 至多携带一个基础设施泛型参数禁用 trait object避免Boxdyn ...改用具体类型与泛型构造器模式new()不带类型约束约束只加在需要它们的方法上组合依赖用运算符把多个基础设施 trait 组合成单一 boundArcT存基础设施基础设施以ArcT存储获得廉价克隆与共享所有权元组结构体模式对单依赖的简单 service用struct ServiceT(ArcT)。示例一无基础设施的纯业务 servicepub struct UserValidationService; impl UserValidationService { pub fn new() - Self { ... } pub fn validate_email(self, email: str) - Result() { ... } pub fn validate_age(self, age: u32) - Result() { ... } }示例二单泛型 Arc 的基础设施注入pub trait UserRepository { fn find_by_email(self, email: str) - ResultOptionUser; fn save(self, user: User) - Result(); } pub struct UserServiceR { repository: ArcR, } implR UserServiceR { // 构造器不带约束接收 ArcR pub fn new(repository: ArcR) - Self { ... } } implR: UserRepository UserServiceR { // 业务方法才带约束 pub fn create_user(self, email: str, name: str) - ResultUser { ... } pub fn find_user(self, email: str) - ResultOptionUser { ... } }示例三元组结构体 组合 trait boundpub trait FileReader { async fn read_file(self, path: Path) - ResultString; } pub trait Environment { fn max_file_size(self) - u64; } // 单依赖 service 的元组结构体 pub struct FileServiceF(ArcF); implF FileServiceF { // 构造器不带约束 pub fn new(infra: ArcF) - Self { ... } } implF: FileReader Environment FileServiceF { // 业务方法带组合约束 pub async fn read_with_validation(self, path: Path) - ResultString { ... } }反模式清单// BAD: service 依赖另一个 service pub struct BadUserServiceR, E { repository: R, email_service: E, // 不要这样做 } // BAD: 使用 trait object pub struct BadUserService { repository: Boxdyn UserRepository, // 避免 Boxdyn } // BAD: 多个基础设施依赖使用多个类型参数 pub struct BadUserServiceR, C, L { repository: R, cache: C, logger: L, // 泛型参数过多——难以使用和测试 } implR: UserRepository, C: Cache, L: Logger BadUserServiceR, C, L { // BAD: 构造器带约束导致难以使用 pub fn new(repository: R, cache: C, logger: L) - Self { ... } }仓库中的落地实例该模式在 ForgeCode 中随处可见且与面向 LLM 的文档规范结合得十分紧密——元组结构体上的///文档直接成为工具描述。例如crates/forge_app/src/agent_provider_resolver.rspub struct AgentProviderResolverS(ArcS);new()无约束业务方法get_provider/get_model所在的implS块才声明S: AgentRegistry ProviderService AppConfigService ProviderAuthService的组合约束crates/forge_services/src/tool_services/plan_create.rspub struct ForgePlanCreateF(ArcF);业务方法create_plan声明F: FileDirectoryInfra FileInfoInfra FileReaderInfra FileWriterInfra EnvironmentInfra Send Synccrates/forge_app/src/terminal_context.rspub struct TerminalContextServiceS(ArcS);。可以推断这套约定为 AI Agent 生成的新 service 提供了高度可预测的骨架构造器永远是无约束的new(ArcT)依赖关系以 trait bound 显式声明测试时只需注入 mock 基础设施既利于单元测试也利于工具描述的自动生成。八、AGENTS.md 的实际使用方式AGENTS.md 位于仓库根目录是 AI Agent以及参与协作的人类开发者进入 ForgeCode 代码库时的首要指引。结合仓库现状其使用路径包括初始上下文加载Agent 在会话开始时读取 AGENTS.md获取错误处理、测试、构建、文档等硬性约定生成代码时的实时约束任何新写的 service、领域类型、测试模块都依据上文规则产出保证风格统一提交与验证改动后按验证流程运行cargo insta test --accept提交时自动附加Co-Authored-By: ForgeCode noreplyforgecode.dev作为系统提示的一部分从 crates/forge_domain/src/snapshots/forge_domain__conversation_html__tests__conversation.snap.html 可以看到Git 署名等规则会被渲染进会话上下文成为 Agent 的常驻行为准则。总结AGENTS.md 本质上是一份面向 AI 协作的工程契约anyhowthiserror的分层错误模型、三段式测试与pretty_assertions、cargo insta test --accept的快照验证流、derive_setters的链式领域类型、面向 LLM 的///文档、以及单泛型 Arc 组合 trait bound的 service 骨架共同构成了 ForgeCode 代码库高一致性、高可测试性的基础。Agent 或开发者只要逐条落实这些约定就能产出与仓库现有代码同构、可被模型稳定理解的 Rust 代码。延伸阅读根目录工程配置Cargo.tomlworkspace 结构、rust-toolchain.toml、insta.yaml领域层定义crates/forge_domain/src/lib.rs、crates/forge_domain/src/error.rs应用层实现与测试crates/forge_app/src/agent.rs、crates/forge_app/src/agent_provider_resolver.rs服务层工具实现crates/forge_services/src/tool_services/plan_create.rs工具描述渲染crates/forge_domain/src/tools/descriptions、crates/forge_app/src/tool_registry.rs快照测试示例crates/forge_app/src/snapshots、crates/forge_display/src/snapshots赞分享人工智能AI Agent代码智能体AI 应用CLI开发工具【免费下载链接】forgecodeAI enabled pair programmer for Claude, GPT, O Series, Grok, Deepseek, Gemini and 300 models项目地址https://gitcode.com/gh_mirrors/forge39/forgecode点击查看免费下载相关推荐PandaWiki 仓库协作与开发规范指南基于 AGENTS.md 的代码 Agent 实操手册PandaWiki 仓库协作与开发规范指南基于 AGENTS.md 的代码 Agent 实操手册 本指南以 PandaWiki 仓库根目录的 AGENTS.m后端前端人工智能AI 应用RAG知识管理JupyterLab 仓库 AI 代理开发协作指南基于 AGENTS.md 的源码级工作规范与实践JupyterLab 仓库 AI 代理开发协作指南基于 AGENTS.md 的源码级工作规范与实践 本文以 JupyterLab 仓库根目录下的 AGENTS前端后端数据科学开发工具基于 AGENTS.md 的 Gumroad 开源仓库开发协作指南Agent 技能、代码注释与工程规范实战基于 AGENTS.md 的 Gumroad 开源仓库开发协作指南Agent 技能、代码注释与工程规范实战 本篇指南以 AGENTS.md https://l音视频后端上一篇如何5分钟搞定多平台抢票智能抢票助手终极指南下一篇Introduction创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表