dsh-cc-switch
Brings the providers you already configured in cc-switch into DeepSeek Harness: reads the cc-switch database, converts Claude / Codex / OpenClaw / MCode / Pi entries into llm-pi-ai routes with their API keys, and adds a health check that measures time-to-first-byte and whether each stream completes.
Install
dsh plugin --profile web add dsh-cc-switch
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-cc-switch



把 cc-switch 里配置好的模型供应商直接接进 DeepSeek Harness:
读取 cc-switch 的数据库(~/.cc-switch/cc-switch.db),把每家供应商转换成 DSH 内置
@deepseek-ai/dsh-llm-pi-ai 的 provider 路由,写进「模型」页面用的同一份配置,并把 API Key
存进 harness 的凭据存储。cc-switch 里有什么模型,DSH 的模型选择器里就能选到什么。
本插件针对当前 DSH 版本(0.2.0-rc.2)的插件契约与 settings/credentials 服务编写,
不使用任何已废弃的配置字段。
它到底做了什么
cc-switch DeepSeek Harness
────────── ─────────────────
providers 表 ──┐
claude │ convert.js plan.js settings.mutate('llm-pi-ai')
codex ├──────────────► 路由 ──────────► providers: { ccswitch-*: {...} }
openclaw │ (协议/端点/模型) (只增删自己写过的) │
mcode / pi … │ └─► 持久化到 profile 的 cordis.patch.yml
│ 并热加载 —— 不用重启
proxy 日志 ────┘ credentials.set('CCSWITCH_…_API_KEY', <key>) ─► 凭据存储
关键点:本插件不实现任何 HTTP/协议代码,也不注册第二个 LLM 适配器
(那样会撞上 DUPLICATE_ADAPTER)。它只做「翻译 + 写入」,
真正的协议实现仍然由 DSH 自带的 pi-ai 适配器完成,所以升级 DSH 后不会失效。
安装
从插件市场一键安装(推荐)
装过 dsh-market(DSH「设置 → 插件」里的可视化插件市场)的话,
直接在市场里搜 cc-switch 点安装即可。市场里的条目来自精选列表
本插件已按该列表的规则提交(条目文件见仓库里的 marketplace/LightingHa__dsh-cc-switch.yml)。
用 CLI 安装
dsh plugin add dsh-cc-switch # 默认 profile dsh plugin --profile desktop add dsh-cc-switch # 指定 profile
安装动作会改 profile 的两处文件:
~/.dsh/profiles/<profile>/package.json→dependencies加"dsh-cc-switch",
dsh.profile.bundles 加 "dsh-cc-switch"
- 在 profile 目录执行一次安装(把包装进
node_modules)
重启 DSH 后生效(bundle 列表在启动时读取)。也可以在「设置 → 插件」里直接启用,
插件管理器会热挂载条目,不必重启。
从源码安装(开发 / 改代码时)
$plugin = "D:/path/to/dsh-cc-switch" # 换成你 clone 的位置 $profile = "$env:DSH_HOME/profiles/desktop" # 换成目标 profile # 1) 在 $profile/package.json 里: # dependencies 加 "dsh-cc-switch": "file:$plugin" # dsh.profile.bundles 加 "dsh-cc-switch" # 2) 安装 cd $profile pnpm install
file: 依赖在 pnpm 里是快照:改完插件源码必须重装才生效 ——
删掉node_modules/dsh-cc-switch,再pnpm add "dsh-cc-switch@file:<路径>";
只跑 pnpm install 会提示 “Already up to date” 而不会刷新内容。
环境要求
- DSH
>= 0.2.0-rc.1(在0.2.0-rc.2上验证) - Node.js
>= 22.13(读 cc-switch 的 SQLite 库用到内置的node:sqlite;它在 Node 22.13 才不再需要--experimental-sqlite。DSH 自带的 Node 24 满足) - 本机装过 cc-switch,并至少配置了一家第三方供应商
装完之后
插件加载后会自动同步一次(syncOnLoad),之后每 30 秒看一眼 cc-switch 数据库有没有变
(watchSeconds),改了自动跟上。首次同步会:
1. 把 cc-switch 里的 API Key 写进凭据存储(名字形如 CCSWITCH_CODEX_…_API_KEY);
2. 把路由写进 llm-pi-ai 的 providers,持久化到 profile 并热加载。
然后打开「设置 → 模型」,就能看到 ccswitch-* 开头的供应商;把它设为默认模型即可开始用。
不想让它自动写入?把配置改成 mode: plan(见下方配置表),它只会计算并打日志。
用工具手动控制
插件注册了工具 cc_switch:
action · 作用
status(默认) · 看当前状态、本次会做什么
sync · 立即同步(dry_run: true 可只预演)
plan · 只预演,绝不写入
probe · 体检:按 pi-ai 会打的那个 URL 真发一次最小流式请求,实测每条路由通不通、首字节多久、流有没有正常收尾
list · 列出 cc-switch 里识别到的全部供应商与模型
skip-list · 只看没导入的供应商及原因
常用参数:app_types(本次只处理这些 app 类型)、include / exclude(按名称/ID 关键字收窄)。
这些参数只影响本次调用,不改插件配置。
例:cc_switch + action=sync, dry_run=true → 打印「将新增几条、更新几条、删几条、写几个凭据」。
体检输出怎么读
🩺 cc-switch 路由体检:共 2 条(可用 2,慢 0,异常 0),单条上限 200s
· ccswitch-openclaw-ark-code-latest(Ark Code Latest / openai-completions / 模型 ark-code-latest)
✅ 可用:HTTP 200,首字节 4.8s,共 7.9s,32365 字节
· ccswitch-codex-…(小胡王国 / openai-responses / 模型 gpt-6-astra)
🐢 可用,但很慢:HTTP 200,首字节 96.3s,共 96.4s,50534 字节
提示:首字节太久,对话时很容易被上游或网关掐断(表现为流读取失败)…
结论 · 含义
✅ 可用 · 2xx + 流里出现完成标记(response.completed / [DONE] / message_stop)
🐢 可用,但很慢 · 通了,但首字节超过 probeSlowFirstByteMs;长对话容易中途断流
⚠️ 流没正常结束 · 连接断了却没看到完成标记 —— 上游把流掐了
⏱️ 超时 · 超过 probeTimeoutMs 仍没跑完
❌ 不可用 · 非 2xx、连不上、DNS/证书失败,或上游在流里返回了错误(错误原文会摘出来,密钥自动打码)
体检只读:不写配置、不写凭据,Key 只出现在请求头里。
支持的 cc-switch app 类型与映射规则
app 类型 · cc-switch 里的配置形状 · 映射结果
claude、claude-desktop · {env:{ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN\ · ANTHROPIC_API_KEY, ANTHROPIC_MODEL, ANTHROPIC_DEFAULT__MODEL}} · anthropic-messages,模型取 ANTHROPIC_MODEL + 各 ANTHROPIC_DEFAULT__MODEL
codex · {auth:{OPENAI_API_KEY}, config:"<TOML>"} · 解析 TOML 的 model / model_provider / [model_providers.*];wire_api=responses → openai-responses,否则按 Codex 自身默认的 chat → openai-completions
openclaw · {baseUrl, apiKey, api, models[]}(也认整份 models.providers) · 与 pi-ai 字段几乎 1:1;一个 providers 条目展开成多条路由
mcode · {custom_provider:{<key>:{api, options:{baseURL,apiKey}, models}}} · 按条目 api,enabled:false 的跳过
pi · [models] default + [model.<id>] base_url / api_key / api_backend · 按 api_backend
gemini · {env:{GEMINI_/GOOGLE_}, config} · 原生 generateContent 不在 pi-ai 支持范围内,默认跳过并说明原因;若在 cc-switch 里开了 OpenAI 兼容(或配置了 meta.apiFormat)就按兼容协议导入
opencode、hermes、grokbuild、未知类型 · 结构不定 · 深度扫描 baseURL / apiKey / models,能认出来就导入,认不出就进 skip-list 并说明原因
识别到的元信息(meta)也会用上:
apiFormat/codexCopilotApiFormat→ 决定协议(openai_chat→openai-completions)apiKeyField→ 指定用哪个字段当密钥isFullUrl→ 端点是完整接口地址时自动去掉/chat/completions、/responses、/messages尾巴customUserAgent/requestHeaders→ 转成路由请求头(非法表头会被丢弃,避免整次写入失败)model_catalog_json→ 补充模型清单
模型清单从哪来:优先用配置里声明的模型;再合并 cc-switch 代理日志
(proxy_request_logs)里这家供应商真实用过的模型名 —— 这能救回那些只声明一
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::2,最后更新 2026-10-15