


为模块化Rust AI框架添加新的AI提供商和向量存储
在扩展支持多家AI提供商的Rust框架时使用。沿用现有的trait和builder,保持WebAssembly支持,让钩子在流式和非流式下行为一致,并检查录制的测试cassette中没有泄露API密钥。
要使用这个AI规则
## 只改所请求的范围,未经要求不提交
- 修改代码前,先阅读现有实现、清单、测试和公共文档。
- 将每项变更严格限制在用户要求的范围内。
- 优先使用现有 trait、builder、模块和错误类型,不要创建平行抽象。
- 不要添加 TODO、stub、占位行为或推测性的公共 API。
- 除非用户明确要求,否则不要提交、暂存、推送、创建分支或发起拉取请求。
- 保留与任务无关的用户变更,并在脏工作树中安全地绕开它们。
- 即使附近的设计可以改进,也要避免无关重构。
- 区分贡献者政策与仓库专用工程规则,并同时遵守两者。
- 缺少必要的产品意图或外部授权时停止。
## 在整个工作区中保持crate划分和feature flag一致
- 让公共 facade crate、核心 crate、配套集成、派生宏、示例和测试各自保持既定职责。
- 由 facade 重新导出核心 API,并通过 feature flag 暴露可选的配套 crate。
- 更改公共 feature、集成或模块路径前,先检查工作区清单和 facade 导出。
- 除非有充分的架构理由必须放入核心,否则将提供商和向量存储集成放在配套 crate 中。
- 将工作区示例、各 crate 示例和集成测试明确区分。
- 添加配套 crate 时,按需更新根依赖、feature、facade 重新导出、示例、README 和 crate 文档。
- 确保各种 feature 组合都能编译,同时不暴露不可用模块。
- 让 facade 与受影响的配套 crate 之间的公共文档保持同步。
- 在代码和清单确认之前,不要描述模块路径或 feature。
## 基于共享trait构建,不做提供商专用的版本
- 基于框架的核心补全、嵌入、向量索引和可调用工具 trait 构建集成。
- 不要为现有跨提供商 trait 创建提供商专用替代方案。
- 对可配置的公共类型遵循既有 builder 模式。
- 让构建过程保持流畅和类型安全,并且仅在显式 build 步骤后完成。
- 使用将提供商扩展与底层 HTTP 传输分离的通用客户端架构。
- 显式声明提供商能力,使不支持的行为在编译时失败。
- 用明确的标记类型表示缺失能力,不要在运行时猜测。
- 保持提供商 builder 与公共客户端别名之间的 API key 类型关系。
- 将提供商专用请求和响应类型限制在转换边界之后。
## 让共享的异步代码在WebAssembly上也能运行
- 在共享 trait、future、错误和集成中保持 WebAssembly 支持。
- 当目标之间存在差异时,使用框架兼容抽象,而不是原始 `Send` 和 `Sync` 约束。
- 对动态返回的 future 使用指定的可移植 boxed-future 类型。
- 仅在支持的目标上应用原生线程安全约束。
- 不要让 WebAssembly boxed error 带有不支持的原生专用约束。
- 更改共享 trait 后,同时测试原生和面向 WebAssembly 的类型签名。
- 避免添加会悄然排除受支持目标的依赖或 API。
- 将条件编译限制在狭小范围,并解释目标之间的差异。
- 确保提供商、向量存储和钩子 API 使用相同的可移植性契约。
## 使用明确的错误类型,并为每个新的公共API写文档
- 不要将 `String` 用作新的可失败 API 的错误类型。
- 定义显式错误枚举,并通过框架错误辅助工具保留有用的提供商响应细节。
- 优先使用 `?` 和有意义的转换,不要手动丢失错误上下文。
- 仅当周围不变量能明显证明情况不可能发生时,才使用 `unwrap()` 或 `expect()`。
- 为每个新的公共类型、函数、trait 和方法添加条目文档。
- 为每个新的公共模块添加模块文档。
- 让示例与真实 API、模型常量、模块路径和 feature flag 保持一致。
- 需要外部凭据或服务的示例应标记为不运行。
- 公共行为发生变化时,更新 README 文件和 crate 级文档。
## 参照最接近的现有提供商来添加新的AI提供商
- 实现或修改提供商之前,先研究最接近的现有提供商。
- 添加提供商扩展与 builder 类型、提供商实现以及显式能力声明。
- 如果框架同时暴露两种路径,则支持从环境值和直接值构建。
- 让公共客户端和 builder 别名与提供商 builder 的 API key 类型保持一致。
- 使用显式凭据标记或身份验证类型,并在调试显示中遮盖携带凭据的值。
- 将框架请求转换为提供商的真实线上格式,再将响应转换回框架类型。
- 仅当提供商实际支持时才添加流式处理,并通过标准辅助工具保留提供商错误。
- 遵循既有遥测约定和扩展 trait。
- 不要虚构提供商真实 API 中不存在的请求或响应字段。
- 添加范围明确的测试或示例,证明受支持的行为。
## 接入带有真实过滤和明确搜索结果的向量存储
- 除非有理由归核心所有,否则将向量存储集成放入配套 crate。
- 同时实现返回结果的搜索和仅返回标识符的搜索。
- 使用能反映后端真实筛选能力的过滤器类型。
- 返回框架的向量存储错误变体,不要返回临时拼凑的字符串错误。
- 应用核心框架所用的同一套可移植异步约束。
- 明确处理分数、文档、标识符和元数据转换。
- 定义排序、数量限制、空结果和后端错误的行为。
- 测试过滤器、排名顺序、结果数量限制、缺失记录和转换失败。
- 在不嵌入秘密信息的前提下,记录所需 feature、凭据、索引和外部设置。
## 为每种钩子事件规定可用的动作
- 将钩子建模为一次运行范围内的生命周期观察器和引导器。
- 向每个事件传递运行上下文,包括运行标识、轮次、流式模式、代理标识和共享暂存状态。
- 为每种事件提供专属动作类型,使不受支持的动作组合在编译时失败。
- 让补全调用钩子修补请求或停止处理。
- 让工具调用和工具结果钩子为后续钩子重写值,并在定义处将 skip 或 stop 作为终止动作。
- 用显式的 fail、retry、repair、skip 和 stop 选项表示无效工具调用的处理方式。
- 将仅观察事件限制为 continue 或 stop。
- 当 stop 动作会使堆栈短路时,在引导钩子之前注册观察钩子。
- 记录哪些动作转换数据、哪些动作累积数据,以及哪些动作终止处理。
## 让叠加的钩子在流式和非流式下以相同方式组合
- 钩子嵌套或堆叠时,保持各事件专用的组合语义。
- 按注册顺序合并补全请求修补内容。
- 追加额外上下文,浅合并附加参数,并对活动工具集合取交集。
- 仅对已记录的标量和历史字段采用最后写入者优先,并在覆盖具有影响时发出警告。
- 将每个请求修补内容限制在一个轮次内,绝不要意外让它持续生效。
- 将工具调用和工具结果的重写依次传给所有后续钩子。
- 当终止动作要求时,立即停止计算堆栈。
- 让流式和非流式接口共用同一个生命周期驱动器。
- 通过流式和非流式入口测试完全相同的钩子行为。
- 为嵌套堆栈、合并冲突、重写链、skip 和 stop 添加组合测试。
## 选择最小的回归测试,提供商调用用录制的cassette测试
- 在最小且可靠的范围内添加回归覆盖。
- 对独立的转换或逻辑缺陷,优先在实现旁添加单元测试。
- 当行为依赖提供商请求和响应流量时,使用由 cassette 支持的提供商测试。
- 仅当确定性的 cassette 重放无法表示该行为时,才使用被忽略的在线测试。
- 添加、更新、录制或重放提供商测试前,先阅读仓库测试指南。
- 默认重放 cassette,使普通测试不需要提供商凭据。
- 将测试执行范围限制在正在变更的提供商和行为上。
- 当两种接口都存在时,同时覆盖流式和非流式行为。
- 在回归断言中保留原始失败模式。
## 只为目标测试录制cassette,并检查其中是否有秘密信息
- 将录制模式视为使用外部连接和凭据并覆盖文件的操作。
- 录制前必须具备相关提供商凭据,且绝不要在输出中暴露凭据。
- 仅录制目标提供商测试,尽量减少无关 fixture 变动。
- 展示或提交每个 cassette 差异前,必须手动检查全部内容。
- 拒绝包含 API key、bearer credential、cookie、账户标识符或其他敏感值的 fixture。
- 不要接受嘈杂的 fixture;应移除无关的请求和响应变动。
- 保持自动 scrub 与安全检查启用,但不要将其当作人工检查的替代品。
- 在遮盖秘密信息和不稳定元数据的同时,保留确定性的重放数据。
- 绝不要仅为让失败测试变绿而覆盖 fixture,却不说明行为变化。
## 从小范围到大范围运行检查,并报告未能验证的部分
- 先运行最小且有用的检查,再根据影响范围和风险扩大。
- 格式化工作区,并对所有受影响的目标和 feature 运行 lint。
- 先运行范围明确的测试,再运行宽泛的工作区测试。
- 当公共 API 或文档发生变化时,构建不含依赖项的文档。
- 当共享约束或 future 发生变化时,验证原生和 WebAssembly 兼容性。
- 确认提供商线上字段与真实 API 一致,并且 cassette 差异不含秘密信息。
- 确认钩子语义在流式和非流式接口上保持一致。
- 必需检查失败时,不要宣称完成。
- 如果命令无法运行,说明原因,并准确指出仍未验证的内容。
- 报告变更范围、已运行检查、观察结果、剩余风险和有意排除的范围。
