前言¶
DSH(DeepSeek Harness)采用「一切皆插件」的理念,本地智能体开发者经常需要把跑在本地的模型网关接入桌面端。hima6652/dsh-workbuddy2api-hub 就是这样一个插件,它的作用是把本地运行的 workbuddy2api-hub 接进 DSH 桌面端,让 hub 上的模型出现在 DSH 的模型列表里,并在侧边栏显示积分余额和用量。
在此之前,如果要接本地 hub,需要手动配置 provider、复制凭据、手动同步模型,流程繁琐且容易出错。这个插件把整个流程自动化:配置一次连接,之后模型自动同步、余额自动刷新、用量自动统计。
安装¶
前置条件:
- Node.js ≥ 20
- 本地 workbuddy2api-hub 已经跑起来,浏览器能打开 http://127.0.0.1:8788
- DSH 桌面端能正常打开
最快的方式是从 npm 安装(装进 profile,不用 clone):
cd ~/.dsh/profiles/desktop
npm i dsh-workbuddy2api-hub
重启 DSH 桌面端。
也可以使用仓库里的安装脚本(会同时登记 dsh.profile.bundles):
# 1. 克隆到任意目录
git clone https://github.com/HimA6652/dsh-workbuddy2api-hub.git
cd dsh-workbuddy2api-hub
# 2. 先确认 hub 通不通(只读,不改任何东西)
node scripts/smoke-live.mjs
# 3. 挂进桌面端 profile(默认 ~/.dsh/profiles/desktop)
node scripts/install-local.mjs
# 4. 重启 DSH 桌面端
DSH CLI 机器上也可以直接从 GitHub 拉:
dsh plugin --profile desktop add github:HimA6652/dsh-workbuddy2api-hub
配置与连接¶
改 profile 的 cordis.patch.yml(或本仓库的 cordis.patch.yml 作为默认值)。只改配置就能换地址/密码,不用改代码:
- id: workbuddy-hub
name: dsh-workbuddy2api-hub
config:
baseUrl: http://127.0.0.1:8788 # 换机器就改成 http://192.168.1.10:8788
pwd: admin # 面板密码
tab: gateway # 打开看板时落在哪个页签
配置项说明:
| 配置 | 默认 | 说明 |
|---|---|---|
| baseUrl | http://127.0.0.1:8788 | 服务地址。从浏览器地址栏整条粘进来也行(?pwd=…&tab=… 会被剥掉),缺协议自动补 http:// |
| pwd | admin | 面板密码。只用于换 Token,不会被当成 API Key |
| tab | gateway | 深链页签,白名单外的值退回 gateway |
| apiKey | 空 | 可选。写了就存进 DSH 凭据库(引用名见 apiKeyEnv),不落状态文件 |
| apiKeyEnv | WORKBUDDY2API_HUB_API_KEY | DSH 凭据库里的引用名 |
| providerEntry | llm-pi-ai | 写到哪个 settings 的 ns 下 |
| routeKey | workbuddy2api-hub | 写进 providers. |
| maxKeys | 10 | 最多同步几条网关 key(1–50)。超出的只读不写,避免一次刷出几十个 provider |
| intervalSeconds | 120 | 轮询间隔,下限 30、上限 3600;连续失败会指数退避到 30 分钟 |
| sync | true | 关掉就只看数据、不写模型 |
| autoApiKey | true | 缺 Key 时是否允许从面板 /settings/reveal 自动取 |
| newModelPolicy | select | hub 上新出的模型默认勾选还是先不写 |
| retireHours | 24 | 模型下架后的宽限期 |
| thresholds.lowCredits | 100 | 余额低于它就告警;0 关掉 |
| thresholds.unreachablePolls | 5 | 连续失败几次才报「连不上」 |
| stateDir | 空 | 状态文件目录。默认跟 profile 同级(workbuddy2api-hub.json) |
重启后:设置 → workbuddy2api-hub → 确认地址/密码 → 「测试连接」→「立即同步」→ 模型出现在设置 → 模型 里,provider 名 workbuddy2api-hub。
模型同步与多 key 管理¶
插件会把 /v1/models 写进 llm-pi-ai 的 providers.workbuddy2api-hub,每个模型带上 contextWindow / maxTokens / 图片输入 / 思考档位。模型名后面直接带网关的倍率(如 GLM-5.1 ×0.79),免费模型标 Free——倍率写不进名字,选择器里就看不见。
网关里有几条 API Key 就同步几条 provider(一 key 一条路由、一条凭据)。主 key 固定 workbuddy2api-hub,其余 workbuddy2api-hub-<名字>。每条 key 每轮都拉模型清单(实测与绑定账号数无关),设置页里各自一份模型开关,模型多的那几条默认收起,点卡片头上那行「账号 N · 模型 6/19」展开。
一个 key ↔ 一条 provider 路由 ↔ 一条凭据引用。路由键建好就不再变(主 key 恒 workbuddy2api-hub,其余 workbuddy2api-hub-<名字>),所以网关里改 key 的名字、换倍率,都不会让会话里已经选中的模型消失。网关里删掉某条 key → 那条路由自动撤掉;删掉的是主 key → 徽标显示「主 key 已删除」、会话提示重新选模型,不会拿别的 key 偷偷顶替。
余额与用量¶
余额与用量来自 /v1/balance-summary 的 credit 余额,以及 /usage?range=today 的请求数 / 失败数 / tokens / credit / API 等价花费 / 缓存命中。每条 key 的余额由后端拿 /accounts 里这条 key 绑定的账号 credits.remain 求和得出(纯内存,不额外发请求);账号没出现在 /accounts 里时该 key 的余额是 null,不报 0。
侧边栏徽标展开态三行——第一行「当前会话那条 key 的名字 + 该 key 余额 / 整域余额」,第二行今日,第三行本周,右半边是 tokens / 积分 / 等价 三列、等宽右对齐。收起态是一个 36×36 圆形图标。数字跟着当前会话用的那条 key 走:会话选的是 key-c 的模型,第一行的名字、余额和第二、三行的用量就都换成 key-c 的,切会话自动切,且不为此多发一个请求(余额是后端拿 /accounts 在本地按 key 绑定的账号求和);会话用的不是网关模型时回落到主 key。
点一下徽标出副窗:贴着徽标上沿弹出,内容是「各 key 用量」表(列标题 tokens / 积分 / 等价,每条 key 一段「名字 + 账号 N」再跟今日、本周两行,末尾 总计),上面两个格子是「这条 key 的余额」与「全部账号」,底部「打开面板」「关闭」,点遮罩或右上角 × 关闭。所有数字两位小数(72.30M、¥10.39、2841.06),数字全是网关原样给的——每条 key 的用量来自 /usage/analytics 的按 API Key 分组,总计来自 /usage 的整域汇总。
错误处理与容错¶
插件对各种失败都有处理:
| 情况 | 面板上看到的 | 处理方式 |
|---|---|---|
| 服务没开 / 端口不通 | 连不上 hub(fetch failed):确认本地服务已启动(默认 http://127.0.0.1:8788) | 冷启动 60 秒内每 15 秒重试,之后指数退避 |
| 8 秒没响应 | 连不上 hub(请求超时) | 同上 |
| 密码错 | 面板密码不对 | 出 auth 告警,不反复猛撞 |
| 60 秒内错 5 次 | 面板登录被限流,N 秒后再试 | 轮询间隔抬到 hub 建议的等待时间以上 |
| 404 | 服务版本可能与本插件不匹配(HTTP 404) | — |
| 5xx | hub 内部错误(HTTP 500) | — |
| 返回 HTML | 返回了非 JSON 内容 | — |
| 缺 API Key | 还没有可用的 hub API Key,暂不写入模型 | 出 api-key 告警,不写注定 401 的路由 |
模型下架先进宽限期(默认 24 小时,可一键立即移除),回来能复活;内容没变就不写配置,避免每次轮询都触发一次配置更新;配置冲突自动重取 revision 重试。/state 永远返回 200,前端永远有东西可渲染。
安全与隐私¶
API Key 只进 DSH 凭据库和内存,绝不写状态文件,也绝不出现在 /state 里(连掩码都不给)。面板密码会存进 profile 的状态文件 workbuddy2api-hub.json(明文,重启后要靠它继续登录)。它只是 hub 的面板密码,不等于 API Key;如果你的 hub 用了别的重要密码,建议给面板单独设一个。
写接口有三道闸:只接受本机来源(127.0.0.1 / ::1 / ::ffff:127.0.0.1)、sec-fetch-site 必须是 same-origin 或 none 且 Origin 与 Host 一致、content-type 必须是 JSON。响应不带任何 CORS 头——这样同机网页用 no-cors 的简单请求也打不进写接口。
插件接口¶
宿主侧注册一个前缀路由 /workbuddy2api-hub/api:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /state | 全量快照(带 ETag,前端用 If-None-Match 拿 304) |
| GET | /usage?range=today | 只刷用量(range 取 today / week / month / all) |
| GET | /accounts | 只刷账号 |
| GET | /dashboard-url | 看板深链(只带 tab,密码永远不进 URL),只给本机 |
| POST | /config | 改地址 / 密码 / 页签 / 间隔 / API Key |
| POST | /selection /bulk /enable-new | 勾选模型、全选/全不选、新模型默认策略(带 hubKeyId 就只作用于那条 key) |
| POST | /keys/pull | 立刻重拉某条 key 的模型(排障用,60 秒节流) |
| POST | /keys/selection /keys/sync-selection | 单独改某条 key 的勾选 / 把一条 key 的勾选同步到别的 key |
| POST | /keys/main | 指定哪条 key 是主 key(只换身份,不改它已有的路由键) |
| POST | /refresh /test /policy /dismiss /retire /clear | 同步、探测、策略、消警、立即移除、清空同步 |
适用场景¶
这个插件适合需要在 DSH 中使用本地 workbuddy2api-hub 的开发者。使用前应检查源码与许可证,确保符合你的使用场景。