dsh-provider-hub
English | 中文
为 DSH 扩大可用的服务商:在官方 Models 页选一个服务商,粘贴 API Key,保存——预设与 DSH 自带的 42 家并列在同一个下拉里,插件把官方 llm-pi-ai 路由与凭据一次性写好,立即生效、无需重启、无需手改 settings.yaml。
内置 58 家服务商预设 / 2908 个模型(其中 2494 个来自 models.dev 补充目录,见「目录维护」)(OpenAI 兼容 / Anthropic Messages / OpenAI Responses 三种协议),覆盖国际与国内的普通 API 与 订阅渠道(百炼 Token Plan、智谱 Coding、Kimi Coding、MiniMax Coding Plan、小米 MiMo、OpenCode Zen、火山方舟 Agent Plan 等);DSH 已内置的服务商不会重复出现在下拉里。
安装
# 通过插件管理器(推荐)
dsh plugin --profile web add dsh-provider-hub
# 或本地开发挂载
dsh plugin --profile web add link:/path/to/dsh-provider-hub
重启 dsh web,打开 设置 → Models。
使用
Models 页页脚有一条 「从预设目录添加(N)」,展开就是还没添加的预设:
- 点 展开 → 找到要的渠道 → 点 添加
- 弹出一个 Key 输入框(若该 Key 已在环境变量或凭据服务里,不会问,直接添加)
- 粘 Key → 确定
添加完它就是一个普通的提供商卡片:模型清单、上下文/输出限额、思考档、逐模型兼容开关都由预设写入,之后你可以在卡片里随便改、删、加,插件不会再把它们改回去。已保存的 Key 会留在凭据服务里,删掉再加时不用重填。
为什么不走官方那个下拉
官方 添加模型提供商 → 第三方模型提供商 的下拉里也能看到这些预设(插件把它们声明成了 configurable providers),但只有 pi-ai 自带目录里有的提供商能走通那条路:
- 目录条目(
registerConfigurableProviders)按 DSH 的契约不携带模型清单——运行时只读provider / displayName / settingsNs / settingsPath / defaultBaseURL / baseURLEnv / nativeAuth; - 于是选中后建出来的路由是「有地址、没模型」;
- pi-ai 对没有模型、且自己也不认识的路由会直接抛
PiAiCatalogError(resolves no models),保存不落地; - 插件的「补模型」逻辑(
enrich)只处理已经配置成功的路由,所以永远轮不到它。
对 DSH 自带的提供商不存在这个问题(pi-ai 目录兜底给模型)。页脚那个入口就是为「pi-ai 不认识的提供商」准备的——它由插件自己写完整档案,绕开这一步校验。
如果你确实想走官方下拉:选中后 pi-ai 会报错,因为目录条目给不了模型。手动在「模型目录」里加一条模型 ID 也能过,但那样只会得到你手填的那一条。
行内
Hub徽标:来自本插件预设的路由,在官方 Models 页各自的服务商行内会带一个Hub标记(注入官方settings.models.provider-card逐行插槽)。官方那个「自定义」标签表达的是「这条路由不在 pi-ai 原生目录里」,与本插件没有对应关系,所以没有改它。判定方式是指纹而非标记——DSH 不记录路由来源,因此要求:路由 ID 属于本目录的预设,且该路由的显示名等于预设名(官方编辑器会从本插件声明的目录条目预填这个显示名;只给原生路由填 Key 的情况保留路由 ID 作显示名,不会被误标)。代价:① 手动改过显示名的路由不再带标;② 若某预设日后从目录下线,其既有路由也不再带标,需自行核对
cordis.patch.yml。
隐藏 / 显示提供商(不丢 Key、不丢配置)
额度用完了、或者只是暂时不想看见,就隐藏它:路由会从聊天输入框的模型选择器里消失,Models 页的那张卡片也一起消失,但 Key 与全部配置都留着——随时点一下就能原样恢复,不用重填任何东西。
- 隐藏:Models 页每条 pi-ai 服务商行内(
Hub徽标旁边)的「隐藏」。确认后插件把该路由整份 profile 存进~/.provider-hub/hidden.json,再把它从用户层撤下。凭据服务里的 Key 完全没动。 - 恢复:页脚那行「已隐藏 N 个提供商(点名字恢复)」,点名字即原样写回(含
apiKeyEnv/baseURL/api/models/compat/headers)。 - 隐藏后的预设还会以「休眠」状态回到 添加模型提供商 → 第三方模型提供商 的下拉里,这是第二条恢复路径(走官方编辑器)。
原理:模型选择器的数据源是 llm.listProviders() —— 只有用户层带着 profile 的路由才会注册,所以撤下 profile 就等于同时离开选择器与设置页,而 Key 引用不需要跟着走。
两种「隐藏」的杠杆
插件按提供商目录里该路由的 settingsPath 自动选杠杆,所以卡片上的文案会告诉你这次会隐藏到什么程度:
| 路由类型 | 杠杆 | 效果 | 例子 |
|---|---|---|---|
profile(settingsPath = ['providers', <route>]) |
撤下该 profile | 卡片 + 选择器一起消失;恢复时原样写回 | opencode、opencode-go、Command Code、ClinePass、Cline Free、千帆… |
catalog(settingsPath = []) |
清空该路由的 models,并在页面上把该行藏起来 |
卡片与选择器都消失;恢复时把原目录写回 | DeepSeek(deepseek-official) |
catalog 模式为什么多一步:这类路由由它自己的官方插件在 apply 时无条件注册适配器与目录条目(ctx.llm.registerAdapter([provider], adapter)),配置层面注销不掉,所以插件做两件事——① 清空 models 让选择器那个分组因「零模型」被过滤;② 在自己的行内槽位里用 closest('li') 把整张卡隐藏(该 <li> 以 provider 为 key,节点稳定)。这是页面级隐藏,不是注销:配置仍在用户层,点页脚「显示」即原样写回并恢复整行。
catalog 模式恢复时:你原本改过模型目录就写回原目录;没改过就 unset,让它回到命名空间自带的默认目录。
想让 DeepSeek 那张卡真正从配置层消失(连路由都不注册)只有一条路:在 profile 组合里
disabled: true掉llm-deepseek这个条目(它对应包@deepseek-ai/dsh-llm-deepseek-api-key)。本插件不替你做这种跨插件的开关决定;DeepSeek 账号(llm-deepseek-account)是另一个条目,不受影响,Key 也留在凭据服务里。
DeepSeek 账号(
deepseek-account)不在支持范围:它的模型清单由账号联网/models拉取,插件明确拒绝models键("models is no longer configurable; the account /models listing supplies the catalog"),配置层面没有可清空的目录。真要它别出现在选择器里,官方做法是退出登录。
自定义服务商
本插件不再自带自定义入口——DSH 官方就有:同一个「添加模型提供商」卡片里,方式选 自定义模型 API 即可接入任何 OpenAI / Anthropic 兼容端点(填 Provider ID、API 地址、协议、模型,还能点「获取可用模型」直接探测端点)。
工作原理
预设通过 官方可配置服务商目录 进入 DSH,写入则全部走官方服务,插件不直接碰配置文件:
llm.registerConfigurableProviders(entries)—— 把预设声明成「休眠提供商」,于是它们出现在官方那个提供商下拉里(DSH 自带的那 42 家由dsh-llm-pi-ai用同一个接口声明);已被别人声明的路由不会被重复声明,同一家厂商换了个路由 ID 的也不重复(预设gemini→ 原生google、opencode-zen→ 原生opencode,按目录里的别名折叠)settings.mutate('llm-pi-ai', [set providers.<route>], revision)—— 你保存之后,把预设的模型清单 / 协议 /compat/headers(例如 OpenCode Go 必需的x-opencode-session)补进该路由的 profile,官方 schema 校验、适配器热注册credentials.set(apiKeyEnv, key)—— Key 由官方编辑器写进凭据服务(与手写 profile 用的是同一个引用)
两条边界值得知道:
- 目录条目带不了模型:DSH 的目录条目只有
provider / displayName / settingsNs / settingsPath / defaultBaseURL / baseURLEnv / nativeAuth,没有models,所以策展必须发生在「保存之后」这一步,而不是目录里。 - 策展只做一次:每路由记一份指纹在
~/.provider-hub/directory.json,此后你对手上这条 profile 的任何编辑(比如裁短模型清单)都不会被插件改回去;预设自身形状变了才会重新策展。
core/ 目录是纯 JS(无 Node 内建、无 DSH 依赖、无 I/O):服务商目录、profile 构建与校验、目录计划。宿主半、浏览器半(本插件)、以及后续的桌面端外壳共用同一份核心代码。
预设清单
OpenAI、OpenRouter、Anthropic、Google Gemini、xAI Grok、Mistral、Groq、Together、Fireworks、DeepInfra、Novita、Cerebras、NVIDIA NIM、Baseten、HuggingFace Router、Vercel AI Gateway、OpenCode Zen / Zen Go、硅基流动、月之暗面 Kimi(国内/国际)、Kimi Coding Plan、智谱 GLM(国内)、智谱 Coding Plan、Z.ai GLM、MiniMax Coding Plan(国际/国内)、MiniMax(国内)、阿里云百炼 Token Plan(国内/国际)、阿里云百炼 Qwen、百度千帆、腾讯混元、火山方舟(豆包)、小米 MiMo、Ant Ling、LongCat(美团)、StepFun Step Plan(国内/国际)、火山方舟 Agent Plan、ClinePass、Command Code、Kilo Gateway、Nous Portal、Cline Free、AIHubMix、Requesty、Kenari、ZenMux、Poe、302.AI、七牛云 AI、腾讯云 Coding Plan、ClinePass、DeepSeek、小米 MiMo Token Plan(国内/新加坡/美国)、APIGOTO 聚合路由。
火山方舟 Agent Plan 预设写入 https://ark.cn-beijing.volces.com/api/plan/v3(不是 /api/v3——后者按量计费),协议走 Responses API(对应 OpenCode 的 @ai-sdk/openai;要更旧的 Chat API 就把协议改成 OpenAI 兼容)。收录 ark-code-latest 与 deepseek-v4.1-flash / glm-5.3 / kimi-k3 / deepseek-v4-pro / deepseek-v4-flash / kimi-k2.8-preview,后六者均标注 1M 上下文窗口。
免费渠道(Step 5 Preview 限免那几家):
- Kilo Gateway:
stepfun/step-5-preview-free(1M 上下文 / 64K 输出,思考档 low/medium/high,走 OpenRouter 式reasoning: {effort}线格式,因为 Step 5 在该端点禁止关闭思考,预设不提供 off 档)。网关对免费模型允许匿名调用(每 IP 200 次/小时),但 pi-ai 适配器没有凭据就不发请求,所以仍需到 app.kilo.ai → 个人资料底部复制免费 Key。 - Nous Portal:
stepfun/step-5-preview:free、stepfun/step-3.7-flash:free等 8 个免费模型,端点inference-api.nousresearch.com/v1,Key 从 portal.nousresearch.com 免费领取(无 Key 返回 x402/402)。 - OpenCode:免费层级拿不到——
/zen/v1的*-free模型报 FreeTierError「只能在 OpenCode 应用内使用」,/zen/go/v1网关则要求 $10/月的 Go 订阅(step-5-preview-free/longcat-2.5-preview-free是 Go 内无限免费,而非无订阅可用)。已实测:Go 网关还会拒绝没有x-opencode-session头的请求,而 pi-ai 适配器不发这个头——opencode-go预设已通过 profile 级headers自动注入,订阅用户直接启用即可。 - Cline Free:
cline-free/*的 Step 5 只对 Cline 产品面开放(API 调用返回 403),拿不到;但:free系列(Poolside / NVIDIA / Cohere / Gemma / DOTS…)走 API 可用,且不计入 ClinePass 周额度,复用已有的CLINE_API_KEY即可启用。 - Puter:未收录——其 OpenAI 兼容端点
/puterai/openai/v1/*对免费账户返回402 subscription_required,只有 puter.js 的 User-Pays 通道免费,DSH 用不上。 - AIHubMix / Requesty / Kenari:这三家是冲着免费额度收的,不是冲着规模——它们转售的模型本目录基本已经能拿到(按
canonical_model_id归并后,三家分别只带来 4 / 18 / 3 个新模型),价值在于各自的零成本条目:AIHubMix 16 个、Requesty 12 个、Kenari 10 个。其中 AIHubMix 的端点得手工钉住(https://aihubmix.com/v1)——models.dev 对它的api字段是 undefined(它走自家 AI SDK 包),模型清单仍由tools/sync-modelsdev.mjs生成。 - 没收的云:Azure / Bedrock / Vertex / SAP AI Core 这类大厂云在 models.dev 里
api同样是 undefined(走各自 SDK 的签名与资源名认证),本插件的 profile 只能表达「baseURL + 一个凭据引用 + 三种协议之一」,适配器也只发x-api-key/Bearer,写进去是坏的;neon的端点则是模板变量${NEON_AI_GATEWAY_BASE_URL}/v1,每个项目不同、钉不住。这些一律不收。
关于内置:DSH 自带 DeepSeek 官方适配器(llm-deepseek),其目录里的 stepfun 指向普通付费端点 api.stepfun.com/v1——Step Plan 订阅端点(step_plan/v1)没有内置条目,因此本插件提供该预设;其余与本插件重合的服务商由 DSH 原生目录覆盖的那些默认折叠在「显示 DSH 已内置」开关后。已配置过的 Key(包括来自环境变量的)会被识别,留空输入框即可直接启用。
WorkBuddy(腾讯)适配
同一份预设目录也能写入 WorkBuddy 的本地自定义模型文件(~/.workbuddy/models.json,明文 JSON,应用启动时读取)。
默认流程与应用官方面板对齐:工具只写「定义」(接口地址 / 模型清单 / 上下文与输出限额 / 图片、推理、工具调用开关 / 思考档位),不写 Key——WorkBuddy 官方的「设置 → 模型 → 模型管理」面板本来就能编辑这同一些字段(含 API Key),Key 由你在应用里填:
node tools/workbuddy.mjs list # 查看预设与 WorkBuddy 里的已装状态
node tools/workbuddy.mjs add-all # 目录内全部预设:只写定义
node tools/workbuddy.mjs add volcengine-agent-plan # 只写定义,Key 在应用里填
node tools/workbuddy.mjs add stepfun-step-plan --key-from-dsh STEPFUN_API_KEY # 想一次到位也行
node tools/workbuddy.mjs unset-key volcengine-agent-plan # 清掉某渠道 Key,改为应用内填(--all 清全部)
node tools/workbuddy.mjs remove stepfun-step-plan
node tools/workbuddy.mjs add-custom --model gpt-5.1 --url https://api.openai.com/v1 --name "GPT-5.1"
- 填 Key(应用内):设置 → 模型 → 模型管理 → 找到条目 → 编辑,面板里直接填 API Key(也能改接口地址、限额、能力开关)
- 条目按 WorkBuddy 的校验规则(
isValidLocalCustomModel)生成,写入前本地校验、临时文件+rename 原子替换 - 写入后需重启 WorkBuddy(CLI 会在应用运行中时提示)
- 应用会把本地模型标记为
custom-local:前缀 +customtag,实际请求前还原原始模型 ID useCustomProtocol: false(默认)=应用自动在 URL 后追加/chat/completions;需要完整 URL 时加--full-url- Key 来源三选一:
--key、--key-env NAME、--key-from-dsh REF(复用 DSH 凭据服务里的 Key) - 无 Key 的写入不会覆盖已有的 Key;WorkBuddy 的模型按 ID 全局唯一,国内/国际预设共用模型 ID 时目录里靠前的一家生效。想换一家先
remove <另一家>再add <目标家>
OpenCode 适配
同一份预设目录也能写入 OpenCode 的配置(~/.config/opencode/opencode.json 或 .jsonc,自动备份)。只写“提供商定义”,绝不写 Key——Key 由 OpenCode 自己的「连接提供商」流程存进 ~/.local/share/opencode/auth.json,和官方原生服务商的待遇完全一致:
provider-hub-opencode list # 预设、已装状态、Key 连接状态
provider-hub-opencode add volcengine-agent-plan # 只写定义(npm/baseURL/模型/限额/视觉)
provider-hub-opencode add longcat --key sk-... # 想命令补 Key 也行(写入 auth.json)
provider-hub-opencode add-all [--prune]
provider-hub-opencode migrate-key # 把配置里残留的 Key 搬进 auth.json
provider-hub-opencode remove volcengine-agent-plan [--purge-key]
provider-hub-opencode add-custom --model gpt-5.1 --url https://api.openai.com/v1 [--key sk-...] [--name "GPT-5.1"]
用户侧填 Key(应用内完成,零命令):OpenCode → 管理模型 → + 连接提供商 → 自定义 OpenAI 兼容提供商 → Provider ID 输入预设 ID(如 volcengine-agent-plan)→ 粘贴 Key。存进 auth.json 后,该渠道就能在「连接提供商」里查看/断开,与 OpenCode Zen、DeepSeek 等官方渠道体验一致。
- 模型条目带 OpenCode 需要的全部元数据:
name/limit(上下文/输出,含 1M 窗口)/reasoning/tool_call/attachment+modalities(方舟文档要求的图片理解字段) - OpenCode 的 models.dev 目录里没有的路由自动补正确的 npm SDK(依据本地
~/.cache/opencode/models.json判定协议) - Key 三选一:
--key、--key-env NAME、--key-from-dsh REF(复用 DSH 凭据服务里的 Key),全部写入 auth.json;配置文件永远零明文 Key list按 coverage 分区:OpenCode 原生已内置的(models.dev 目录里有同名 provider)自动折叠成一行,只把「OpenCode 没有的渠道」摆在上面——那才是本工具的价值;add一个原生已覆盖的预设时会提示你它本可走/connect--key-in-config是旧模式(Key 写回options.apiKey),仅供想要单文件自包含配置的用户
连接向导(provider-hub-connect)
不想记命令?一条交互式向导就是「第三方登录」入口:列出全部渠道(●=这些 App 原生没有、本工具独有;○=部分 App 原生已有)→ 选编号 → 贴一次 Key → 自动探测本机装了哪些 App 并分别写入:
provider-hub-connect # 或 npm run connect
echo -e "3\nsk-ant-xxx\ny" | provider-hub-connect # 也可管道喂输入
- WorkBuddy:写入 models.json(之后在应用内也能改 Key)
- OpenCode:定义进配置、Key 进 auth.json(与官方 /connect 同一存储,应用内可查看/断开)
- DSH:打印应用内的添加路径(官方「添加模型提供商 → 第三方模型提供商」下拉里选该渠道,贴 Key 保存)
--yes跳过写入确认
cc-switch 适配
cc-switch(136k★ 的多 App 服务商切换器:Claude Code / Codex / Gemini CLI / OpenCode / OpenClaw / Claude Desktop / GrokBuild)的全部状态就是一个纯 JSON:~/.cc-switch/config.json({version:2, <app>:{providers:{<id>:…}, current}})。各段的 settingsConfig 形状照它 Rust 源码(src-tauri/src/provider.rs)逐段实现,我们的目录写进去后直接出现在 cc-switch 的 UI 里:
| 段 | settingsConfig 形状 | 哪些预设能进 |
|---|---|---|
| opencode | {npm, name, options:{baseURL, apiKey}, models} |
全部协议 |
| codex | {auth:{OPENAI_API_KEY}, config:"<config.toml>"} |
OpenAI 兼容(wire_api 按协议填 responses/chat) |
| claude / claude-desktop | {env:{ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN}, model} |
Anthropic Messages |
| gemini | {env:{GOOGLE_GEMINI_BASE_URL, GEMINI_API_KEY}} |
Google 自家端点 |
| openclaw | {baseUrl, apiKey} |
全部协议 |
provider-hub-cc-switch list
provider-hub-cc-switch add volcengine-agent-plan --key-from-dsh ARK_API_KEY # 自动写全部匹配段
provider-hub-cc-switch add minimax-coding-plan --app claude,claude-desktop # 只写指定段
provider-hub-cc-switch add-all
provider-hub-cc-switch unset-key <presetId> [--app ...] # Key 改为在 cc-switch UI 里填
provider-hub-cc-switch remove <presetId> [--app ...]
- Key 写进 cc-switch 自己的 config(它的设计如此:切换时才写入 App 的 live 配置),不动 OpenCode 的 auth.json
- 合并保留其它 App 段与用户手编辑;绝不改
current,不抢用户当前选中的 provider - GrokBuild / Hermes / Pi 段的形状还没扒全(配置文本是 TOML/YAML 内嵌),暂不写入
- 连接向导(provider-hub-connect)检测到 cc-switch 也会一并写入全部匹配段
ChatGPT 桌面版「从第三方登录」按钮(实验)
把我们的渠道挑选器种进 ChatGPT/Codex 桌面版的登录页——右下角会出现「⚡ 从第三方登录」悬浮按钮,点开就是全部渠道的搜索/挑选/填 Key 面板:
npm run patch-chatgpt # = node tools/patch-chatgpt.mjs --apply
node tools/patch-chatgpt.mjs --status
node tools/patch-chatgpt.mjs --restore
原理(tools/patch-chatgpt.mjs,全部可逆):
- 渠道挑选器写到
~/.provider-hub/overlay.js(改它不用重新打包) - 给 app.asar 的入口(package.json 的
main)加一段 4 行钩子:每个 webContents 加载完执行这个文件 - 重打包 asar → 重算 SHA256 写回 Info.plist 的
ElectronAsarIntegrity→ ad-hoc 重签名,应用照常启动 - 原始 asar/Info.plist 备份在
~/.provider-hub/,--restore一键还原
已知限制(不藏奸):
- 每次 ChatGPT 更新都会冲掉补丁,重跑
--apply即可 - ad-hoc 签名丢失 notarization(本机运行无碍)
- macOS 会拦截别的进程改
/Applications里的 App——在你自己的终端里运行npm run patch-chatgpt(首次弹权限框点允许,或加 sudo) - 按钮目前是入口:写 Key 进本机渠道库;把 ChatGPT 流量导向所选服务商还需要本地代理(下一步)
目录维护
- models.dev 补充目录:
node tools/sync-modelsdev.mjs读 OpenCode 那份 models.dev 全量缓存(~/.cache/opencode/models.json),把每个已有预设缺的模型补进生成文件core/catalog-models.js。它只做加法:core/providers.js里的手工条目、注释、已策展字段一个都不动,且永远排在新模型前面。--check可判断生成文件是否过期。- 抄得动的:模型清单(id / 名称 / 上下文 / 输出上限)、思考等级(models.dev 的
reasoning_options.values与 pi-ai 的THINKING_LEVELS同名,none→off: null) - 抄不动的:模态只能 text / image —— pi-ai 的
MODALITIES就这两个值,models.dev 的pdf/video/audio写进 profile 会被 schema 直接拒(实测报错expected "text" | "image" but got "pdf"),生成器会裁掉;输出不是文本的模型(画图/语音/embedding)也一并裁掉 - 匹配按 id → baseURL → 名称相等,故意不用凭据变量名兜底:同一家会用同一个 env 覆盖不同套餐端点(
STEPFUN_API_KEY同时管api.stepfun.com/v1与/step_plan/v1),按 env 匹配会把一个套餐的模型嫁接到另一个套餐的预设上
- 抄得动的:模型清单(id / 名称 / 上下文 / 输出上限)、思考等级(models.dev 的
- 模型清单与逐模型兼容开关可从任意权威目录刷新:
node tools/refresh-catalog.mjs --catalog <catalog.json>(先--dry审阅);路由级只保留全部模型一致的开关,不一致的由模型自己携带compat - 校验:
node --test跑形状不变量(模态集合、思考档集合、正整数限额、id 唯一、生成文件只做加法);node tools/verify-presets.mjs <dsh-llm-pi-ai 路径>再拿装着的真实 pi-ai schema 逐条过一遍(schemastery的 Ref 要.get()读值) - WorkBuddy 端用
node tools/workbuddy.mjs add-all --prune同步:装入全部预设并清掉目录里已不存在的旧条目
注意
- 预设里的模型规格(上下文/输出/档位)是可编辑的起手默认值;模型 ID 与限额以各服务商文档为准,可在官方 Models 页增删改
- 声明了
reasoningEfforts的模型才会有思考档位选择器;未声明的模型按无档位处理 - 移除只下线路由,不删除 Key(见上)
English
Expand the providers DSH can use: pick a provider in the official Models page, paste the API key, save. The presets sit in the same select as the 42 providers DSH ships, and the plugin writes the official llm-pi-ai route and its credential in one step - effective immediately, no restart, no hand-editing settings.yaml.
54 built-in presets (OpenAI-compatible, Anthropic Messages and OpenAI Responses protocols), covering plain APIs and subscription channels (Alibaba Token Plan, Zhipu Coding, Kimi Coding, MiniMax Coding Plan, Xiaomi MiMo, OpenCode Zen, Volcengine Agent Plan, Command Code, ...). Providers DSH already ships are never repeated in that select.
Install
dsh plugin --profile web add dsh-provider-hub
Restart dsh web, open Settings → Models, and use Add model provider.
Usage
Pick Third-party model provider, choose the channel in the Provider select (the plugin's presets are listed next to DSH's own), paste the API key, and save. The curated model list, context and output limits, reasoning levels and per-model compat switches are filled in for you; pick the provider's models in the composer's model selector. The stored key stays in the credentials service, so re-adding a route never needs it again.
How it works
All writes go through official services - the plugin never touches config files directly: llm.registerConfigurableProviders(entries) declares the presets in the configurable-provider directory the page's own select reads (the same seam dsh-llm-pi-ai uses for its 42 providers), settings.mutate('llm-pi-ai', [set providers.<route>], revision) writes the curated profile into the user layer of the official pi-ai namespace once the row is saved (schema-validated, hot-registered), and credentials.set(apiKeyEnv, key) stores the key.
Two limits are worth knowing. A directory entry carries no model catalog - only provider / displayName / settingsNs / settingsPath / defaultBaseURL / baseURLEnv / nativeAuth - so curation happens after adoption, not in the directory. And curation is once per preset version, recorded per route in ~/.provider-hub/directory.json, so an edit you make to that profile afterwards is never reverted.
core/ is pure JS (no Node built-ins, no DSH imports, no I/O): the provider catalog plus profile building, validation and the directory plan, shared by the host half, this plugin's browser half, and any future desktop shell.
The same catalog ships two CLIs: provider-hub-workbuddy writes WorkBuddy's local models.json, provider-hub-opencode writes OpenCode's config. The OpenCode CLI writes provider definitions only - keys land in OpenCode's own auth.json (the file its in-app 连接提供商 flow uses), so custom providers behave like natively supported ones and stay manageable from the app. Both accept --key-from-dsh <REF> to reuse a key already stored in DSH.
Notes
Preset model specs are editable starting defaults; model ids and limits follow each vendor's docs. Only models declaring reasoningEfforts get the thinking-level selector. Removing a route keeps its credential.
No comments yet. Be the first to write one.