拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OmniRoute 贡献开发指南:从零开始理解 AI 网关的架构、调试与开发规范

OmniRoute 贡献开发指南从零开始理解 AI 网关的架构、调试与开发规范【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline Copilot. Quota-aware auto-fallback, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute本文以 OmniRoute 项目根目录的CLAUDE.md及仓库内各文档、源码与测试为核心骨架系统讲解如何快速上手开发、理解统一 AI 网关的分层架构与请求处理管线、掌握三层弹性容错机制Provider Circuit Breaker、Connection Cooldown、Model Lockout的区别与调试方法并遵守从代码风格、数据库约束、安全红线到测试覆盖率的完整质量门槛。读完本文你将具备在 OmniRoute 仓库中进行新 Provider 接入、新 API 路由、新 DB 模块、新 MCP 工具等常见开发任务的实战能力。快速上手开发环境与常用命令OmniRoute 是一个单仓库monorepo核心由src/Next.js 16 应用、open-sse/流式引擎工作区、electron/桌面应用、tests/测试组成。在根目录执行以下命令即可完成从安装到校验的完整循环npm install # 安装依赖自动从 .env.example 生成 .env npm run dev # 启动开发服务器默认 http://localhost:20128 npm run build # 生产构建Next.js 16 standalone npm run lint # ESLint预期 0 错误警告为历史遗留 npm run typecheck:core # TypeScript 类型检查应保持干净 npm run typecheck:noimplicit:core # 严格检查不允许任何隐式 any npm run test:coverage # 单元测试 覆盖率门槛75/75/75/70 —— 语句/行/函数/分支 npm run check # lint 测试合并执行 npm run check:cycles # 检测循环依赖说明文档中提到的覆盖率为语句/行/函数 75%、分支 70%当前仓库 package.json 中test:coverage的 c8 参数基线为 statements/lines/functions 60%、branches 60% 的托底门槛硬性质量门保持在更高水位详见后文「测试策略与覆盖率门」。运行测试的三种方式# 单个测试文件Node.js 原生测试运行器 —— 适用于大部分测试 node --import tsx/esm --test tests/unit/your-file.test.ts # VitestMCP 服务器、autoCombo、缓存相关 npm run test:vitest # 全部测试套件 npm run test:all完整的测试矩阵见 CONTRIBUTING.md → Running Tests深入架构见 AGENTS.md。项目结构分层一览OmniRoute 的架构围绕一个端点、多家 Provider、自动回退展开代码按职责清晰分层层级位置职责API 路由src/app/api/v1/Next.js App Router —— 入口点处理器open-sse/handlers/请求处理chat、embeddings 等执行器open-sse/executors/按 Provider 定制的 HTTP 分发翻译器open-sse/translator/格式转换OpenAI↔Claude↔Gemini转换器open-sse/transformer/响应 API ↔ chat completions服务open-sse/services/组合路由、限流、缓存等数据库src/lib/db/110 个顶层 SQLite 领域模块130 个迁移领域/策略src/domain/策略引擎、成本规则、回退逻辑MCP 服务器open-sse/mcp-server/107 个独立工具3 种传输stdio/SSE/Streamable HTTP32 个作用域A2A 服务器src/lib/a2a/JSON-RPC 2.0 Agent 协议技能src/lib/skills/可扩展的技能框架记忆src/lib/memory/持久化对话记忆monorepo 构成src/Next.js 16 应用、open-sse/流式引擎工作区、electron/桌面应用、tests/、bin/CLI 入口。请求管线一次 Chat 请求的完整旅程Client → /v1/chat/completions (Next.js route) → CORS → Zod validation → auth? → policy check → prompt injection guard → handleChatCore() [open-sse/handlers/chatCore.ts] → cache check → rate limit → combo routing? → resolveComboTargets() → handleSingleModel() per target → translateRequest() → getExecutor() → executor.execute() → fetch() upstream → retry w/ backoff → response translation → SSE stream or JSON → If Responses API: responsesTransformer.ts TransformStream所有 API 路由遵循统一模式Route → CORS preflight → Zod body validation → Optional authextractApiKey/isValidApiKey→ API key 策略执行 → Handler 委托open-sse。OmniRoute 没有全局 Next.js middleware——所有拦截都是路由级的。Combo 路由open-sse/services/combo.ts支持 19 种公开策略priority、weighted、fill-first、round-robin、p2c、random、least-used、cost-optimized、reset-aware、reset-window、headroom、strict-random、auto、lkgp、context-optimized、cache-optimized、context-relay、fusion、pipeline。每个目标通过handleSingleModel()执行该函数用每目标错误处理和熔断检查包装handleChatCore()。关于 13 因子的 Auto-Combo 评分见 AUTO-COMBO.md当前实现为 16 因子评分见open-sse/services/autoCombo/scoring.ts的DEFAULT_WEIGHTS三层弹性架构见 RESILIENCE_GUIDE.md。三层弹性容错机制一次彻底区分OmniRoute 中有三个相关但截然不同的临时故障机制。调试路由行为时务必区分它们的作用域。可对照三层弹性架构图源文件resilience-3layers.mmd快速定位。Provider Circuit BreakerProvider 熔断器作用域整个 Provider例如glm、openai、anthropic。目的当某个 Provider 在上游/服务层反复失败时停止向其发送流量避免一个不健康的 Provider 拖慢每一个请求。实现核心类src/shared/utils/circuitBreaker.ts聊天门控/执行接线src/sse/handlers/chatHelpers.ts、src/sse/handlers/chat.ts运行时状态 APIsrc/app/api/monitoring/health/route.ts共享包装器open-sse/services/accountFallback.ts持久化状态表domain_circuit_breakers状态CLOSED正常放行流量。OPENProvider 被临时阻断调用方会收到 provider-circuit-open 响应或 Combo 路由转向其他目标。HALF_OPEN重置超时已到允许一个探测请求。成功则熔断关闭失败则重新打开。从源码看熔断器还包含DEGRADED中间态src/shared/utils/circuitBreaker.ts的STATE常量并在failureThreshold/resetTimeout之外支持按失败类型kindThresholds区分阈值、指数退避maxBackoffMultiplier、backoffEscalationCount与状态迁移历史记录transitionHistory。默认值见 open-sse/config/constants.ts 的PROVIDER_PROFILES均可通过OMNIROUTE_CIRCUIT_BREAKER_*环境变量覆盖Provider 类型熔断阈值重置超时OAuth8OMNIROUTE_CIRCUIT_BREAKER_OAUTH_THRESHOLD60000msOMNIROUTE_CIRCUIT_BREAKER_OAUTH_RESET_MSAPI Key12OMNIROUTE_CIRCUIT_BREAKER_API_KEY_THRESHOLD30000msOMNIROUTE_CIRCUIT_BREAKER_API_KEY_RESET_MS本地local2OMNIROUTE_CIRCUIT_BREAKER_LOCAL_THRESHOLD15000msOMNIROUTE_CIRCUIT_BREAKER_LOCAL_RESET_MS注文档原文给出的阈值为 OAuth 3/60s、API Key 5/30s、Local 2/15s当前仓库 constants.ts 已根据规模化后的连接数上调为 OAuth 8/60s、API Key 12/30s、Local 2/15s并新增了 Provider 级整体熔断OMNIROUTE_PROVIDER_BREAKER_*_FAILURE_THRESHOLD、_WINDOW_MS、_COOLDOWN_MS与自适应熔断 v2DEGRADATION_THRESHOLD、MAX_BACKOFF_MULTIPLIER、BACKOFF_ESCALATION_COUNT。以当前源码为准。哪些状态会触发 Provider 熔断只有 Provider 级失败状态码会 trip Provider 熔断器(408, 500, 502, 503, 504);不要因为常见账户/Key/模型错误如大多数401、403或429场景而 trip 整个 Provider 的熔断器。这些通常属于连接冷却或模型锁定范围。一个普通的 API Key Provider403应该是可恢复的除非它被归类为终端性 Provider/账户错误。熔断器采用惰性恢复而非后台定时器。当OPEN到期时getStatus()、canExecute()、getRetryAfterMs()等读路径会把状态刷新为HALF_OPEN避免仪表盘和 Combo 候选构建器永远排除一个已过期的 Provider。Connection Cooldown连接冷却作用域单个 Provider 连接/账户/Key。目的临时排除一个坏 Key/账户同时允许同一 Provider 的其他连接继续服务请求。实现写入/更新路径src/sse/services/auth.ts::markAccountUnavailable()账户选择/过滤src/sse/services/auth.ts::getProviderCredentials...冷却计算open-sse/services/accountFallback.ts::checkFallbackError()设置src/lib/resilience/settings.tsProvider 连接上的关键字段rateLimitedUntil; testStatus: unavailable; lastError; lastErrorType; errorCode; backoffLevel;账户选择时一个连接在以下情况被排除new Date(rateLimitedUntil).getTime() Date.now();冷却同样是惰性的当rateLimitedUntil位于过去时连接重新变得合格。成功使用时clearAccountError()会清除testStatus、rateLimitedUntil、错误字段和backoffLevel。默认连接冷却行为以 constants.ts 的PROVIDER_PROFILES为准OAuth 基础冷却5000mstransientCooldown。API Key 基础冷却3000mstransientCooldown。API Key 遇到429时应优先遵循上游重试指示Retry-After、reset 头或可解析的 reset 文本。反复的可恢复失败使用指数退避baseCooldownMs * 2 ** failureIndex;防惊群anti-thundering-herd硬守卫会阻止同一连接上的并行失败叠加冷却或翻倍backoffLevel。终端状态不是冷却banned、expired、credits_exhausted在有意的状态保持为不可用直到凭据/设置变更或操作员重置。不要用临时冷却状态覆盖终端状态。Model Lockout模型锁定作用域Provider 连接 模型。目的当仅某个模型不可用或被配额限制时避免禁用整个连接。示例按模型计配额的 Provider 返回429。本地 Provider 对缺失模型返回404。Provider 特有的模式/模型许可失败如特定 Grok 模式。Model Lockout 位于open-sse/services/accountFallback.ts允许同一连接继续服务其他模型。它默认关闭src/lib/resilience/settings.ts中enabled: false详见 RESILIENCE_GUIDE.md 的配置表并支持自定义冷却窗口与失败计数上限当锁定期满后再次失败的模型会继续升级冷却而不是从 1 重新计数。调试指导如果一个 Provider 的所有 Key 都被排除同时检查 Provider 熔断状态和每个连接的rateLimitedUntil/testStatus。如果一个 Provider 在重置窗口之后仍被永久排除检查代码是否读取了原始state而不是使用getStatus()/canExecute()。如果一个 Provider Key 失败但其他 Key 应正常工作优先考虑连接冷却而非 Provider 熔断器。如果只有单个模型失败优先考虑模型锁定而非连接冷却。如果一个状态应当自恢复它应拥有未来的时间戳/重置超时和一个能在过期时刷新状态的读路径。终端状态需要手动凭据或配置变更。核心规范代码风格、数据库与错误处理代码风格2 空格缩进、分号、双引号、100 字符宽度、es5 trailing comma通过 lint-staged 由 Prettier 强制执行Import 顺序外部 → 内部/、omniroute/open-sse→ 相对路径命名文件camelCase/kebab-case、组件PascalCase、常量UPPER_SNAKEESLintno-eval、no-implied-eval、no-new-func 全仓库错误no-explicit-anyopen-sse/和tests/内为警告TypeScriptstrict: false、目标 ES2022、模块 esnext、解析 bundler。优先显式类型数据库始终通过src/lib/db/领域模块访问数据库——绝不在路由或处理器中写原始 SQL绝不在src/lib/localDb.ts中添加逻辑它只是再导出层绝不从localDb.ts做 barrel import——应导入具体的db/模块DB 单例getDbInstance()来自src/lib/db/core.tsWAL journaling迁移src/lib/db/migrations/——带版本号的 SQL 文件幂等在事务中执行错误处理使用具体错误类型的 try/catch配合 pino context 记录日志不要吞掉 SSE 流中的错误——使用 abort 信号进行清理返回正确的 HTTP 状态码4xx/5xx安全红线不可逾越的硬性规则绝不使用eval()、new Function()或隐式 eval所有输入通过 Zod schema 验证静态凭据加密AES-256-GCM上游 header 白名单src/shared/constants/upstreamHeaders.ts——编辑时保持 sanitize、Zod schema 和单元测试同步公共上游凭据Gemini/Antigravity/Windsurf 风格的 OAuth client_id/secret 从公共 CLI 提取的 Firebase Web key必须通过open-sse/utils/publicCreds.ts的resolvePublicCred()嵌入——绝不作为字符串字面量。强制模式见 PUBLIC_CREDS.md错误响应HTTP/SSE/Executor/MCP handler必须通过open-sse/utils/error.ts的buildErrorBody()或sanitizeErrorMessage()——绝不在响应体里放原始err.stack或err.message。见 ERROR_SANITIZATION.md由变量构造的 shell 命令当exec()/spawn()需要运行时值时通过env选项传入自动 shell-escape——绝不将不可信/外部路径字符串插值进脚本体。参考src/mitm/cert/install.ts::updateNssDatabases优先使用安全默认库如 Helmet.js、DOMPurify、ssrf-req-filter、safe-regex、Google Tink而非自定义实现常见开发场景演练新增一个 Provider在src/shared/constants/providers.ts注册加载时经 Zod 验证如需自定义逻辑在open-sse/executors/添加 executor继承BaseExecutor若非 OpenAI 格式在open-sse/translator/添加 translator若基于 OAuth在src/lib/oauth/constants/oauth.ts添加 OAuth 配置——如果上游 CLI 提供公共 client_id/secret通过resolvePublicCred()嵌入见 PUBLIC_CREDS.md绝不作为字面量在open-sse/config/providerRegistry.ts注册模型在tests/unit/编写测试若新增嵌入式默认值需包含 publicCreds 大小确认新增一个 API 路由在src/app/api/v1/your-route/下创建目录创建带GET/POSThandler 的route.ts遵循模式CORS → Zod body 验证 → 可选认证 → Handler 委托Handler 放在open-sse/handlers/从那里 import不要内联错误响应使用open-sse/utils/error.ts的buildErrorBody()/errorResponse()自动 sanitize——绝不把原始err.stack/err.message放进 body。见 ERROR_SANITIZATION.md添加测试——至少包含一个断言错误响应不泄漏堆栈!body.error.message.includes(at /)新增一个 DB 模块创建src/lib/db/yourModule.ts——从./core.ts导入getDbInstance为领域表导出 CRUD 函数如需新表在src/lib/db/migrations/添加迁移从src/lib/localDb.ts再导出仅加入再导出列表编写测试新增一个 MCP 工具在open-sse/mcp-server/tools/添加工具定义Zod 输入 schema async handler注册到工具集由createMcpServer()组装分配到合适的作用域编写测试工具调用记录在mcp_audit表新增一个 A2A 技能在src/lib/a2a/skills/创建技能已存在 5 个smart-routing、quota-management、provider-discovery、cost-analysis、health-report技能接收任务上下文消息、元数据→ 返回结构化结果在src/lib/a2a/taskExecution.ts的A2A_SKILL_HANDLERS注册在src/app/.well-known/agent.json/route.ts发布agent card在tests/unit/编写测试在 A2A-SERVER.md 的技能表中补充文档新增一个 Cloud Agent在src/lib/cloudAgent/agents/创建继承CloudAgentBase的 Agent 类已存在 3 个codex-cloud、devin、jules实现createTask、getStatus、approvePlan、sendMessage、listSources在src/lib/cloudAgent/registry.ts注册如需 OAuth/凭据管理添加到src/lib/oauth/providers/编写测试 在 CLOUD_AGENT.md 补充文档新增 Guardrail / Eval / Skill / Webhook 事件Guardrailsrc/lib/guardrails/→ 文档GUARDRAILS.mdEval 套件src/lib/evals/→ 文档EVALS.mdSkill沙箱src/lib/skills/→ 文档SKILLS.mdWebhook 事件src/lib/webhookDispatcher.ts→ 文档WEBHOOKS.md测试策略与覆盖率门类别命令单元测试npm run test:unit单文件node --import tsx/esm --test tests/unit/file.test.tsVitestMCP、autoCombonpm run test:vitestE2EPlaywrightnpm run test:e2e协议 E2EMCPA2Anpm run test:protocols:e2e生态npm run test:ecosystem覆盖率门npm run test:coverage75/75/75/70 —— 语句/行/函数/分支覆盖率报告npm run coverage:reportPR 规则如果你修改了src/、open-sse/、electron/或bin/中的生产代码必须在同一 PR 中附带或更新测试。测试层级优先级单元优先 → 集成多模块或 DB 状态→ e2e仅 UI/工作流。Bug 复现应像自动化测试一样编码先于或伴随修复提交。Copilot 覆盖率策略当一个 PR 修改生产代码且覆盖率低于 75%语句/行/函数或 70%分支时不要只报告——添加或更新测试、重新运行覆盖率门然后请求确认。PR 报告中包含已运行的命令、修改的测试文件和最终覆盖率结果。Git 工作流与提交规范# 绝不要直接提交到 main git checkout -b feat/your-feature git commit -m feat: 描述你的变更 git push -u origin feat/your-feature分支前缀feat/、fix/、refactor/、docs/、test/、chore/提交格式Conventional Commitsfeat(db): add circuit breaker—— scope 可选值db、sse、oauth、dashboard、api、cli、docker、ci、mcp、a2a、memory、skillsHusky 钩子pre-commitlint-staged check-docs-synccheck:any-budget:t11pre-pushnpm run test:unit运行环境与关键配置运行时Node.js ≥22.22.2 23 | ≥24 25当前 package.json 的engines为22.22.2 23 || 24.0.0 27、ES ModulesTypeScript5.9目标 ES2022模块 esnext解析 bundler路径别名/*→src/omniroute/open-sse→open-sse/omniroute/open-sse/*→open-sse/*默认端口20128API 与仪表盘同端口数据目录DATA_DIR环境变量默认~/.omniroute/核心环境变量PORT、JWT_SECRET、API_KEY_SECRET、INITIAL_PASSWORD、REQUIRE_API_KEY、APP_LOG_LEVEL初始化cp .env.example .env然后生成JWT_SECRETopenssl rand -base64 48和API_KEY_SECRETopenssl rand -hex 32硬性规则清单绝不提交机密或凭据绝不在localDb.ts添加逻辑绝不使用eval()/new Function()/隐式 eval绝不直接提交到main绝不在路由中写原始 SQL——使用src/lib/db/模块绝不静默吞掉 SSE 流中的错误始终用 Zod schema 验证输入修改生产代码时始终附带测试覆盖率必须 ≥75%语句、行、函数/≥70%分支。当前实测约 82%未经操作员明确许可绝不绕过 Husky 钩子--no-verify、--no-gpg-sign绝不将公共上游 OAuth client_id/secret 或 Firebase Web key 作为字符串字面量嵌入——始终通过resolvePublicCred()open-sse/utils/publicCreds.ts。见 PUBLIC_CREDS.md绝不在 HTTP/SSE/Executor 响应中返回原始err.stack/err.message——始终通过buildErrorBody()或sanitizeErrorMessage()open-sse/utils/error.ts。见 ERROR_SANITIZATION.md绝不在exec()/spawn()中字符串插值外部路径或运行时值——改用env选项传入。参考src/mitm/cert/install.ts::updateNssDatabases绝不忽略 CodeQL/Secret-Scanning 警告(a) 先查阅上述模式文档判断是否适用(b) 在忽略注释中记录技术理由。先例js/stack-trace-exposure在调用点经sanitizeErrorMessage()路由后判定为已知 CodeQL 限制无法识别自定义 sanitizer引用 ERROR_SANITIZATION.md 标记为 false positive绝不公开会 spawn 子进程的路由/api/mcp/、/api/cli-tools/runtime/除非在src/server/authz/routeGuard.ts的isLocalOnlyPath()分类中。回环强制在任何认证检查之前无条件发生——经隧道泄漏的 JWT 不能触发进程 spawn。见 ROUTE_GUARD_TIERS.md绝不包含署名给 AI 助手、LLM 或自动账户的Co-Authored-By尾缀如含 Claude、GPT、Copilot、Bot 名称或anthropic.com/openai.com/bot 所有的noreply.github.com邮箱。此类尾缀会在 GitHub 上把提交归属路由到 bot 账户在 PR 历史中隐藏真正的作者diegosouzapw。人类协作者——包括上游 PR 作者和移植到 OmniRoute 的 issue 报告者——可以且应当使用标准Co-authored-by: Name email尾缀上游移植工作流/port-upstream-features、/port-upstream-issues依赖于此。参考文档索引任何非理论性变更之前先阅读对应领域的深度分析领域文档仓库导航docs/architecture/REPOSITORY_MAP.md架构docs/architecture/ARCHITECTURE.md工程参考docs/architecture/CODEBASE_DOCUMENTATION.mdAuto-Combo评分、策略docs/routing/AUTO-COMBO.md弹性3 种机制docs/architecture/RESILIENCE_GUIDE.md推理重放docs/routing/REASONING_REPLAY.md技能框架docs/frameworks/SKILLS.md记忆系统FTS5 Qdrantdocs/frameworks/MEMORY.mdCloud Agentdocs/frameworks/CLOUD_AGENT.mdGuardrailsPII/注入/视觉docs/security/GUARDRAILS.md公共上游凭据Gemini 等docs/security/PUBLIC_CREDS.md错误消息消毒docs/security/ERROR_SANITIZATION.mdEvalsdocs/frameworks/EVALS.md合规/审计docs/security/COMPLIANCE.mdWebhooksdocs/frameworks/WEBHOOKS.md授权管线docs/architecture/AUTHZ_GUIDE.md隐身TLS/指纹docs/security/STEALTH_GUIDE.mdAgent 协议A2A/ACP/Clouddocs/frameworks/AGENT_PROTOCOLS_GUIDE.mdMCP 服务器docs/frameworks/MCP-SERVER.mdA2A 服务器docs/frameworks/A2A-SERVER.mdAPI 参考 OpenAPIdocs/reference/API_REFERENCE.mddocs/reference/openapi.yamlProvider 目录自动生成docs/reference/PROVIDER_REFERENCE.md发布流程docs/ops/RELEASE_CHECKLIST.md【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline Copilot. Quota-aware auto-fallback, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门