dsh-router-qoder
dsh-router 的 Qoder 供应商插件,同时覆盖国内版与国际版。以个人访问令牌认证、对 Qoder 的 cosy 网关签名请求,并把上游 SSE 转成 OpenAI SSE;模型列表同时上报上游显示名与 key,选号与冷却仍由 dsh-router 核心处理。
安装
dsh plugin --profile web add dsh-router-qoder
沙箱测试
这个插件还没测过。提交测试 →
README
<h1 align="center">dsh-router-qoder</h1>
<p align="center">dsh-router 的 Qoder 族供应商插件(国内版 + 国际版)</p>
<p align="center">
<a href="https://www.npmjs.com/package/dsh-router-qoder"><img src="https://img.shields.io/npm/v/dsh-router-qoder?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.2.0+" src="https://img.shields.io/badge/DSH-0.2.0%2B-4d6bfe" /></a>
</p>
<p align="center">
<a href="#快速安装">快速安装</a> ·
<a href="#两个供应商">两个供应商</a> ·
<a href="#取-pat">取 PAT</a> ·
<a href="#能力">能力</a> ·
<a href="https://github.com/CARVIN94/dsh-router#readme">dsh-router 核心</a>
</p>
为 dsh-router 提供 Qoder(阿里 AI 编码平台)的
两个供应商(PAT 认证,cosy 签名网关)。单独装它没用——它只是向核心注册供应商,
面板、账号池、组合回退、模型管理都在核心里。
两个供应商
供应商 id · 面板名 · 网关 · openapi · uid 前缀
qoder · Qoder · gateway.qoder.com.cn · openapi.qoder.com.cn · qd
qoder-global · Qoder Global · api1.qoder.sh · openapi.qoder.sh · qdg
两个区域同协议同契约(cosy 签名、jobToken 交换、同一套 chat/models 端点),
所以共用同一份实现(src/core.ts),差异只在 src/cn.ts / src/global.ts 的
profile 与 QODER_REGIONS 的主机表。
两个 id 同时是凭证与配置的存储键(credentials.sqlite 的 supplier 列、
supplier-config.json 的键)——改 id = 已添加的账号全部消失。
src/ core.ts 共享实现 —— 供应商契约、账号/积分缓存、chatOnce、签到、addApiKey cosy.ts cosy 协议原语 —— 自定义 base64、请求签名、RSA/AES 会话、设备指纹 messages.ts OpenAI 请求 → Qoder 请求体(模板 + 消息/工具转换) upstream.ts Qoder HTTP 客户端 —— jobToken 交换、模型目录、SSE 聊天、用量、活动/领取 sse.ts Qoder SSE → OpenAI SSE(核心只接受 OpenAI 格式的字节) cn.ts qoder profile(区域、图标、uid 前缀、弹窗提示文案) global.ts qoder-global profile icon.ts 内联 SVG data URI(面板图标不依赖另一个服务活着) index.ts 插件入口(host 半,一次注册两个供应商) contract.ts 供应商契约(自含,与 dsh-router 契约同步,含 addApiKey/apiKeyHint) types.ts 通用类型 cordis.patch.yml bundle patch,把插件插入 DSH cordis bundle stack
与 CodeBuddy 族的两处不同
1. 认证是 PAT,不是 OAuth。 粘贴一个 pt-… 就完事,没有浏览器登录、没有回调、
没有 refresh token。所以本插件实现的是契约里的 addApiKey 那条路,不是
generateLoginUrl/completeLogin。添加时会真的交换一次 jobToken 校验——
打错一个字符的 PAT 不会存进去。
2. 上游不是 OpenAI 兼容端点。 Qoder 官方没有 OpenAI 兼容接口,chat 直连它的
agent_chat_generation:请求体是私有模板 + cosy 编码加密,响应是「信封套一层
OpenAI 形状」的 SSE。sse.ts 把这层拆开重新包成 OpenAI SSE 交给核心。
快速安装
需要 DSH 0.2.0 及以上。先装核心,再装本插件,然后重启 dsh web:
dsh plugin --profile web add dsh-router-core dsh plugin --profile web add dsh-router-qoder
dsh plugin add 会在 profile 里 pnpm add,并自动把声明了 dsh.bundle.patch
的包加入 dsh.profile.bundles(本插件即声明了,即 cordis.patch.yml)。
本地开发版:不用 npm,直接 dependencies 加
"dsh-router-qoder": "link:/path/to/dsh-router-qoder" 指向本地仓库
(本机 profile 就是这么装的,改完pnpm build再重启dsh web即生效)。
重启后本插件以 cordis service router.suppliers 向 dsh-router 注册两个供应商,
面板「供应商」出现 Qoder 与 Qoder Global 两张卡片。
能力
能力 · 说明
添加账号(PAT) · 弹窗粘贴 pt-…。先交换 jobToken 校验,成功才落盘,昵称取上游下发的账号名;同一 PAT 不会重复建号。粘贴时带 Bearer 前缀也能识别(会被剥掉)。
模型列表 · 「获取模型」从 GET /algo/api/v2/model/list 实时拉取。面板显示上游的 display_name、请求仍用上游 key(对照表见[使用](#使用))。上游的 auto 不列出来:它是该区的默认路由(请求时才决定解析成哪个模型),不是可描述的模型。没有 PAT 时列表为空——这是正确状态,不是故障。
对话 · 直连 cosy 网关:请求体走 Qoder 私有模板(chat_context/model_config/business/session_id),body 经自定义 base64 加密后参与签名;响应 SSE 转成 OpenAI SSE(含 reasoning_content、tool_calls、usage、[DONE])。usage 里的 prompt_tokens_details.cached_tokens 原样透传,宿主的缓存命中率因此是真实读数。
图文输入 · 请求里出现 image_url / input_image 时把 model_config.is_vl 置真,否则置假——图片能力按这次请求决定,不靠一张静态能力表。
思考强度 · 核心给的推理等级按上游约定的两处同时写(顶层 reasoningEffort + parameters.reasoning_effort)——官方客户端如此,只写一个可能被某个区域忽略。auto/空/none/off 一律不下发,用模型自己的默认档。
积分显示 · 面板账号积分 = sash/api/v2/me/usage 的剩余量(基础包 userQuota + 加量包 addOnQuota + 企业包 orgResourcePackage 的 remaining 求和),内存缓存 10 分钟。读不到报 -1(不是 0),核心据此保留上次持久化的值。
每日签到 · 走活动接口(/sash/api/v1/me/campaigns → …/{id}/claim),路径里没有「签到」二字。CLAIMED 与 409 都算「今日已领」(幂等,不是失败);上游今日没下发可领活动时如实说明。
多账号池 · 核心按池顺序/策略选号回退,本插件只报单个账号的成败与语义状态。
取 PAT
本插件只认 PAT(Personal Access Token,pt- 开头)。两个区域各签发一份、互不通用:
用哪个卡片 · 控制台 · 入口
Qoder(国内版) · qoder.cn(同 qoder.com.cn) · 设置 → 个人访问令牌(旧页面/旧文档写作「API 令牌」)→ 创建令牌
Qoder Global(国际版) · qoder.com · Settings → Personal Access Tokens → Create token
创建时填名称(只是给你自己看的备注),有效期按需选;完整令牌只在创建那一刻显示一次,
当场复制。漏了就只能删掉重建。
官方原文(令牌格式与作用域说明):
三件容易踩的事:
- 国际版的控制台不是
qoder.sh。那只是网关与开放 API 的主机名(api1.qoder.sh/
openapi.qoder.sh),没有网页控制台,域名本身也不解析。发 PAT 的是 qoder.com。
- 区域对不上一定被拒:国内版的
pt-…贴进国际版卡片(或反之)交换 jobToken 就失败,
这不是插件坏了、也不是令牌过期。
- 别把令牌提交进仓库或贴进 issue:它等价于你的账号权限,谁拿到都能以你的身份调接口。
使用
1. 重启 dsh web
2. 面板 → 供应商 → Qoder / Qoder Global 卡片 → 添加 API key → 粘贴 PAT
(从哪个入口拿见上一节)
3. 点「获取模型」从上游拉目录,勾选要用的模型
4. 请求模型可写 qmodel_38max,或带别名前缀 qoder/qmodel_38max(插件自动剥前缀)
模型名:显示用名字,请求用 key。 上游的 key 是内部标识(qmodel_38max、
kmodel_latest),人读的是它同时下发的display_name(Qwen3.8-Max、
Kimi-K3.1-Pro)。插件把两者都报给核心:**面板、搜索、组合挑选显示可读名,
组合里存的与请求里发的仍是 key**——拿显示名去请求上游只会 404。
面板每行的 key 以小号淡字跟在名字后面,hover 也有完整说明。
2026-10-28 国内版实测快照(会随上游变,以面板为准):
面板显示 · 上游 key(请求/组合用) · 上下文 · 倍率
Qwen3.8-Max · qmodel_38max · 180K · 0.5×
Qwen3.8-Flash · qfmodel · 180K · 免费
DeepSeek-V4-Pro · dmodel · 96K · 0.5×
DeepSeek-Flash · dfmodel · 180K · 免费
GLM-5.3 · gmodel · 180K · 0.8×
GLM-5.3-Flash · gfmodel · 1000K · 0.1×
Kimi-K3.1-Pro · kmodel_latest · 180K · 1×
Kimi-K2.8-Preview · kmodel · 180K · 0.8×
MiniMax-M3.1-Flash · mmodel
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:3,最后更新 2026-10-28