dsh-openrouter-providers
Route OpenRouter requests through a configured provider list and quantization cap, injected as provider.only/order with allow_fallbacks, plus provider.quantizations.
Install
dsh plugin --profile web add dsh-openrouter-providers
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-openrouter-providers
中文 | [English](README.en.md)
DeepSeek Harness 插件:从 OpenRouter 官方目录勾选请求允许使用的提供商,或按模型规则分别限定,并可设置量化位数限制与服务层级(service_tier),把它们作为 provider.only / provider.order / provider.quantizations 路由参数(以及顶层 service_tier)注入到所有 OpenRouter 模型请求中(含图片的多模态请求原样透传)。可选地把这些请求改经 billion-context 的压缩代理发出。配置由插件自持,写入 $DSH_HOME/openrouter-providers.json(未设置 DSH_HOME 时为 ~/.dsh/openrouter-providers.json),重启后自动恢复。
适配版本:DeepSeek Harness 0.1.5-rc.1 ~ 0.2.1-rc.3(engines.dsh: >=0.1.5-rc.1 <0.3.0)。本插件不 import 任何 @deepseek-ai/dsh-* 包,唯一 peer 是 @deepseek-ai/cordis,因此不受 0.1.7 / 0.2.x 破坏性改动影响;跨 0.2 主版本已在真实 0.2.0-rc.2、0.2.1-alpha.1、0.2.1-alpha.2、0.2.1-alpha.4、0.2.1-rc.2 与 0.2.1-rc.3 上逐项复验(配置读写往返、llm/stream 重路由、真实 OpenRouter 路由、billion-context 代理接入、插件页显示名与图标、设置页表单渲染、adapter 契约、服务层级注入)。注意:DSH 自 0.2.1-alpha.3 起把 engines.dsh 当作真实门禁(优先于 peerDependencies,不匹配会直接拒绝加载),因此升级到 0.3.x 时需先放宽本行上界。
为什么不再用 settings 服务:DSH0.1.7删除了 settings 命名空间注册(settings.register/SettingsScope/watch),改为只枚举 profile 条目 Config 上的.volatile()字段。依赖旧 API 的插件在 0.1.7 上会静默失效——apply提前返回,HTTP 路由与llm/stream重路由都不再注册,设置页显示「无法读取当前状态(Host 端不可用)」,且请求注入完全不生效。本插件改为自持配置文档,并只把旧命名空间当作能力探测的可选增强(见下),因此在新旧宿主上行为一致。
配置入口(双栈):DSH 0.1.6-alpha.2 把插件配置从设置搬到新的侧栏「插件」页,并退役了 settings.plugin.item。本插件同时注册两个 slot,由宿主声明决定哪个生效(未声明的那个永不触发,不会报错):
宿主 · slot · 位置
DSH ≥ 0.1.6-alpha.2 · plugins.bundle.config(键=包名) · 侧栏插件 → 本组合包页面内的配置表单
DSH < 0.1.6-alpha.2 · settings.plugin.item · 设置 → 插件 → 插件配置 内的折叠卡片
旧宿主上,那半卡片按 Host 已服务的 settings 命名空间派发,所以本插件会探测 settings.register 是否存在,存在才注册一个空的 pass-through 命名空间(只为让卡片能被派发,不承载任何取值);0.1.7 起该 API 不存在,跳过即可,不影响其余功能。
功能
- 勾选式提供商选择器:Host 半拉取 OpenRouter 官方目录(
https://openrouter.ai/api/v1/providers,24 小时缓存),表单渲染可搜索的复选框列表,同时保留手填自定义 slug 的入口。选中项即使不在目录里也始终显示,因此离线快照缺某家也不会把已有选择丢掉。目录拉取失败时回退到内置快照,并在表单下方明确标注「离线或未刷新」,60 秒后重试(而不是等满 24 小时)。 - 配置表单:选择路由模式与量化位数限制:
- 仅允许这些提供商 → 请求体注入
provider: { only: [...], allow_fallbacks: false } - 按顺序优先尝试 → 注入
provider: { order: [...], allow_fallbacks: true } - 量化位数限制 → 注入
provider: { quantizations: ['int4' | 'int8' | ...] }(可选,默认不限制;合法值见 OpenRouter Quantization) - 可整体开关;保存后写入插件自持的配置文件(
$DSH_HOME/openrouter-providers.json)。新「插件」页只有保存会写入,离开页面丢弃暂存修改;旧折叠卡片另提供「撤销」按钮与「未保存」徽标。 - 按模型规则(可选):配置文件里的
modelRules数组,让不同模型走不同的提供商限制——例如给xiaomi/mimo钉死makora/xiaomi,同时让其它模型不受限。规则自上而下、第一条命中生效;未命中的模型沿用全局配置。pattern是大小写不敏感的 glob(含时按通配匹配),不含*时按命名空间前缀匹配(xiaomi即覆盖xiaomi/mimo-v2.6-flash)。mode取inherit(跟随全局)/only/order/off(该模型跳过注入)。规则里providers留空则继承全局列表。判定发生在buildBody()与llm/stream重路由闸门两处,都按本次请求自己的模型解析,因此解析后没有任何限制的模型不会被强行塞进本插件的 adapter。 - 界面跟随 DSH 语言:文案来自插件注册的
openrouter-providerslocale 命名空间(zh/en双语词典),切换语言后界面即时重渲染,无需刷新页面;宿主没有 locale 服务时回退中文文案。 - 「插件」页显示名称与图标:包内
locale/zh.json与locale/en.json的meta.title/meta.description提供本地化显示名(中文「OpenRouter 提供商列表」/ 英文OpenRouter Providers),因此插件列表里显示的是可读名称而非裸包名dsh-openrouter-providers;package.json的icon: "./icon.svg"提供卡片与行内图标(36×36 三层渐隐圆角条,示意「按列表逐级收窄提供商」)。两者都跟随 DSH 界面语言。注意exports必须包含"./locale/.json": "./locale/.json",否则 Node 的 exports 解析会抛ERR_PACKAGE_PATH_NOT_EXPORTED,显示名静默回退为包名;icon必须是相对路径、扩展名限.svg/.png/.jpg/.jpeg/.webp、须位于包目录内且 ≤256 KiB,写错会报错(但只丢图标,名称仍生效)。 - 路由识别不看名字:profile 里的 provider 可以随意重命名(例如叫
aaaa),只要它的baseURL主机是openrouter.ai(含子域),或apiKeyEnv是OPENROUTER_API_KEY,就算作 OpenRouter 路由——识别结果 30 秒缓存,改名无需重启。内置的openrouter永远算在内,也可以在配置文件的routes数组里手填额外路由名。判定刻意锚定 URL 的主机而不是子串匹配:/openrouter\.ai/也会命中无关域名里的路径片段。 - 图片输入:多模态请求里的图片会转成 OpenRouter 的
image_url部分(data:URL)发出,不再一律拒绝。图片字节来自attachments服务给出的宿主路径;已从上下文移出(offloaded)的图片降级为文字占位符,不会重发已不属于历史的字节。请求级图片预算沿用宿主的IMAGE_OFFLOAD_REQUIRED契约——超限时由compaction-image-offload把最旧的图片移出上下文后重试,用户看不到失败——并且按 provider 实际配置的maxRequestImageBytes执行,不再写死 20 MiB。 - 服务层级(可选):注入顶层
service_tier,取default/flex/priority/ultrafast(OpenRouter Service Tiers)。两个容易混淆的地方:「不注入」和default不是一回事——不注入时交给 workspace 默认,且:nitro/:floor变体仍可能把层级端点拉进候选池;注入default才明确钉住标准层并关掉这条通路。ultrafast需要足够的max_tokens,否则会退化成priority。不提供fast,它是priority的同义词。表单下方会显示上一次请求实际由哪个层级与提供商服务(响应里的service_tier),因为 OpenRouter 对无法满足的层级是静默回落的——不显示的话设了也看不出有没有生效。 - 请求注入:监听
llm/streamwaterfall——当请求的 provider 路由被认定为 OpenRouter(已启用且列表非空、或设置了量化限制、或指定了服务层级、或开启了代理)时,把请求重路由到插件自研的 chat-completions adapter,由它构造请求体注入provider字段;reasoning.effort(off/low/medium/high/max,均为 OpenRouter 合法值)按契约透传。会话日志与 UI 仍显示原来的路由名。 - billion-context 压缩代理(可选):把代理开关设为自动后,插件会探测本机运行中的 billion-context 代理,命中则把请求改经它的
/bili/入口发出(<origin>/bili/https://openrouter.ai/api/v1/chat/completions),从而获得其上下文压缩;探测不到代理时直连,不会因为装了本插件而让生成失败。代理开关与「提供商限制」总开关互相独立:只想压缩、不想限制路由时,关掉提供商限制、单独开启代理即可。 - 凭据:复用现有
OPENROUTER_API_KEY——优先通过credentials服务解析(与llm-pi-ai的apiKeyEnv一致),读不到时回退到启动dsh web的 shell 里的同名环境变量,因此不必在界面里再填一次。 - 应用归属(App Attribution):请求携带
HTTP-Referer: https://github.com/deepseek-ai/deepseek-harness、X-OpenRouter-Title: DeepSeek Harness OpenRouter与X-OpenRouter-Categories: cli-agent头,使 OpenRouter 界面/排行榜中显示为DeepSeek Harness OpenRouter而非 Unknown(OpenRouter App Attribution 文档)。
安装(bundle 挂载)
插件以 bundle 包形式挂载,与其他插件(dshmarket、dsh-recall-plugin 等)一致,通过 cordis.patch.yml 的 insert 行自动合并进 profile composition。
方式 A:从 npm 安装(推荐)
在 profile 目录(如 ~/.dsh/profiles/web/)执行:
pnpm add dsh-openrouter-providers@latest
然后把包加入 profile 的 package.json 的 dsh.profile.bundles 列表:
`
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::25,最后更新 2026-10-29