证据快照复核于 2026-09-16GitHub 数据核对日期: 2026-08-21
证据已验证Plugin Bundle模型与路由Web Profile

dsh-router

一个 DSH Web Profile 插件:提供兼容 OpenAI 的本地模型路由网关和管理面板。

快速了解

它能做什么

一个 DSH Web Profile 插件:提供兼容 OpenAI 的本地模型路由网关和管理面板。

本站提供的是中文说明,不代表该项目或 Plugin 自身提供中文界面;语言支持请以上游文档为准。

使用场景
模型与路由模型路由配置UI
适配技术
deepseek-harnessopenai-compatible-api
兼容性

Web Profile
DSH 0.1.5-rc.1 or later

可信度与状态

证据已验证
核对日期 2026/9/16 UTC 13:55

有代码证据的贡献

它为 DSH 增加什么

路由设置面板

在“设置 > 路由”中提供供应商、账号池、回退组合、用量、端点设置与 API 密钥管理。

机制证据
兼容 OpenAI 的本地路由端点

通过 DSH Web 服务器提供 /v1/models 和 /v1/chat/completions,并将请求路由到已配置的供应商。

机制证据

选择前先看

dsh-router-core 作为 DeepSeek Harness 内部插件运行,不需要另起网关服务。安装并重启 DSH Web 后,它会增加“设置 > 路由”,同时提供本地兼容 OpenAI 的模型与对话端点。可在面板中配置供应商和账号、启用模型、创建回退组合、查看用量,以及管理端点 API Key。

适合谁

使用 DSH Web Profile,并希望通过一个本地端点管理多个已配置 AI 供应商、路由和回退策略的用户。

常见任务

  • 运行 `dsh plugin --profile web add dsh-router-core`,重启 `dsh web` 后在“设置 > 路由”完成配置。
  • 配置供应商和模型后,将兼容 OpenAI 的客户端指向 `http://localhost:3080/v1`。
  • 创建回退组合,让 DSH 中选择的模型可按策略路由到多个供应商模型。
  • 查看本地请求用量、最近请求、供应商账号和已启用模型。

权限与数据

该插件运行于 DSH Web Profile,提供本地路由 API,并持久化路由相关状态。

权限
  • 新增 DSH 设置区块和本地 `/router/api/*` 管理端点。
  • 通过 DSH Web 服务器提供本地兼容 OpenAI 的 `/v1/*` 端点。
  • 仅当单独安装并启用的路由扩展注册命令改写器时,才可能拦截 bash 工具调用。
数据处理
  • 将供应商凭证以不透明数据保存到 `<dataDir>/auths/credentials.sqlite`。
  • 在数据目录下保存 API Key、供应商配置和用量状态,包括用量 JSON 与密钥数据。
  • 用量记录可能包含请求次数、模型和供应商信息、Token 用量以及最近请求的耗时信息。
外部服务
  • 将请求路由到你配置的上游 AI 供应商。
  • 在你配置并使用相应功能时,可能调用供应商登录、API Key、模型列表、签到和对话能力。
凭据
  • 不同供应商可能需要账号或 API Key。
  • 端点 API Key 强制校验是可选的,默认关闭。

局限

  • 需要 DSH 0.1.5-rc.1 或更高版本、Node.js 20 或更高版本,以及 DSH Web Profile。
  • 该 bundle patch 仅支持 DSH Web Profile。
  • 本次整理未实际执行安装或运行测试。
  • README 声明该项目仅用于学习和技术研究,请勿用于商业用途。

DSHub 已核对

  • 固定提交的源代码包含已验证结构的 DSH bundle patch,包名为 `dsh-router-core`。
  • 包清单声明 Node.js >=20,并列出 DSH 相关 peer dependencies。
  • README 记录了 Web Profile 安装命令、DSH 版本要求、本地端点和路由界面。

DSHub 未核对

  • 未在 DSH 环境中测试安装成功或运行行为。
  • 已审计的源记录未证明已发布 npm tarball 的具体内容。
  • 未独立测试上游供应商行为、已存储凭证的安全性,或与特定客户端工具的兼容性。

固定版本安装

安装 dsh-router

这个Plugin Bundle没有 DSH Plugin 安装操作,请根据源码文档使用真实交付方式。

访问源码项目

维护者原文

项目 README

查看 commit a66b93f 对应的 README
维护者编写的上游内容原文于 2026/9/16README.md 获取,正文和仓库相对媒体固定到 commit a66b93f0fbbc,内容哈希为 713e3cd5239e。以下是未经 DSHub 翻译的上游原文,语言可能与当前页面不同;第三方托管的 badge 可能独立更新。
<h1 align="center">dsh-router</h1><p align="center">DeepSeek Harness 的 OpenAI 兼容路由插件</p><p align="center"> <a href="https://www.npmjs.com/package/dsh-router-core"><img src="https://img.shields.io/npm/v/dsh-router-core?style=flat-square&logo=npm&label=npm" alt="npm version"></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-10b981?style=flat-square" alt="MIT license"></a> <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本:0.1.5-rc.1+" src="https://img.shields.io/badge/DSH-0.1.5--rc.1%2B-4d6bfe" /></a> </p><p align="center"> <a href="#快速安装">快速安装</a> · <a href="#面板设置--路由">面板</a> · <a href="#api-端点openai-兼容3080v1">API 端点</a> · <a href="docs/suppliers.md">供应商开发</a> · <a href="docs/ext.md">扩展开发</a> </p>

插件版的 9router —— 不是另开一个网关服务,而是直接作为 DSH 插件嵌进 DSH web, 在 http://localhost:3080/v1 上原生暴露 OpenAI 兼容端点,把请求路由到内部供应商。 管理界面在设置 → 路由(官方设置页座位,不是自己开的页面)。装好即用, 不用多开一个 9router、不用维护第二个端口、不用在网关和 DSH 之间搬配置。

设置 → 路由 面板:概览(用量看板)、供应商、组合、端点与密钥

快速安装

需要 DSH 0.1.5-rc.1 及以上(支持 dsh plugin profile 插件机制)、Node.js >= 20,以及 web profile。

dsh plugin --profile web add dsh-router-core

然后重启 dsh web。打开设置面板,左侧导航「模型」下面会出现 路由

更多供应商:DSH 插件形态的供应商各自发 npm 包,同样 dsh plugin --profile web add <包名> 即可;供应商接入与开发见 docs/suppliers.md

本地开发版:不用 npm,直接 dependencies"dsh-router-core": "link:/path/to/dsh-router" 指向本地仓库。

它解决什么问题

能力 说明
零额外进程 就是 DSH 插件,随 dsh web 启停,天然同源(/router/api/* 无 CORS、面板嵌在设置里)。
扩展即插即拔 扩展插件(如 dsh-router-ext-rtk)经 router.ext 注册,在 bash 执行前改写命令(如加 rtk 前缀压缩输出)。面板「扩展」页一键开关,带自检。
供应商即插即拔 内置供应商随插件分发;更多供应商 = 装一个 DSH 插件(dsh-router-*)或放一个 js 文件到 ~/.dsh/profiles/web/suppliers/
模型不内置 供应商只实现差异化能力,模型拉取与缓存由核心统一管,不写死、不过时。
策略只写一次 组合回退、账号池(选号/冷却/禁用)、响应写入、凭证存储、积分持久化、模型管理都由核心提供。供应商 js 只对单个账号调一次上游并报告成败,不自己遍历账号、不维护冷却表、不落盘积分——否则每个插件都会长出一份互相不一致的实现,而核心也就无从判断「该不该换号」。
凭证单库 auths/credentials.sqlite,供应商凭证不透明 blob,核心统一生命周期,干净可备份。
组合即模型 建好的组合自动带出为 DSH 模型目录里的 router provider 选项,设置 → 模型直接选组合名即可。
用量可观测 面板概览看板:周期切换、汇总卡、趋势折线、Top 榜、最近请求。

面板布局、组合 fallback、连接池/账号池、API key 管理都贴近 9router,但按 DSH「一切皆插件」的方式 重组得更轻。

供应商开发与接入规范见 docs/suppliers.md (契约 / 加载顺序 / 模型统一策略 / 内置供应商参考实现)。

面板(设置 → 路由)

面板挂在 设置 → 路由(官方 settings.section 座位,排在「模型」下面):

  • 概览 — 用量看板(默认页):
    • 周期切换 今日 / 24 小时 / 7 天 / 30 天;
    • 汇总卡:总请求(含成功率)、输入 Tokens、输出 Tokens、缓存 Tokens、平均耗时(含首字节);
    • 签到卡:一键签到所有支持签到的供应商(按 checkinNow 能力筛),并显示 「今天点过没」;
    • Token 趋势折线图:鼠标悬停 / 触摸点选 / 键盘 (Home End 到两端,Esc 取消) 看每个时段;读数和峰值用 K/M 缩写,精确值在悬停提示里;
    • Top 榜:按供应商 / 按模型(请求数带失败计数);
    • 最近请求:时间 / 模型 / 供应商 / in↑ out↓ / 耗时,显示最近 10 条;
    • 清空 — 清掉全部用量统计(不影响供应商、账号、组合配置);
    • 数据落盘 data/usage.json(按天聚合 + 每天 24 个小时桶 + 最近 500 条明细 + 累计计数)。今日/7 天/30 天读天桶、24 小时读小时桶,都不受明细环容量限制; 明细环只服务「最近请求」列表。 小时桶从新数据开始累积,升级前那几天的天内分布查不到(明细环只剩 500 条 回溯不回去),那段历史的小时柱状图留空、24 小时口径按整桶计入 —— 不编数据。 token 口径:上游返回 usage 就用真值(分散在多帧时按字段取最大值合并); 上游不发时按 ~4 字符/token 估算,面板上标 ~失败请求不估算—— 它没到上游,编造输入 token 只会把总量灌水; 缓存口径:OpenAI 系 prompt_tokens 缓存,Claude 系不含(单报 cache_read_input_tokens),归一时统一折成「prompt 含缓存」, 所以「缓存 Tokens」是「输入 Tokens」的子集,不是并列的第三种; 签到口径:卡片上的「今日已点」= 今天在这个浏览器点过这个按钮(记在 localStorage),不代表上游一定签上了——真凭据是上游的 checked_in, 当前契约没有「查签到状态」的能力,要真状态得先给供应商契约加 checkinStatus?()(升级路径写进 CheckinCard.tsx 头注释)。
  • 供应商 — 供应商卡片(内置 / 插件分组),点击进入详情:
    • 链接池 — 账号列表(冷却/禁用/健康数/积分),支持删除;
    • 加链接 — 按供应商能力弹出不同流程:URL 登录(生成链接 → 浏览器登录 → 回调)、 API key 弹窗(填名字 + key)、轮询登录(登录后自动取凭证);
    • 签到 — 供应商实现了签到的才显示(如 codebuddy:每日 100 积分,连续第 7 天 1000)。核心遍历所有链接逐个签,汇总「N/M 成功 · X 今日已签」;上游「今日已 签到」按成功处理(幂等),账号额度或凭证失效会单独标出;
    • 刷新 — 刷所有链接的积分,并跑一次最简会话探测该供应商是否还有活着的链接 (走真实对话路径 + 账号池回退,能分清是账号额度没了还是供应商真挂了);
    • 可用模型 — 模型列表,逐个启用/禁用 + 自定义模型(通用能力,持久化到 data/supplier-config.json,/v1/models 与 chat 只接受启用的模型);单个模型可 「测试」,走真实对话路径并按账号池依次回退,所以能分清是这个账号额度没了还是 该模型真的不支持;
  • 组合 — fallback 链(免费优先),可自定义。组合即模型:建好的组合会自动带出 为 DSH 模型目录里的 router provider 选项(设置 → 模型直接选组合名即可用),请求 按组合策略命中其中一个供应商模型;
  • 端点与密钥 — 端点核心(无隧道/Tailscale):
    • API 端点 URL(http://localhost:3080/v1,可复制);
    • 鉴权设置 requireApiKey 开关;
    • API Keys 管理:创建 / 启用切换 / 显示 / 复制 / 删除(持久化到 data/keys.json)。

API 端点(OpenAI 兼容,:3080/v1)

# 模型列表
curl http://localhost:3080/v1/models

# 对话(流式/非流式)
curl -X POST http://localhost:3080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"glm-5.2","messages":[{"role":"user","content":"你好"}],"stream":false}'

任何支持 OpenAI 兼容 API 的工具(Claude Code、Cline、DSH 设置-模型 等)都可以把 baseURL 指向 http://localhost:3080/v1

鉴权:默认 requireApiKey=false,/v1/* 不要求鉴权(本地使用,与 9router 一致)。 在「端点与密钥」页开启「要求 API Key」后,请求必须带 Authorization: Bearer <库内启用的 Key>

面板 API(/router/api/*,同源)

端点 方法 说明
/health GET 供应商列表(含来源/能力)
/status GET 全部账号(含供应商 id)
/models GET 合并模型列表(已过滤禁用)
/combos GET 组合 fallback 链
/keys GET/POST 密钥列表(含完整 key)/ 创建 {name} → 返回明文一次
/keys/toggle POST {id, isActive}
/keys/delete POST {id}
/settings GET/PATCH {requireApiKey}
/ext GET/PATCH 扩展插件列表 + 开关 {id, enabled}(见下)
/stats GET 用量统计 ?period=today|24h|7d|30d(汇总 + Top 榜 + 最近请求 20 条)
/stats/chart GET 趋势图数据 ?period=…(today/24h = 24 小时桶,7d/30d = 天桶)
/stats/clear POST 清空全部用量统计
/suppliers/:id/login POST 生成登录链接
/suppliers/:id/login/callback POST {callbackUrl} → 加账号
/suppliers/:id/models GET 模型 + 启用状态
/suppliers/:id/models/toggle POST {id, enabled}

扩展插件(router.ext)

完整契约、注册方式、自检与降级约定见 docs/ext.md

面板「扩展」页列出所有扩展插件,每个一个开关。扩展插件是独立 npm 包 (如 dsh-router-ext-rtk), 经 cordis service router.ext 注册自己 —— 同 router.suppliers 的共享表模式, 与加载顺序无关。

分工:

  • dsh-router 核心:持有 router.ext 空表;在 tools/execute 拦截 bash 工具 调用,把命令委派给表里 enabled 且 ready 的扩展器改写;命中则短路。只拦 bash,其他工具(含 run_code 体内自起的子进程)不动。
  • 扩展插件:实现 rewrite(command)(同步、不能做 IO)+ 自管开关状态 (何时 enabled、是否 ready、怎么持久化)。核心不感知具体扩展器实现。

开关打开时会自检:扩展器 getState().ready === false 的(如没装 rtk)拒绝开启 (API 返回 409 + 问题描述),面板内容区红字显示原因。

已知坑

  • ctx.tools.get(name) 必须带 agent scope(exec.agent):bash 工具注册在 agent scope,不带 scope 只查全局视图会查不到,静默走原样执行、从不改写。
  • 改写在一次已被审批授权的工具调用内发生,不绕过 sandbox / 审批。

架构

浏览器(client 半)
  └─ 设置 → 路由(settings.section 座位, order 10, 排在「模型」下面)
       ├─ RouterSettingsSection  注册入口(settings-section.tsx)
       ├─ RouterView        tab: 概览 / 供应商 / 组合 / 端点与密钥(tab 条:下划线指示器)
            ├─ StatsTab          概览:用量看板(周期按钮组 + 汇总卡 + 折线趋势 + Top 榜 + 最近请求)
       ├─ SupplierDetail    供应商详情:链接池 + 加链接 + 可用模型
       ├─ EndpointTab       端点 URL + requireApiKey + 密钥管理
       └─ fetch /router/api/*            (同源,无 CORS)
            └─ host 半(src/index.ts)
                 ├─ /v1/models + /v1/chat/completions   (OpenAI 兼容, KeysStore 鉴权)
                 │    └─ RouterAdapter(src/llm/adapter.ts)  OpenAI SSE → DSH StreamChunk
                 │         (usage 经 toTokenUsage 转 DSH 契约,见 docs/suppliers.md)
                 ├─ KeysStore(src/keys.ts)              密钥库 + requireApiKey
                 └─ Router(路由器) → suppliers[]
                      ├─ OpenCodeSupplier(lib/suppliers/opencode.js) 无账号免费直连
                      ├─ OpenRouterSupplier(lib/suppliers/openrouter.js) API key 账号
                      └─ NvidiaSupplier(lib/suppliers/nvidia.js)       API key 账号
                      └─ 外部插件供应商(经 router.suppliers service 注册)
  • 供应商抽象:可插拔 js 模块只提供差异化能力(status/listModels/getAlias/chatOnce
    • 可选登录/签到/加 key);策略与通用能力(组合回退、账号池选号/冷却/禁用、 连接池排序、模型启用/自定义、别名、凭证、响应写入)由核心统一管。 chatOnce(uid, req) 一次只服务一个账号,返回成功/失败 + 语义状态,换号由核心决定。
  • 供应商加载(三来源,见 docs/suppliers.md):
    1. 内置:lib/suppliers/*.js(随插件分发,如 opencode)
    2. 用户:~/.dsh/profiles/web/suppliers/*.js
    3. 外部插件:其他 DSH 插件通过 cordis service router.suppliers (值为 { [supplierId]: (env) => SupplierModule })暴露供应商, dsh-router ctx.inject(['router.suppliers']) 延迟加载。
  • 模型统一策略:插件不内置、不缓存模型;listModels 每次从上游拉取, 缓存由核心按 60s TTL 统一管(/suppliers/:id/models),/v1/models 保持实时。
  • 凭证存储:SQLite 单库 {authDir}/credentials.sqlite(表 credentials(supplier, uid, data), 凭证为供应商不透明 JSON blob)。
  • /v1/* 鉴权:由 KeysStore.requireApiKey 控制。关闭 → 不鉴权; 开启 → Bearer 必须是「库内启用的 key」。

与 DSH 的边界

  • dsh-router 复用 DSH 的 Web Server 与设置面板座位,不启动第二个应用或代理系统。
  • 供应商 js 不改 DSH 的 prompt、工具 schema 或权限;它只负责「把上游协议翻译成 OpenAI 形态」,路由/回退/存储归核心。
  • 数据分两处:data/ 下的状态与用量 JSON(删了只是没统计了),以及 auths/credentials.sqlite(删了要重新登录所有供应商)。
  • 内置 patch 仅支持 DSH 的 web profile。

前提

  • 凭证由 dsh-router 核心统一管(SQLite 库 <dataDir>/auths/credentials.sqlite);
  • 供应商接入与开发见 docs/suppliers.md;
  • 重启 DSH 后 /v1/* 即生效;面板管理账号、模型与密钥。

开发

pnpm install
pnpm build        # lib/index.js(host) + lib/client.js / lib/client-registry.js(browser)
pnpm typecheck
pnpm test         # node --test "src/**/*.test.ts"

需要一个供应商最小实现作参考时,看 examples/suppliers/echo.js; 完整契约、加载顺序与模型策略见 docs/suppliers.md

致谢

感谢以下项目给的灵感:

许可证

MIT

免责声明

本项目仅用于学习与技术研究,请勿用于商业用途。

有意识地管理

安装与管理

前置条件与目标 Profile

目标 Web Profile

交付方式 Git Bundle — CARVIN94/dsh-router#a66b93f0fbbc1b5110d101549c934e5a357e16a6

验证、更新与移除

显示生命周期命令
验证
dsh plugin --profile web list

兼容性与访问范围

DSH web-profile plugin; Node.js >=20 DSH 0.1.5-rc.1 or later

检查兼容性证据

风险事实

api-authentication

API-key protection is off by default

证据
credential-storage

Supplier credentials are stored in a local SQLite database

证据
external-services

Configured suppliers may receive routed model requests and credentials

证据
证据与编辑审查Manifest、Bundle patch、分发与新鲜度

不可变证据

审查状态与源码活动

AI 已审查

若要让本地 `/v1/*` 端点被其他人或其他设备使用,请先开启“要求 API Key”;同时应审查所配置的供应商,因为路由请求会发送到这些服务。

AI 审查于 2026/9/16 UTC 13:56GitHub 事实核对日期: 2026/9/16 UTC 13:56

自当前证据基线以来,没有记录到重要源码变化。

下一步

按 Plugin 安装流程操作

订阅重要变化: dsh-router