dsh-key-switch
IdentifiedDeepSeek Harness plugin: 多把 API Key 池 + 一键切换 + 每把 key 的实时余额
dsh-key-switch
English | 中文
给 DeepSeek Harness(dsh)用的 API Key 池插件:多把 DeepSeek key 放在一个池子里,一键切换当前生效的那把,并且每把 key 各自还剩多少钱一目了然。
deepseek-official 在 dsh 里是单一路由(PROVIDER 写死),一个路由只能挂一把 key。想用多个账号,只能在"换 key"上做文章——这个插件就是干这个的。
功能
- 侧边栏余额入口:
设置上方一行,实时显示当前生效 key 的余额,60 秒自动刷新 - 点开即切换:弹层里每把 key 一行,带备注、掩码、余额;点哪行就切到哪把,下一次模型调用生效,不用重启
- 每把 key 各自的余额:宿主进程直接向
api.deepseek.com/user/balance查询,60 秒缓存,刷新余额可强制重查;自动识别 CNY / USD 多币种 - 管理页:设置 →
API Key 管理,添加 / 删除 / 切换,支持备注("个人账号"、"公司账号"…);趋势和自动策略收在页面底部的高级设置里,默认折叠 - 余额趋势:阶梯图(24 小时 / 7 天 / 30 天)+ 今日已花、日均消耗、预计可用天数;弹层每行还有一条 24 小时迷你折线
- 自动策略(默认关闭):余额低于阈值自动换到更健康的账号;或按权重均衡各账号的消耗速度
- 原生外观:字号、颜色、描边、阴影全部用 dsh 自己的
--dsw-*设计令牌,浅色深色自动跟随
安装
dsh plugin --profile web add dsh-key-switch
装完重启一次 dsh web(宿主插件层只在启动时加载),然后:
- 设置 → API Key 管理 → 把 key 一个个粘进去,填个备注
- 侧边栏底部会出现余额入口,点开就能切
它是怎么切换的
切换不是改配置,也不是劫持请求:插件把值写进 $DSH_HOME/.credentials.yaml 里 deepseek-official 引用的那个凭据项(默认 DEEPSEEK_API_KEY),宿主对凭据文件有热重载,下一次模型调用就用新值。
写入是原子替换(临时文件 + rename),并且写完会回读校验,值对不上就报错而不是假装成功。
如果你的环境变量里也定义了同名变量(
DEEPSEEK_API_KEY),它会盖住文件里的值——界面会直接提示,这种情况下切换不会生效。
语言
界面文案跟随 dsh 的语言设置(设置 → 通用设置 → 语言),插件提供六种:
| 语言 | 说明 |
|---|---|
简体中文 zh | 内置 |
English en | 内置(缺失键的回退语言) |
繁體中文 zh-Hant | 插件注册,回退链 zh-Hant → zh → en |
日本語 ja | 插件注册,回退到 en |
한국어 ko | 插件注册,回退到 en |
Русский ru | 插件注册,回退到 en |
宿主本身只有中英两套界面翻译:切到日 / 韩 / 俄时,dsh 的外壳文案会回落成英文,而这个插件的文案仍是各自语言。
余额趋势
官方平台给的是按天聚合的消费账单,回答"过去花了多少"。这个插件回答的是另一类问题:现在还剩多少、还能撑多久。
它就做三件事:在每次查余额时顺手记一个样本 → 画成阶梯图 → 算出三个数。
| 数字 | 含义 |
|---|---|
| 今日已花 | 今天第一个样本减最后一个(按账号自己的币种) |
| 日均消耗 | 最近 7 天实际消耗 ÷ 观测天数,没有消耗时显示 0 |
| 预计可用 | 当前余额 ÷ 日均消耗,不花钱就不编造天数(显示 —) |
图是阶梯而不是斜线:余额是阶梯函数(花钱才跳一档),斜线会假装钱在匀速流失。采样断档(间隔超过中位数 3 倍)时折线断开,不连一条假线;查询失败的样本也会记录,曲线在那里留个断口,而不是画成 0。
数据在哪里
$DSH_HOME/dsh-key-switch/balances.jsonl,一行一个样本,追加写、权限 0600:
{"v":1,"t":1793128276356,"k":"k_mvqbpnx1_ojvu2w","c":"CNY","b":"26.43","g":"0.00","u":"26.43"}
{"v":1,"t":1793128336000,"k":"k_mvqbpnx1_ojvu2w","ok":false,"e":"HTTP 429"}
- 只记池子里 key 的稳定 id 和后四位,不存 key 本身
- 同值样本至少隔 5 分钟才落一行,狂点刷新也不会把文件撑爆
- 保留策略:最近 7 天原始点;7–90 天压成每小时一点;更早的丢弃(自动压缩,无需维护)
- 2 把 key 用 90 天,文件大约 1 MB
它不是什么
- 不是持续监控:DSH 没运行的时候没有采样,那段时间的曲线是断的
- 不是官方账单的替代:官方的按天消费统计才是唯一准的,这里只反映"你看到的余额变化"
会话消耗归因
官方账单只按天、按 API Key 聚合,回答不了"钱花在哪个会话上"。这一节直接读本地会话日志算。
数据来源
每个会话文件 $DSH_HOME/sessions/<工作区>/<会话>/session.*.jsonl.zstd 里,每条 assistant/message 都带 usage:
{"inputTokens":12993,"outputTokens":423,"cacheReadTokens":1408,"reasoningTokens":210}
其中 inputTokens 是缓存未命中的输入,cacheReadTokens 是命中部分,模型名由同会话的 request/header 向下继承。所以这是每次调用的精确记账,不是余额差分估算——不受采样间隔和账单延迟影响。
分时段
一天按 8 小时切三段(00–08 / 08–16 / 16–24),每段单独累计。切换「今天 / 7 天 / 30 天」会按所选范围重新聚合。
金额从哪来
插件不内置单价。 官方价格会变(还有高峰/低谷两套),写死在代码里迟早算错钱。所以默认只显示 token;你在底部填了某个模型的 6 个单价(峰/谷 × 输入/命中/输出,单位「元/百万 token」),表格才会显示金额。峰谷按北京时间工作日 9–12、14–18 自动判定。
单价存在 $DSH_HOME/dsh-key-switch/prices.json(0600)。
自动策略
两个开关,默认都是关的。关着的时候插件只读不写,不会碰你的 key。
余额不足时自动切换
当前 key 的余额低于阈值时,切到同币种里余额最多的那把。
- 只在余额确实读到、且候选也高于阈值时才动手;没有健康候选就原地不动
- 不跨币种比较:¥10 和 $10 不是一回事,硬比只会算出错误的结论
- 冷却 30 分钟,避免在阈值附近来回抖
按权重均衡消耗
想让两个账号"用得一样快",或者"公司号先用、个人号兜底",就用这个。
它比较的不是金额,而是每个账号消耗掉自身余额的比例——这样跨币种也不需要汇率:
消耗占比 = 窗口内花掉的 ÷ (当前余额 + 花掉的)
得分 = 消耗占比 ÷ 权重
当前 key 的得分比"得分最低的那把"高出容差(默认 20 个百分点)时,切到得分最低的那把。权重填 2 表示这个账号可以承受两倍于别人的消耗才被换下。
窗口默认 7 天,零消耗时不评价(不花钱就不该换)。
数据与安全
策略存在 $DSH_HOME/dsh-key-switch/policy.json(0600),含上次动作记录,用于界面展示和冷却判断。切换仍然走"改写凭据文件 + 回读校验"那条路径,和手动切换完全一样。
数据与安全
| 项 | 说明 |
|---|---|
| key 存在哪 | $DSH_HOME/dsh-key-switch/keys.json,权限 0600(明文——不存值就换不了 key) |
| 浏览器能看到什么 | 平时只有 ****后四位。点「显示」或「复制」时,宿主才把这一把的明文经同源 POST 返回一次,30 秒后界面自动收回;接口要求同源 cookie,且只能取池子里的 key |
| 写接口鉴权 | 要求同源会话 cookie,本机其它进程调不动 |
| 余额请求 | 由宿主发往 api.deepseek.com,不经浏览器、不受跨域限制 |
| 不做什么 | 不采集、不上传、不统计使用行为,没有任何第三方请求 |
卸载后 ~/.dsh/dsh-key-switch/ 会留下你的 key 池,需要的话手动删掉。
兼容性
在 DSH 0.1.5-rc.3 + Web profile 上实测(macOS / Chrome)。依赖:
- 宿主服务:
webServer(硬依赖)、settings/llm(软取,拿不到就用默认的deepseek-official) - 客户端槽位:
sidebar.footer.action、shell.overlay、settings.section
已知限制
- 只支持 DeepSeek 官方接口的余额查询(其它厂商接口不同,没做)
- 一个 provider 一把 key:这是 dsh 的限制,不是插件的;想同时用多个账号就得切
- 页面里同时开多个 dsh 标签页时,浏览器对同一源只有 6 条连接,而每个标签页开两条常驻 SSE,新请求可能排队——此时入口会显示
⚠ 余额不可用,关掉多余标签页即可 - 余额查询失败不会影响切换和正常对话
- 设置导航的图标由宿主按 section id 查表决定(第三方分区一律是齿轮)。插件会在自己那一行把齿轮替换成钥匙图标——这属于 DOM 层处理,宿主若改动导航结构就会失效,届时图标会退回齿轮,不影响功能
卸载
dsh plugin --profile web remove dsh-key-switch
License
MIT
Comments
Loading…