askalf/dario

GitHub: askalf/dario

一个本地 LLM 路由器,将多个提供方统一为单一端点供工具使用并支持多账号池。

Stars: 58 | Forks: 24

dario

一个本地 LLM 路由器。你的机器上只有一个端点,背后是每一个提供方,你的工具无需更改。

npm version CI CodeQL License Downloads

快速开始适用人群后端为什么切换可信与透明常见问题

## 它是什么 Dario 在你的机器上运行,为你使用的每一种工具提供一个本地 URL,这个 URL 可以访问 **你使用的每一个 LLM**。将 Cursor、Continue、Aider、LiteLLM 或你自己的脚本——任何使用 Anthropic 或 OpenAI API 的工具——指向 `http://localhost:3456`,Dario 会将每个请求路由到正确的后端: - **Claude Max / Pro 订阅** — 基于 OAuth,按你的计划计费而非 API 价格。如果拥有多个账号,支持多账号池化。 - **OpenAI** — 使用你的 API 密钥,直接路由到 `api.openai.com`。 - **任意 OpenAI 兼容端点** — OpenRouter、Groq、本地 LiteLLM、Ollama 的 openai 兼容模式、托管的 vLLM。设置一次后端的 `baseUrl`,即可完成配置。 你的工具看到的只是一个基础 URL。`gpt-4` 走向 OpenAI,`claude-opus-4-6` 走向你的 Claude 订阅,`llama-3-70b` 走向 Groq。无需让任何工具了解这些细节。 **无需在任何地方注册账户。** 仅使用单个后端的 Claude dario 只需 `dario login` 即可工作。多后端 dario 仅依赖本地配置文件。完全不联系外部服务。零运行时依赖。约 2,000 行 TypeScript。 ## 适用人群 **最佳匹配:** - **在多个工具中使用多个 LLM 的开发者**,厌倦了为每个工具配置基础 URL、API 密钥和提供方设置。 - **Claude Max 或 Pro 订阅者**,希望订阅能在机器上每个工具中可用,而无需为每个请求支付 API 费率。 - **运行本地或托管 OpenAI 兼容服务器(LiteLLM、vLLM、Ollama、Groq、OpenRouter)的团队**,希望拥有一个稳定本地端点供所有工具复用。 - **在 Claude 订阅上运行多智能体工作负载的高级用户**,希望在自己的机器上实现基于账户剩余配额感知的池化路由,无需托管平台。 **不适用场景:** - 你需要每个请求的供应商托管生产 SLA。使用提供方 API 直接访问。 - 你需要一个带有仪表板的托管多租户路由平台。试试 [askalf](https://askalf.org),同一生态中的独立产品,不同问题,不同工具。 - 你只想要一个聊天 UI。使用 claude.ai 或 chatgpt.com。 ## 首次使用场景 在全新机器上的流程: ``` # Install npm install -g @askalf/dario # Optional: log in to your Claude subscription (Max or Pro) dario login # Optional: add an OpenAI-compat backend dario backend add openai --key=sk-proj-... # Start the proxy dario proxy # Use it — set these once, every tool that honors them just works export ANTHROPIC_BASE_URL=http://localhost:3456 export ANTHROPIC_API_KEY=dario export OPENAI_BASE_URL=http://localhost:3456/v1 export OPENAI_API_KEY=dario ``` 现在从相同的 Cursor/Continue/Aider 实例: - `gpt-4o` → OpenAI,你的密钥,直接通过 - `claude-opus-4-6` → Claude 订阅,按你的 Max 计划计费 - `opus` → 快捷方式,等同于上述 - `llama-3.1-70b` 在 OpenRouter 上 → 配置 `dario backend add openrouter --key=sk-or-... --base-url=https://openrouter.ai/api/v1`,完成 一个 URL。你的工具无需关心或知道是哪个提供方在响应。 ## 为什么切换 **如果你的情况符合以下任意一条,请使用 dario:** - 你使用了多个 LLM 提供方,或多个工具,或两者都有——并且厌倦了为每个工具配置不同的基础 URL 和每个提供方的 API 密钥。 - 你支付了 Claude Max 或 Pro 费用,并希望该订阅在机器上的每个工具中可达,无需按请求支付 API 费率或暴露第二个计费面。 - **使用多账户池模式**,如果你在 Claude 订阅上运行多智能体工作负载并遇到每个账户的速率限制。添加 2–N 个账户(通过 `dario accounts add`),dario 会根据每个账户的剩余配额在它们之间路由,全部在本地进行,针对你自己的订阅。参见 [多账户池模式](#multi-account-pool-mode)。 - **如果需要供应商托管的生产 SLA 或高级编排原语**,请直接使用提供方 API。Dario 并不试图替代它们的 API——而是希望在所有它们前面加一层本地垫片,让你的工具不关心具体是哪个。 **不要使用 dario 的情况:** - 你需要一个在后台调用 `claude --print` 的子进程桥接(openclaw-claude-bridge 或类似)。这适用于可接受单订阅速率上限和单机部署的单团队单机工作负载,属于不同的权衡与工具。 ## 快速开始 ``` # Install npm install -g @askalf/dario # Claude subscription path (detects Claude Code credentials if CC is installed, # runs its own OAuth flow otherwise) dario login # OpenAI or any OpenAI-compat provider (optional, additive) dario backend add openai --key=sk-proj-... # Start the proxy dario proxy # Point anything that speaks the Anthropic or OpenAI API at localhost:3456 export ANTHROPIC_BASE_URL=http://localhost:3456 export ANTHROPIC_API_KEY=dario export OPENAI_BASE_URL=http://localhost:3456/v1 export OPENAI_API_KEY=dario ``` Opus、Sonnet、Haiku、GPT-4o、o1、o3、o4,以及任何已配置 OpenAI 兼容后端提供的模型。支持流式调用、工具使用、提示缓存、扩展思考。**零运行时依赖**。在可用时自动在 [Bun](https://bun.sh) 下启动,以保证与 Claude Code 运行时一致的 TLS 指纹;否则在 Node.js 上运行。 ## 后端 Dario 的路由围绕 **后端** 组织,每个后端拥有独立的认证与目标。v3.6.0 内置两个后端,未来计划支持更多。 ### 1. Claude 订阅后端(内置) 基于 OAuth 的 Claude Max / Pro,按计划计费而非 API 费用。通过 `dario login` 激活。 **功能:** - 每个请求在发送到上游前被替换为 Claude Code 模板——包含 25 个工具定义、25KB 系统提示、精确的 CC 字段顺序、精确的 Beta 头与元数据结构。仅保留对话内容。Anthropic 的分类器看到的行为与 Claude Code 会话一致,从而保持订阅计费而非额外用量。 - **计费标签**按 CC 自身算法重建:`x-anthropic-billing-header: cc_version=.; cc_entrypoint=cli; cch=<5-char-hex>;`,其中 `build_tag = SHA-256(seed + chars[4,7,20] of user message + version).slice(0,3)`。 - **OAuth 配置**在启动时自动从已安装的 CC 二进制文件中检测。当 Anthropic 轮换 `client_id`、授权 URL 或作用域时,dario 在下次运行时自动获取新值。 - **多账号池模式**——详见下文。自动激活条件是 `~/.dario/accounts/` 中存在 2 个及以上账号。 - **框架脱敏**——从系统提示与消息内容中移除已知指纹令牌(`OpenClaw`、`sessions_` 前缀、编排标签)。 - **Bun 自动重启**——当 Bun 可用时,dario 会重启自身以匹配 CC 运行时的 TLS 指纹;否则在 Node.js 上运行。 **直通模式**(`dario proxy --passthrough`)仅执行 OAuth 交换,不进行模板注入、身份伪装或脱敏。用于上游工具已自行构建类 Claude Code 请求时,仅需令牌认证。 **检测范围**:Claude 后端是每个请求的独立层。模板重放与脱敏设计在请求层面与 Claude Code 无法区分。无法防御的是 Anthropic 会话级行为分类器(基于每个 OAuth 的累积统计:吞吐、对话深度、流式时长、到达间隔)。实际答案是 **池模式**——将负载分散到多个订阅,使单个账号的统计信号不足以触发限制。参见 [常见问题条目](#faq) 了解完整机制。 ### 2. OpenAI 兼容后端(v3.6.0+) 支持任何使用 OpenAI 聊天完成 API 的提供方。激活方式如下: ``` # OpenAI itself (default base URL) dario backend add openai --key=sk-proj-... # Groq dario backend add groq --key=gsk_... --base-url=https://api.groq.com/openai/v1 # OpenRouter dario backend add openrouter --key=sk-or-... --base-url=https://openrouter.ai/api/v1 # Local LiteLLM / vLLM / Ollama openai-compat mode dario backend add local --key=anything --base-url=http://127.0.0.1:4000/v1 ``` 凭据存储在 `~/.dario/backends/.json`,权限为 `0600`。 **路由规则:** 当 OpenAI 兼容后端配置后,每个 `/v1chat/completions` 请求按以下规则路由: | 请求模型 | 路由目标 | |---|---| | `gpt-*`, `o1-*`, `o3-*`, `o4-*`, `chatgpt-*`, `text-davinci-*`, `text-embedding-*` | OpenAI 兼容后端 | | `claude-*`(或 `opus` / `sonnet` / `haiku`)| Claude 订阅后端 | | 其他 | 使用 Claude 后端并做 OpenAI 兼容翻译 | dario 对 OpenAI 后端的直通行为为:客户端请求体原样转发,仅替换 `Authorization` 头为配置的 API 密钥,并将 URL 指向 `baseUrl + /chat/completions`。响应体原样流回。 ### 后续计划 - **Anthropic → OpenAI 请求翻译**:针对 `/v1/messages` 请求中 GPT 系列模型名(tool_use 格式、流式增量转换)。 - **多个并发的 OpenAI 兼容后端**:按模型名路由规则(`gpt-*` → OpenAI,`llama-*` → Groq,`mixtral-*` → OpenRouter)。 - **回退规则**:“若 Claude 429,则改用 Gemini”。v3.6.0 已包含路由框架;回退逻辑将在后续版本中实现。 ## 多账户池模式 *v3.5.0 新特性,专用于 Claude 订阅后端。* Dario 可管理多个 Claude 订阅并根据每个请求的剩余配额选择账户。单个账号的 Claude dario 保持不变——**仅当 `~/.dario/accounts/` 包含 2 个及以上账号时,池模式才会激活**。 ``` dario accounts add work dario accounts add personal dario accounts add side-project dario accounts list dario proxy ``` 每个请求选择剩余配额最高的账号: ``` headroom = 1 - max(util_5h, util_7d) ``` 响应中的 `anthropic-ratelimit-unified-*` 头部会被解析回池中,供下次选择使用。返回 429 的账号会被标记为 `rejected`,并在下次窗口重置前被跳过。当所有账号都被耗尽时,请求最多等待 60 秒直至配额恢复。 账号可混合使用不同计划(Max 与 Pro 可共存);dario 仅关注剩余配额,不关心具体等级。 **池监控端点:** ``` curl http://localhost:3456/accounts # per-account utilization, claim, status curl http://localhost:3456/analytics # per-account / per-model stats, burn rate, exhaustion predictions ``` **范围说明**:v3.5.0 在请求之间实现有状态的头耗感知选择——单个请求返回 429 会标记该账号被拒绝,后续请求自动切换。请求级失败转移(in-request failover)将在 v3.5.1 中支持,并新增分析记录。 ## 命令 | 命令 | 描述 | |---|---| | `dario login` | 登录 Claude 后端(检测 CC 凭据或运行独立 OAuth 流程) | | `dario proxy` | 启动本地 API 代理,监听 3456 端口 | | `dario status` | 显示 Claude 后端 OAuth 令牌状态与有效期 | | `dario refresh` | 强制刷新 Claude 令牌 | | `dario logout` | 删除存储的 Claude 凭据 | | `dario accounts list` | 列出池中的所有账号 | | `dario accounts add ` | 向池中添加 Claude 账号(运行 OAuth 流程) | | `dario accounts remove ` | 从池中移除账号 | | `dario backend list` | 列出已配置的 OpenAI 兼容后端 | | `dario backend add --key= [--base-url=]` | 添加 OpenAI 兼容后端 | | `dario backend remove ` | 移除 OpenAI 兼容后端 | | `dario help` | 完整命令参考 | ### 代理选项 | 标志 / 环境变量 | 描述 | 默认值 | |---|---|---| | `--passthrough` / `--thin` | 精简代理(仅 OAuth 交换),不注入模板 | 关闭 | | `--preserve-tools` / `--keep-tools` | 保留客户端工具模式而非映射为 CC 工具(Claude 后端) | 关闭 | | `--model=` | 强制模型(`opus` / `sonnet` / `haiku` 或完整 ID),仅适用于 Claude 后端 | passthrough | | `--port=` | 监听端口 | `3456` | | `--host=` / `DARIO_HOST` | 绑定地址。使用 `0.0.0.0` 访问局域网,或指定 IP(如 Tailscale 接口)。非回环时需设置 `DARIO_API_KEY` | `127.0.0.1` | | `--verbose` / `-v` | 记录每个请求日志 | 关闭 | | `DARIO_API_KEY` | 若设置,所有端点(除 `/health`)需匹配 `x-api-key` 或 `Authorization: Bearer` 头。非回环绑定时必须设置 | 未设置(开放) | | `DARIO_CORS_ORIGIN` | 覆盖浏览器 CORS 源 | `http://localhost:${port}` | | `DARIO_NO_BUN` | 禁用自动 Bun 重启 | 未设置 | | `DARIO_MIN_INTERVAL_MS` | Claude 后端请求最小间隔(速率限制) | `500` | | `DARIO_CC_PATH` | 覆盖 Claude Code 二进制文件路径(用于 OAuth 检测) | 自动检测 | ## 使用方式 ### Python(Anthropic SDK) ``` import anthropic client = anthropic.Anthropic( base_url="http://localhost:3456", api_key="dario", ) msg = client.messages.create( model="claude-opus-4-6", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}], ) print(msg.content[0].text) ``` ### Python(OpenAI SDK —— 同代理,不同提供方) ``` from openai import OpenAI client = OpenAI( base_url="http://localhost:3456/v1", api_key="dario", ) # gpt-4o routes to the configured OpenAI backend msg = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Hello!"}], ) # claude-opus-4-6 routes to the Claude subscription backend — same SDK, same URL claude_msg = client.chat.completions.create( model="claude-opus-4-6", messages=[{"role": "user", "content": "Hello!"}], ) ``` ### TypeScript / Node.js ``` import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic({ baseURL: "http://localhost:3456", apiKey: "dario", }); const msg = await client.messages.create({ model: "claude-opus-4-6", max_tokens: 1024, messages: [{ role: "user", content: "Hello!" }], }); ``` ### OpenAI 兼容工具(Cursor、Continue、Aider、LiteLLM、…) ``` export OPENAI_BASE_URL=http://localhost:3456/v1 export OPENAI_API_KEY=dario ``` 任何接受 OpenAI 基础 URL 的工具均可使用。使用 Claude 模型名(`claude-opus-4-6`、`opus`、`sonnet`、`haiku`)适用于 Claude 后端,或使用 GPT 系列名称适用于已配置的 OpenAI 兼容后端。 ### curl ``` # Claude backend via Anthropic format curl http://localhost:3456/v1/messages \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{"model":"claude-opus-4-6","max_tokens":1024,"messages":[{"role":"user","content":"Hello!"}]}' # OpenAI backend via OpenAI format curl http://localhost:3456/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer dario" \ -d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello!"}]}' ``` ### 流式调用、工具使用、提示缓存、扩展思考 全部支持。Claude 后端:完整的 Anthropic SSE 格式,以及 OpenAI-SSE 格式的工具使用流。OpenAI 兼容后端:原始响应体字节流透传。 ### 库模式 ``` import { startProxy, getAccessToken, getStatus, listBackends } from "@askalf/dario"; await startProxy({ port: 3456, verbose: true }); const token = await getAccessToken(); const status = await getStatus(); const backends = await listBackends(); ``` ### 健康检查 ``` curl http://localhost:3456/health ``` ## 端点 | 路径 | 描述 | |---|---| | `POST /v1/messages` | Anthropic 消息 API(Claude 后端) | | `POST /v1/chat/completions` | OpenAI 兼容聊天 API(按模型名路由) | | `GET /v1/models` | 模型列表(Claude 模型——OpenAI 模型来自对应后端) | | `GET /health` | 代理健康 + OAuth 状态 + 请求计数 | | `GET /status` | 详细的 Claude OAuth 令牌状态 | | `GET /accounts` | 池快照(仅池模式) | | `GET /analytics` | 每账号 / 每模型统计、耗费率、耗尽预测(仅池模式) | ## 可信与透明 Dario 在本地处理你的 OAuth 令牌与 API 密钥。以下是其可信的原因: | 信号 | 状态 | |---|---| | **源代码** | 约 2,500 行 TypeScript,分布在 10 个文件中——足够小以一次审阅完 | | **依赖** | 零运行时依赖。验证:`npm ls --production` | | **npm 溯源** | 每个发布版本均通过 GitHub Actions 进行 [SLSA 溯源](https://www.npmjs.com/package/@askalf/dario) | | **安全扫描** | [CodeQL](https://github.com/askalf/dario/actions/workflows/codeql.yml) 在每次推送及每周运行 | | **凭据处理** | 令牌与 API 密钥永不记录、错误中脱敏、存储权限为 `0600` | | **OAuth 流程** | 使用 PKCE(无客户端密钥) | | **网络范围** | 默认绑定 `127.0.0.1`。`--host` 允许局域网/网格访问,需 `DARIO_API_KEY` 保护。上游流量仅发往配置的 HTTPS 目标 | | **SSRF 防护** | `/v1/m` 仅访问 `api.anthropic.com`;`/v1/chat/completions` 仅访问配置的 `baseUrl`——严格白名单 | | **遥测** | 无。零分析、追踪或数据收集 | | **审计追踪** | [CHANGELOG.md](CHANGELOG.md) 记录每个发布版本 | 验证 npm 压缩包是否与仓库一致: ``` npm audit signatures npm view @askalf/dario dist.integrity cd $(npm root -g)/@askalf/dario && npm ls --production ``` ## 常见问题 **这是否违反 Anthropic 的服务条款?** Dario 的 Claude 后端使用你现有的 Claude Code 凭据与 OAuth 令牌,以你的身份通过 Anthropic 官方 API 进行认证。 **Claude 订阅支持哪些计划?** Claude Max 与 Claude Pro。任何能使用 Claude Code 的计划均可。 **是否支持团队/企业版?** 应该可以,只要你的计划包含 Claude Code 访问权限。尚未进行广泛测试——欢迎提交结果或问题。 **是否需要安装 Claude Code?** 推荐用于 Claude 后端,但非强制要求。安装 CC 后,`dario login` 可自动获取凭据;未安装时,dario 将自行发起 OAuth 流程。 **是否需要 Bun?** 可选,推荐用于 Claude 后端请求。Dario 在可用时会自动重启以匹配 CC 的 TLS 指纹;无 Bun 时仍可在 Node.js 上正常运行,区别仅在于 TLS 指纹。 **在全新 Claude 账户上的首次设置:** 若 dario 是针对全新 Claude 账户运行的第一款工具,请先用几条真实的 Claude Code 命令预热账户: ``` claude --print "hello" claude --print "hello" ``` 这有助于建立会话基线。未经预热的新账户偶尔会在首次使用时出现计费分类问题。 **当 Anthropic 轮换 OAuth 配置时会发生什么?** dario 会自动从已安装的 Claude Code 二进制文件中检测 OAuth 配置。CC 发布新版本并轮换值时,dario 在下次运行时自动获取新值。缓存位置为 `~/.dario/cc-oauth-cache-v3.json`,以 CC 二进制指纹为键。若未安装 CC,则回退至硬编码的 CC 2.1.104 生产值。 **在 Claude 后端遇到速率限制怎么办?** Claude 订阅具有 5 小时与 7 天的滚动窗口。可通过 Claude Code 的 `/usage` 命令或 [状态栏](https://code.claude.com/docs/en/statusline) 检查用量。对于多智能体工作负载,建议添加更多账户并通过池模式分配负载:`dario accounts add `。 **多智能体工作负载出现重分类(overage),尽管 dario 按请求重放模板,为什么?** 重分类并非发生在单次请求层面。Anthropic 的分类器基于每个 OAuth 会话的累积统计(吞吐、对话深度、流式时长、到达间隔、思考块体积)。即使 dario 的 Claude 后端使每个请求都与 Claude Code 无法区分,长时间运行的智能体会话仍可能因累积信号而触发限制。根本解决方式是 **池模式**——将负载分散到多个订阅,使单个账号的累积信号不足以触发限制。参见 [多账户池模式](#multi-account-pool-mode)。 **能否通过 dario 路由非 OpenAI 提供方?** 可以——只要支持 OpenAI 聊天完成 API。例如: - `dario backend add groq --key=... --base-url=https://api.groq.com/openai/v1` - `dario backend add openrouter --key=... --base-url=https://openrouter.ai/api/v1` - 或指向本地 LiteLLM / vLLM / Ollama openai 兼容服务的 `--base-url=http://localhost:4000/v1` v3.6.0 一次仅支持一个活动的 OpenAI 兼容后端;按模型路由到多个后端将在后续版本中支持。 **仅使用 OpenAI 后端(无需 Claude 订阅)是否可行?** 可以。不运行 `dario login`,仅执行 `dario backend add openai --key=...` 和 `dario proxy`。Claude 后端请求将返回认证错误;OpenAI 兼容请求将正常工作。此时 dario 成为一个本地 OpenAI 兼容垫片,不涉及任何 Claude 功能。 **为何取名 “dario”?** 只是一个名字,并非缩写。不必深究。 ## 技术深度解析 关于 dario 的工作原理及设计缘由的更长篇幅文章: - [v3.0 模板重放——为何我们停止信号匹配](https://github.com/askalf/dario/discussions/14) - [Claude Code 默认值是检测信号而非优化项](https://github.com/askalf/dario/discussions/13) - [为何通过其他代理的 Opus 体验更差及修复方法](https://github.com/askalf/dario/discussions/9) - [计费标签算法与指纹分析](https://github.com/askalf/dario/discussions/8) - [速率限制头部分析](https://github.com/askalf/dario/discussions/1) ## 贡献 欢迎提交 PR。项目代码约 2,500 行 TypeScript,分布在 10 个文件中: | 文件 | 用途 | |---|---| | `src/proxy.ts` | HTTP 代理服务器、请求处理器、速率限制器、后端调度 | | `src/cc-template.ts` | CC 请求模板引擎、工具映射、编排与框架脱敏 | | `src/cc-template-data.json` | CC 请求模板数据(25 个工具、25KB 系统提示) | | `src/cc-oauth-detect.ts` | OAuth 配置自动检测(从已安装的 CC 二进制文件) | | `src/oauth.ts` | 单账号令牌存储、PKCE 流程、自动刷新 | | `src/accounts.ts` | 多账号凭证存储与独立的 OAuth 生命周期 | | `src/pool.ts` | 账号池、头耗感知路由、失败目标选择 | | `src/analytics.ts` | 滚动请求历史、每账号/每模型统计、耗费率 | | `src/openai-backend.ts` | OpenAI 兼容后端凭据存储与请求转发 | | `src/cli.ts` | CLI 入口,命令路由、Bun 自动重启 | | `src/index.ts` | 库导出 | ``` git clone https://github.com/askalf/dario cd dario npm install npm run dev # runs with tsx, no build step ``` ## 贡献者 | 谁 | 贡献 | |---|---| | [@GodsBoy](https://github.com/GodsBoy) | 代理认证、令牌脱敏、错误净化 | | [@belangertrading](https://github.com/belangertrading) | 计费分类调研、缓存指纹、计费重分类根因、OAuth 客户端 ID 发现、多智能体会话级计费分析 | | [@nathan-widjaja](https://github.com/nathan-widjaja) | README 定位与结构重写 | ## 许可证 MIT
标签:AI工具链, AI工程化, API路由, CI, Claude订阅, CodeQL, HTTP路由, LiteLLM, LLM路由, localhost, MITM代理, npm包, npm版本, OpenAI, OpenAI兼容端点, OpenRouter, 下载统计, 代理路由, 内存规避, 前端AI, 多提供商路由, 大语言模型路由, 安全评估工具, 工具无需变更, 服务端路由, 本地LLM路由, 本地开发, 本地推理, 端口3456, 端点聚合, 统一入口, 自动化攻击, 软件许可