dsh-plugin-litellm-bridge
v2.1.1
Published
LiteLLM gateway bridge for DSH: assemble root / coder / research fallback chains from the DSH model pool and hand the order to a LiteLLM gateway that executes retries and fallbacks. The plugin performs no routing itself.
Maintainers
Readme
dsh-fallback-auto-pool-arch
DSH + LiteLLM 网关桥接方案。
litellm-bridge 是一个 DSH 插件:在 DSH 里按 agent 类型编排 fallback 降级链、 下发给 LiteLLM 网关执行、查看日志、绑定会话 profile。
核心定位:插件不内置任何路由、重试、降级逻辑。降级能力 100% 交给 外部 LiteLLM 网关;插件只负责「编排顺序」和「把顺序下发下去」。
模型数据源:DSH【设置 → 模型】里已配置好的供应商与模型。 插件不从网关拉取模型清单,供应商凭证也只在 DSH 原生模型页面维护。
📖 完整部署文档:docs/README.md
快速导航
| 我想… | 去哪 |
|---|---|
| 读完整部署 / 导入 / 测试流程 | docs/README.md |
| 在 DSH 里选模型、编排降级链 | DSH 设置 → LiteLLM 网关 → 路由配置 |
| 改网关模板 | litellm-gateway/config.yaml.template |
| 验证链路是否通 | node tests/live-e2e.mjs |
| 看插件本体 | dsh-plugin-litellm-bridge/ |
| 看 header 注入插件 | dsh-plugin-header-inject/ |
| 配密钥 | .env(不提交,模板见 .env.example) |
三条硬边界
| 层 | 负责 | 不负责 |
|---|---|---|
| litellm-bridge 插件 | 读 DSH 模型池、编排三条降级链、下发 config.yaml、拉日志、发探针、写会话变量、子代理改道 | 重试、降级执行、选具体模型凭证 |
| header-inject 插件 | 注入 x-agent-type / x-session-profile 头 | 认识 LiteLLM、写变量 |
| LiteLLM 网关 | 全部路由 / 重试 / 降级 / 负载均衡,按插件下发的顺序执行 | 维护模型清单、UI、DSH 集成 |
网关生命周期跟随 DSH:DSH 启动时插件自动拉起网关,DSH 退出时自动关闭; 网关是插件托管的子进程,不需要手动常驻,也不会被残留。
子代理路由覆盖
| 会话选中的供应商 | root 主 Agent | 子 Agent |
|---|---|---|
| trae / workbuddy | 保持原样(消耗积分) | 强制改道 litellm-gateway(走 subagent 降级链) |
| litellm-gateway | 走网关 | 走网关(不覆盖) |
| 未知 / 其它 | 原样 | 原样(fail-open,不猜) |
实现用 cordis 的服务读取 waterfall(internal/get)包装 subagents 服务,
在子会话创建之前改写 agentOptions —— 因为「子代理用什么模型」在创建前就定了,
事后事件改不了。详见 docs/README.md 第 6.5 节。
root 链与 subagent 链完全独立
每个 profile 里有三条互不影响的降级链:
| 链 | 谁在用 | 可配 |
|---|---|---|
| root | 主 Agent | 首选模型 + 任意长度 fallback 序列 + 超时 |
| coder | spawn 出来的 Coder 子 Agent | 同上,可与 root 完全不同 |
| research | spawn 出来的 Research 子 Agent | 同上 |
保存后点「保存并下发到网关」→ 插件生成 config.yaml → 重启网关 → 网关按该顺序执行。
安装
方式 A:插件市场 / git 地址(推荐)
仓库根目录就是一个可安装的 npm 包(package.json 用 exports 指向
dsh-plugin-litellm-bridge/ 里的实现),所以可以直接按 git 装:
git+https://github.com/heixiua/dsh-fallback-auto-pool-arch.git#<commit-sha>在插件市场里粘贴这个地址即可。建议带上 commit sha(而不是 #main),
否则每次重装都会拉到最新代码,出问题时无法复现。
方式 B:本地路径安装
# 完全退出 DSH(全部 6 个 DeepSeek Harness.exe 进程)后
cd "D:\AI agent cache\dsh\profiles\desktop"
pnpm add "file:D:/AI sandbox/dsh-sandbox/dsh-fallback-auto-pool-arch"⚠ 装完立刻检查
pnpm-workspace.yaml的allowBuilds里有没有"set this to true or false"占位符,有就改成true/false并再跑一次pnpm install。否则会破坏后续所有插件的安装能力。
方式 C:从子目录装(旧方式,仍支持)
pnpm add "file:D:/AI sandbox/dsh-sandbox/dsh-fallback-auto-pool-arch/dsh-plugin-litellm-bridge"子目录里保留了完整、可独立安装的 package.json,与根目录指向同一份实现
(tests/package-layout.test.mjs 有断言保证两者不会漂移)。
60 秒上手
# 1) 装网关
python -m pip install 'litellm[proxy]'
# 2) 准备密钥(Windows 默认路径)
# 至少要有 LITELLM_MASTER_KEY=sk-<足够长的随机串>
notepad "D:\AI agent cache\dsh\.env"
# 3) 自测插件逻辑(不启动网关)
node tests/run-all.mjs # 期望 497 通过, 0 失败(十个套件)
# 4) 真实链路验证(会拉起网关、发真请求、清理并恢复)
node tests/live-e2e.mjs # 期望 20 通过, 0 失败然后在 DSH 里:先禁用 dsh-llm-fallbacks → 安装插件 → 重启。
到【设置 → 模型】确认供应商可用,再到【设置 → LiteLLM 网关 → 路由配置】选模型。
密钥纪律
- 所有模型密钥、npm 令牌统一从
D:\AI agent cache\dsh\.env读取; .env只在网关进程侧加载,由start-gateway.sh注入环境变量;- 供应商的 api-key / api 地址统一在 DSH【设置-模型】 维护,插件不接管;
- 插件 UI 不读取、不回显任何明文密钥,界面仅展示 【来自 .env 环境变量】;
- 生成的
config.yaml里api_key一律是os.environ/XXX引用,零明文; - 插件代码用私有字段 + 强制脱敏 + 只报存在性,三道硬保证
(
tests/host-half.test.mjs有 4 项针对泄漏向量的断言)。
已知限制
有几处主动偏离了字面要求,因为照字面实现会得到不能工作的东西。详见 docs/README.md 第 10 节,摘要:
- 插件 HTTP 路由不能挂在
/api/**下 —— 那是dsh-api-gateway的 typert RPC 分发领地,挂过去实测永远 404(transport for ... HTTP 404)。 改用插件命名空间/plugins/dsh-plugin-litellm-bridge(同dsh-connect-trae的/plugins/...与dsh-qq-plugin的/.dsh-qq-plugin)。 - 网关热重载在本机 LiteLLM 1.108.3 不可用(
/config/reload404,/config/update需 PostgreSQL +store_model_in_db,SQLite 硬失败) → 改为「写 config.yaml + 重启进程」;start-gateway.sh本就有 「config.yaml 存在则跳过生成」逻辑,所以写盘即生效。 - 网关必须知道供应商 api_base 才调得通 —— 上一版生成
os.environ/LITELLM_UPSTREAM_<模型名>这类没人设置的变量,单测全绿但 网关每条链都是坏的。现在从 DSH 供应商配置里取真实baseURL, 只把api_key写成os.environ/<供应商声明的凭证变量>。 agent/spawn事件在 DSH 中不存在(已用cordis_inspect核对全部约 85 个事件) → header 注入改用真实存在的llm-pi-ai/request-headerswaterfall。- 子代理改道不能用「监听事件」实现 —— 子代理用什么模型在子会话创建前就定了
→ 改用
internal/get服务读取 waterfall,在startActivation前改写。
MIT
