DeepSeek Harness(DSH)一只住在 DSH 界面右下角的小鲸鱼娘,帮你盯着DeepSeek账户余额。QQ弹弹,支持拖拽吸附、左吸附翻转、数字滚动动画,随界面自动启用,建议直接喊来你的dsh安装
JavaScript
5,267
81 commits
updated Oct 11, 2026

DeepSeek Harness(DSH)Web 界面右下角的常驻挂件:小鲸鱼气泡图 + DeepSeek API 余额 + 今日已用 + 每轮对话消耗,并且泡泡内容可以完全自定义(点击序列、模块化排版、并列加权出泡、随机语句/随机图片)。标准 DSH bundle 插件,dsh plugin 一键安装,无需任何会话令牌。
⚠️ Codex 版小鲸鱼已迁至独立仓库 → https://github.com/Yang-huai406/Codex-Whale-Public(已安装用户无需重装;详见下方「两条分支怎么选」)
本仓库现在只维护一条产品线(main,同一个包同时支持 DSH Web 与官方桌面客户端)。按你要挂在哪里选:
| 你要挂在哪 | 用哪条分支 | 安装方式 |
|---|---|---|
| DSH Web 界面右下角(就是这个 README 描述的插件) | main(默认分支) | dsh plugin --profile web add dsh-whale-widget(推荐,装 npm 已发布版);也可以从本仓库装 dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget,但那样装的是 main 当前状态、不跟随已发布版本 |
| 官方桌面客户端(Electron)右下角 | main(同一个包) | ⚠️ 不能用 --profile web(桌面端读的是 desktop profile,CLI 也拒绝 --profile desktop)—— 在桌面端会话里让 DSH 自己装,见下方「官方桌面端(Electron 客户端)请先看这一节」 |
| Codex 桌面应用(跟随 Codex 窗口、无独立网页) | ⚠️ 已迁出本仓库 | 新仓库 · 最新版下载 · 已安装用户无需重装 Codex 版迁移公告:本次迁移保留了开发历史、历代版本与作者贡献,并清理了旧图片中的非必要元数据(贡献者致谢见文末「致谢」)。后续更新、问题反馈与版本发布都在新仓库;反馈问题时请注明版本、系统和复现步骤,勿上传密钥、完整配置或未脱敏日志。 |
⚠️ 两条线互不兼容:Codex 版不能用 dsh plugin … add 装进 DSH 网页,本仓库的插件也不能在 Codex 桌面里运行。
⚠️ 安装方式二选一、别混用(npm 名 / github:)—— 它们是同一个包名,先后安装会并存冲突;已经是 github: 装的,要换 npm 名请先 dsh plugin --profile web remove dsh-whale-widget。
DEEPSEEK_API_KEY;② DSH 账号登录态 —— 通过「设置 → 账号与余额」登录了 DeepSeek 账号、又没配 API key 时自动使用(不需要去 platform 建 key).dshw-usage-archive.json);金额按 8 位小数记账、显示保留两位{cost} 引用),入口:菜单 → 「音效与提示」→ 「全局设置」→ 展开「每轮消耗提示」→「编辑提示内容」deepseek-flash → DeepSeek-V4.1-Flash,旧名标注"同 V4.1 Flash")默认音效组 · 100%、自动关 180s · 叮~),点一行才展开该区的设置项(可同时展开多个)。每个音效都有独立音量,每行带「试听」;音效行左侧的 [✓] 决定该音效响不响(不响 = 仍可冒泡)。底栏 取消 / 恢复默认 / 保存 —— 面板内的改动只落内存,点「保存」才生效,点「取消」完整还原(「恢复默认」之后点取消同样能撤销)...,0 = 不截断)
{balance_ds},老配置里的模块照旧显示,无需重配);赠金({bonus_ds})与充值余额({recharge_ds})是单独拆出来的两个模块,取不到数时显示 —(真的为 0 才显示 0.00)v0.3.19-beta){cost});开关、自动关闭秒数、提示音量、任务结束音效与内容编辑入口都在「音效与提示 → 全局设置」面板的「每轮消耗提示」区(主菜单不再单列这一行){session} 会替换成当前对话名(读不到就显示「当前对话」,超长自动截断为 12 字符 + ...)。同一个未回答的提问只响一次(刷新页面也不会重复响)assets/minecraft-exp-orb.wav)与 A(assets/task-end-a.wav),也可选任意片段或音效组[✓] 决定「响不响」(不响 = 仍会冒泡提示)跟随按压音量 N%);一旦你拖过那个滑块,就按你设的值播(摘要只显示百分比)。这样既能"一个总音量管全局",也能单独压低某类提示音。角色 1 · 泡泡图 2、音效组 3 · 片段 4),点一行才展开明细;「导入片段」在音频那一区里;收起/展开时会顺带停掉正在试听的那一段petpet、money1 两张图,也可上传 png/gif,供图片/随机图片模块使用除内置的 DeepSeek 余额外,可在「小鲸鱼记账 → 模型」里添加任意厂商;每个模型独立配置余额预警 / 今日预算 / 额度:
probeUrl 探活验证 key,余额显示「—」,今日已用按会话事件估算):硅基流动(CN / EN)、火山方舟 Ark、OpenAI、Anthropic Claude、Google Gemini、xAI Grok、Groq、Mistral AI、Together AI、Fireworks AI、DeepInfra、Cerebras、阿里云百炼(通义千问)、百度千帆(文心)、腾讯混元、讯飞星火、魔搭 ModelScope、本地模型(Ollama / LM Studio)OPENROUTER_API_KEY);删除模型会连带清理该模型的额度模块与设置a.b[0].c 与 scale 乘数);点「测试连通性」可先验证 keyinput + cacheRead + output,推理 token 已含在 output 内,跨天保留),也可切换手动填写;支持「不重置 / 每日 / 每月」kind:'quota' 模板):直接读厂商官方接口的「窗口已用% + 重置时间」,与上面按会话统计的额度互补。支持一个接口返回多个窗口(目前 OpenCode Go 为 5h / 周 / 月三窗口),逐窗口展示已用百分比与各自的紧凑重置倒计时;模板用 quota.json.windows 描述各窗口的字段路径{balance}、{today}、{quota}、{quota_used}、{quota_left}、{quota_total}、{quota_reset}说明:并非所有厂商都提供「用 API key 查余额」的接口。硅基流动的余额接口已被官方下线(2026-08-11 更新公告:
/user/info自 2026-08-14 起停止服务,「后续将适时提供替代 API」,截至发版仍未见替代接口),火山方舟的余额 / 用量与阿里云百炼 / 百度千帆 / 腾讯混元一样属于各家云平台 AK/SK 签名的 OpenAPI,OpenAI / Anthropic / Gemini / xAI / Groq / Mistral / Together / Fireworks / DeepInfra / Cerebras 则根本没有公开的余额查询接口 —— 这些模板统一是「无余额接口 + 探活验证 key」,今日已用按会话事件估算。厂商的订阅额度接口(智谱 / Kimi Coding / MiniMax Coding / OpenCode Go)只对订阅套餐账号有效:Token 资源包账号调用智谱接口会返回「当前用户不存在coding plan」,这种情况请用上面的「额度(订阅 / 资源包)」自动统计。模板只提供默认值:选完模板后可以随意改写接口地址与字段路径;留空的字段会继续沿用模板默认值(不会因为留空而失效)。
ℹ️ 先分清楚:这一节说的是本插件读取本机 Codex 会话日志的能力(属于
main,就是把 Codex 当数据源), 与**「Codex 版小鲸鱼」挂件**(跟随 Codex 窗口的那个端口)是两回事 —— 后者已迁出本仓库,见「两条分支怎么选」里的「Codex 版迁移公告」。
⚠️ 限制:Codex 支持目前只是部分接口适配,本挂件不能安装到 Codex 里(它是 DSH Web 插件,Codex 仅作为数据来源被读取);订阅窗口没有真实订阅样本可验证,遇异常欢迎反馈。
挂件可以直接读本机 Codex 的会话日志统计 token 用量 —— 因此不限于 DSH 内部,你在 Codex CLI / 桌面版里跑的消耗也能看到。
$CODEX_HOME/sessions/YYYY/MM/DD/rollout-*.jsonl(含 archived_sessions/),明文 JSONL;只读本机文件、不联网、不需要密钥,也不会写入 ~/.codextotal_token_usage)的差值累加,天然避免同一轮多条记录被重复计数;模型归属由 turn_context.payload.model 判定;按天 + 模型聚合,带增量缓存($DSH_HOME/.dshw-codex.json,只存聚合与文件偏移)Codex 今日 x · 近7天 y tokens;模型子菜单显示今日 / 本月 / 累计 / 近7天与会话文件数;「测试」按钮直接返回本地统计rate_limits 带窗口快照,有 ChatGPT 订阅时子菜单自动追加 5h 已用 x% · 2小时30分后重置 | 周 已用 y% · 3天后重置(字段名已做容错;API-key 计费或无订阅时该行不显示)dsh-whale-widget/
├── package.json # DSH bundle 插件元数据(dsh.bundle.patch 指向 cordis.patch.yml;顶层 icon 指向 icon.png)
├── icon.png # 插件列表图标(256×256 PNG,含透明;宿主读成 data URL 塞进 meta.icon,必须是正方形)
├── README.md # 本文件
├── cordis.patch.yml # 插件挂载声明
├── lib/
│ ├── index.js # 宿主侧插件本体(路由 + 记账 + 音效/图片/角色服务)
│ └── accounting.mjs # 记账内核(定点金额运算 + 余额观测/校正账本)
├── assets/
│ ├── whale-widget.js # 前端挂件本体(由宿主按 mtime 热读取)
│ ├── DSH2.png # README 顶部展示图
│ ├── DSniang1.png # 小鲸鱼本体(cut-out,气泡由代码绘制)
│ ├── DSniang02.png # 备用整图(兼容旧版手动安装路径)
│ ├── rua.gif # 随机台词/撒娇动图(可选)
│ ├── Ya1.mp3 / Ya2.mp3 # 预置音效「小黄鸭」按压 / 松开
│ ├── D1.mp3 / D2.mp3 # 预置音效「音效1」按压 / 松开
│ ├── minecraft-exp-orb.wav # 任务结束音内置默认音效(Minecraft·经验球)
│ ├── task-end-a.wav # 任务结束音内置预设(A)
│ ├── bubble-petpet.gif # 内置泡泡图:petpet
│ └── bubble-money1.gif # 内置泡泡图:money1(余额预警默认内容的配图)
└── whale-widget-prompt.md # 完整规格/维护提示词(面向二次开发)
运行时数据(都放在 $DSH_HOME,默认 ~/.dsh;用环境变量 DSH_HOME 可以改到别处):
| 文件 / 目录 | 用途 |
|---|---|
.dshw-size.json | 挂件外观与开关(缩放、音量、音效组、峰值样式、吸附相关等) |
.dshw-usage.json | 记账账本 + 按日余额观测/校正摘要 + 用量设置(任务结束音、余额预警、今日预算、每轮消耗提示内容,以及 events:按压 / 每轮消耗 / 提问 / 授权四个事件的音效选择、独立音量、冒泡配置;每轮消耗的自动关闭秒数存在 .dshw-size.json 的 turnCostCloseMs) |
.dshw-usage.json.before-recharge-fix.bak | 旧格式账本备份(0.3.1 首次写入旧账本前自动创建;已存在则不覆盖) |
.dshw-turn.json | 每轮消耗的 seq(避免热重载后前端把新轮次当旧轮次) |
.dshw-bubble.json | 自定义泡泡配置(点击序列 + 模块库 + 点按角色推进队列开关) |
.dshw-api.json | 自定义 API 模型注册表(厂商 / 凭据名 / 接口字段 / 自定义单价 / 额度与用量累计;不含密钥) |
.dshw-usage-archive.json | 账本归档(超过保留期的逐轮明细与逐日汇总;明细 90 天/2 万条、逐日 365 天) |
.dshw-codex.json | Codex 本地会话统计缓存(按天/模型聚合 + 文件偏移;不含任何凭据) |
whale-roles/ | 自定义角色图 + roles.json 索引 |
whale-audio/ | 音频片段 <id>.wav + audio.json 索引(音效组/片段) |
whale-bubble-imgs/ | 泡泡图库图片 + bubble-imgs.json 索引 |
桌面端读的不是 web profile。 官方桌面客户端用的是 desktop profile(%USERPROFILE%\.dsh\profiles\desktop),而 dsh plugin 命令行按设计拒绝碰它:
error: profile "desktop" is managed exclusively by the Electron application
所以下面「方式 A~D」里的 --profile web 命令对桌面端不适用 —— 按它装完,插件落在 web profile 里,而桌面窗口读的是 desktop profile,一个字也读不到。表现就是「右下角什么都没有(连 ☰ 也没有)、控制台也不报错」。
桌面端的正确装法:明确使用当前宿主内置的 plugin_manager。
在桌面客户端的会话里可直接说:
请使用当前桌面端内置的
plugin_manager安装dsh-whale-widget。先核对当前 profile 和是否已有同名插件;已有安装时先报告来源与版本。按该工具支持的操作完成后,告诉我安装结果及是否需要重启。
plugin_manager 的作用域是当前 profile(桌面端为 desktop),由宿主使用其自带的包管理器完成安装与挂载登记。需要固定版本时,将安装规格改成 dsh-whale-widget@<目标版本>。这条说明用于减少安装前后的无关探索(#194);不需要自行构造认证 cookie、调用底层 RPC 或改写宿主管理的 profile 文件。工具不可用或操作不受支持时,先说明缺少哪项宿主能力,不绕过桌面端限制改用 --profile web。
首次安装与升级的生效方式(#162):
"application":"applied",但这不保证当前窗口已显示挂件。若装完没有出现,完全退出客户端(含系统托盘)后重新打开,再按下方两条自检排查。"restart-required" 时完全退出并重开,随后重新核对实际版本。0.1.7-rc.2,页面没有升级入口,重新“添加”带版本的同名包也可能只返回“已安装”。先检查该宿主内置工具是否支持同来源更新;若工具也不支持,保留当前安装,按宿主支持的升级方案处理。只有明确需要卸载再安装或迁移来源时,才先保留原来源、精确版本和用户数据的恢复办法;不要把卸载、删除依赖目录/锁文件当作通用更新步骤。命令行侧的 dsh web 使用自己的 web profile:更新后重启宿主,再在浏览器按 Ctrl+F5。
装完怎么自检(两条分别对应宿主半区与客户端半区):
%USERPROFILE%\.dsh\.dshw-turn.json 存在,且 seq 随对话递增;%APPDATA%\@deepseek-ai\dsh-desktop\Local Storage\leveldb 里出现 dshw-pos / dshw-last-seq —— 这两个键只有挂件前端会写。桌面端界面里看不到插件版本号时,可以看 %USERPROFILE%\.dsh\profiles\desktop\package.json 的 dsh.profile.bundles 和同目录的 pnpm-lock.yaml。
下面方式 A~D 都是 Web(
dsh web) 的安装方式。
适用于别人直接发给你一个 zip,或你手上已有一份解压好的插件目录(目录里应有 package.json、cordis.patch.yml、lib/、assets/、README.md)。
# 1) 若是 zip:先解压到一个固定、以后不会移动或删除的目录(不要放临时目录/下载目录)
# 例:D:\Plugins\dsh-whale-widget
# 要安装的是「包含 package.json 的那一层」,不要多套一层同名目录
# 2) 确认关键文件都在(缺 assets/ 会导致没图、没声)
Test-Path "D:\Plugins\dsh-whale-widget\package.json",
"D:\Plugins\dsh-whale-widget\lib\index.js",
"D:\Plugins\dsh-whale-widget\assets\whale-widget.js"
# 3) 如果之前从 GitHub / npm 装过同名插件,先卸载避免版本冲突
dsh plugin --profile web remove dsh-whale-widget
# 4) 用绝对路径安装(路径含空格要加引号)
dsh plugin --profile web add link:D:\Plugins\dsh-whale-widget
说明:
link: 是软链安装:源目录里的文件改了立即生效;但安装后不能移动/重命名该目录,移动了要重新 add 一次dsh plugin --profile web add file:D:\Plugins\dsh-whale-widget(此后源目录再改不会同步,需重新 add)assets/minecraft-exp-orb.wav、assets/task-end-a.wav 等内置资源;删掉 assets 里的文件会让对应功能静默降级(无图/无声)dsh web,再 F5 刷新浏览器无需本地克隆,一条命令安装:
dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget
说明:
$env:http_proxy="http://<ip>:<port>"; $env:https_proxy="http://<ip>:<port>"; $env:all_proxy="socks5://<ip>:<port>"; dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget
dsh web,再 F5 刷新浏览器在仓库根目录(package.json 所在目录)执行:
dsh plugin --profile web add link:.
说明:
dsh plugin 会把参数转发给 pnpm,并在成功后自动把 dsh-whale-widget 加入 dsh.profile.bundleslink:. 表示链接当前目录(仓库根目录本身就是插件包)。如果仓库在别处,用绝对路径:
dsh plugin --profile web add link:D:\你的路径\DeepSeek-Balance-Whale-Widget
link:.\dsh-whale-widget——仓库里没有 dsh-whale-widget/ 子目录,这样会安装成普通依赖而非插件dsh web,再 F5 刷新浏览器add link:<新路径>;若提示冲突,先 dsh plugin --profile web remove dsh-whale-widget 再 adddsh plugin --profile web add dsh-whale-widget
plugin_manager 提示)请帮我安装插件 dsh-whale-widget。可能的来源有两种:GitHub 仓库
MeteorNOX/DeepSeek-Balance-Whale-Widget,或者我本地已经有这个插件的「完整资源包」。
先确认运行形态:如果当前是官方桌面客户端,请使用宿主内置 plugin_manager,
不要执行下面的 Web 命令,也不要自行构造认证/RPC或修改 desktop profile。
以下步骤仅用于 dsh web:
1. 确认 DSH 安装器使用的 pnpm 可用;若提示找不到 pnpm,先报告安装器所用路径和版本,
按该 DSH 版本的安装说明处理,不直接假定需要全局安装或重装插件。
2. 在 Web profile 安装(按我实际拿到的来源任选一种):
【来源一:从 GitHub 安装】
dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget
或从本地 git 仓库链接安装:
dsh plugin --profile web add link:<仓库绝对路径>
(注意:仓库根目录就是插件包,不要写成 link:.\dsh-whale-widget 这种带子目录的路径)
【来源二:我本地已有完整资源包(zip 或已解压目录)】
先确认「完整资源包」长什么样:一个目录,里面应当有
package.json、cordis.patch.yml、lib/index.js、
assets/(含 whale-widget.js、DSniang1.png、Ya1.mp3、minecraft-exp-orb.wav、task-end-a.wav 等)、README.md
然后按下面做:
a) 如果给我的是 zip:先解压到一个**固定、以后不会移动或删除**的目录,例如
D:\Plugins\dsh-whale-widget
不要解压到临时目录/下载目录/会被清理的位置;也不要多套一层——
要安装的是**包含 package.json 的那一层**,不是外面那个同名压缩包目录
b) 检查文件完整性(任意一条 False 就先告诉我,不要继续装):
Test-Path "<资源包目录>\package.json"
Test-Path "<资源包目录>\lib\index.js"
Test-Path "<资源包目录>\assets\whale-widget.js"
并确认 package.json 里 name 是 dsh-whale-widget、带 dsh.bundle.patch 字段
c) 如果之前从 GitHub / npm 装过同名插件,先卸载避免版本冲突:
dsh plugin --profile web remove dsh-whale-widget
d) 用**绝对路径**安装(路径含空格要加引号):
dsh plugin --profile web add link:<资源包目录>
link: 是软链安装:源目录改了立即生效,但安装后不能移动/重命名该目录;
移动后必须重新执行一次 add。若想按拷贝安装可用:
dsh plugin --profile web add file:<资源包目录>
(file: 以后源目录改动不会同步,需要重新 add)
3. 如果报 pnpm 阻止构建脚本(allowBuilds 相关),先确认被阻止的是哪个包。
本插件没有安装/编译脚本;不要因此放行所有依赖的构建脚本,按具体报错处理。
4. 重启 dsh web,然后 F5 刷新浏览器
安装后验证:
- dsh --profile web --dump-config 应该能看到 dsh-whale-widget 在 bundles 里
- curl http://127.0.0.1:3080/dsh-whale/balance.json 应返回 200 JSON(含 totalBalance)
- curl http://127.0.0.1:3080/dsh-whale/widget.js 应返回 200 JS
- curl "http://127.0.0.1:3080/dsh-whale/audio-fragment.wav?id=exp_orb" 应返回 200 audio/wav
- curl "http://127.0.0.1:3080/dsh-whale/audio-fragment.wav?id=end_a" 也应返回 200 audio/wav
(用来确认资源包里的内置音效已随包就位;若是 404 说明 assets/ 不完整)
另外请检查 DSH 凭据里是否配置了 DEEPSEEK_API_KEY(没有就提示用户配置;如果用户是用 DSH 账号登录的,较新 DSH 上不配 key 也能取余额,**别把"没 key"当成故障**)。
余额有两种取数方式(API key 优先,两者互不干扰):
DEEPSEEK_API_KEY(推荐):DeepSeek API 密钥,用于拉取余额(GET https://api.deepseek.com/user/balance)。在 DSH 凭据服务里配置(凭据管理界面 / .dsh/.credentials.yaml)。0.1.7-rc.2)才有这个服务;老版本、未登录、或账号没有余额钱包时,会回到下面的「未配置」提示。不需要
DEEPSEEK_PLATFORM_TOKEN。早期版本的"实时·令牌"模式已下线,今日已用统一由小鲸鱼记账(余额差 + 会话事件)计算,零令牌开箱即用。
插件会把凭据交给谁、以及谁能改这件事的规则:
{base} 指向你自己填的地址),插件默认不会把凭据发过去,而是返回一条明确提示。
127.0.0.1 / localhost / [::1],一律 403。
DSHW_ADMIN_HOSTS=192.0.2.10:3080,myhost.lan(逗号分隔,可带端口;默认空)。https://user:pass@host/),凭据名只允许字母、数字与下划线。添加自定义模型时,还会按需用到各自厂商的凭据名(都可不配,用到哪个配哪个):
| 凭据名 | 用途 |
|---|---|
OPENROUTER_API_KEY | OpenRouter 余额(/api/v1/credits) |
MOONSHOT_API_KEY | Kimi / Moonshot 大陆站余额(人民币) |
MOONSHOT_INTL_API_KEY | Kimi / Moonshot 国际站余额(美元,独立账号体系) |
SILICONFLOW_API_KEY | 硅基流动 /v1/models 探活 |
ARK_API_KEY | 火山方舟 /api/v3/models 探活 |
ZHIPU_API_KEY | 智谱(订阅额度接口 / Coding 端点) |
OPENCODE_GO_API_KEY | OpenCode Go 订阅额度(opencode.ai/zen/go/v1/usage,鉴权为 Authorization: Bearer <key>) |
CUSTOM_API_KEY | 自定义 HTTP / OpenAI 兼容中转站 |
⚠️ 自定义模型面板里的「凭据名」决定密钥写进哪个 ref。换厂商时请确认这一栏跟着模板变了,否则新密钥会写进上一家厂商的凭据名里(覆盖掉原来的 key)。v679 起新增模型会自动跟随模板。
dsh plugin --profile web remove dsh-whale-widget
如果你之前按旧方式手动安装过(复制 whale-balance.mjs + 改 cordis.patch.yml),先清理:
$web = "$env:USERPROFILE\.dsh\profiles\web"
Remove-Item "$web\whale-balance.mjs" -ErrorAction SilentlyContinue
Remove-Item "$web\whale-balance.cjs" -ErrorAction SilentlyContinue
Remove-Item "$web\DSniang1.png" -ErrorAction SilentlyContinue
Remove-Item "$web\DSniang02.png" -ErrorAction SilentlyContinue
然后编辑 $web\cordis.patch.yml,删除这段旧补丁:
- insert:
- id: whale-balance-widget
name: ./whale-balance.mjs?v=1
如果里面只有这段,直接改成:
[]
清理后再执行上面的安装命令。
dsh --profile web --dump-config | Select-String -Pattern "whale"
curl http://127.0.0.1:3080/dsh-whale/balance.json
curl http://127.0.0.1:3080/dsh-whale/size.json
curl http://127.0.0.1:3080/dsh-whale/widget.js
curl http://127.0.0.1:3080/dsh-whale/image.png
curl http://127.0.0.1:3080/dsh-whale/audio.json
/dsh-whale/balance.json → 200 JSON,含 {ok:true, totalBalance, currency, todayUsage}/dsh-whale/size.json → GET 返回配置;PUT 写入/dsh-whale/widget.js → 200 JS(前端挂件本体)/dsh-whale/image.png → 200 image/png/dsh-whale/audio.json → 200,含 groups / fragments(其中内置片段 exp_orb = Minecraft·经验球、end_a = A)/dsh-whale/audio-fragment.wav?id=exp_orb → 200 audio/wav(内置任务结束音;无需用户导入)/dsh-whale/audio-fragment.wav?id=end_a → 200 audio/wav(内置任务结束音 A)/dsh-whale/wait.json → 200 JSON,含 {ok:true, pending};pending 为当前挂起的「提问 / 授权」({kind:'question'|'approval', id, ts})或 null —— 这是「提问提示 / 授权提示」音效与常驻气泡的数据源(默认每秒轮询一次)/dsh-whale/about.json → 200 JSON:菜单底部版号那行点开后的「关于 / 自检」面板数据源(版本、通道、文件路径与时间、数据落点、记账/余额/Codex 状态;路径已脱敏,点开才请求)/dsh-whale/update-check.json → 200 JSON:检查更新({ok, current, latest, hasUpdate, source});点了才联网,镜像优先(npmmirror → jsdelivr → unpkg → npmjs)+ npm view 兜底,宿主侧 10 分钟缓存⚠️ 关于上面这些
curl:全部 26 个/dsh-whale/*路由都已接入 DSH 浏览器信任栅栏(connection.requestRejection)。 因此不带会话凭据的裸curl会返回 401(伪造Host头则是 403)—— 这是预期行为,不是接口坏了。 想验证接口是否存活,看返回 401/403 即说明路由已注册且栅栏在工作;在浏览器里访问同一条路径(带会话)才是 200。 另外自 0.3.15 起,写请求(POST/PUT/PATCH/DELETE)还必须是本机来源(Host 为127.0.0.1/localhost/[::1]),否则 403 —— 详见上方「安全边界」。
exit 1 / pnpm failed:这些是汇总错误,不能据此认定插件代码有错,也不能直接归因网络。若明确出现“找不到 pnpm / 不是内部或外部命令”(#145),先检查宿主安装器使用的包管理器与启动环境;桌面端尤其要区分宿主自带工具和终端 PATH 中的工具。诊断时请提供:
web 或 desktop),首次安装还是升级。.plugin-manager/logs/operation-*/pnpm.log,再对照 hub.log;同时说明是否使用代理/镜像、失败请求的目标域名和状态码。ERR_PNPM_ADDING_TO_ROOT、Invalid time value、Failed to fetch 应分别定位,不按同一原因处理。node_modules、锁文件或修改全局 registry。相关issue由报告者验证效果后决定是否关闭。dsh web):确认安装命令成功;dsh --profile web --dump-config 里能看到 dsh-whale-widget;重启 dsh web 后 F5。desktop profile,不能用 --profile web(而 --profile desktop 会被 CLI 拒绝,这是设计如此)。正确入口见上面「官方桌面端(Electron 客户端)请先看这一节」,并用那里的两条自检判断是「没装到位」还是「装了但没渲染」。新装也建议重开一次客户端(issue #162:热生效不一定够)。/dsh-whale/*)的访问校验:默认只接受回环地址(127.0.0.1 / localhost / [::1])的请求,并拒绝跨站标记(Sec-Fetch-Site: cross-site)与 Origin 和 Host 不同源的请求 —— 这是防「恶意网页读写本机接口」的信任栅栏(issue #92 / #136)。如果你把 dsh web 放在反向代理或局域网地址后面,请用环境变量声明允许的 Host(逗号分隔,可带端口),否则会被 403:
DSHW_TRUSTED_HOSTS=dsh.example.com,10.0.0.5:3080 dsh web
assets/ 完整(DSniang1.png、*.mp3、minecraft-exp-orb.wav 等);缺失时相关功能静默降级。选项 → 文件类型 / 站点排除,把 127.0.0.1 与 localhost 加进去;其它管理器同理,关键词是"排除本机地址 / 不监控该站点")。关掉挂件音效开关并不能消除弹窗 —— 音效元素在页面初始化时就会建立。[✓](不勾 = 静音、但照旧冒泡),再在下拉里选一个音效;不需要提示就把该区入口行左边的总开关 [✓] 取消。(入口行右侧的摘要会实时显示当前配置。).dshw-usage.json)被外部改坏或结构异常,插件拒绝覆盖它以免丢数据。先把它备份改名让插件重建,再按需用「余额校正」补账。403 / 在别的机器上改了配置不生效:0.3.15 起写操作只能在运行 DSH 的那台机器上、用 127.0.0.1(本机地址)打开界面进行。从局域网或反向代理访问时,读没问题、写会被拒。需要远端管理就用 DSHW_ADMIN_HOSTS 显式授权那台机器(见「凭据 → 安全边界」)。--:先等一次成功的余额观测;统计从该观测时刻开始,起点之前的消费不在此区间内。[✓] 是勾上的(入口行右侧摘要会直接显示 已关闭 或当前配置);一轮对话要完整结束(turn/end)才结算。余额变化泡泡与消耗泡泡抢层时,提醒会退化为居中卡片。{cost});同一区里能设自动关闭秒数、提示音量与任务结束音效。A,另有内置的 Minecraft·经验球可选);到「音效与提示 → 全局设置」→ 展开「每轮消耗提示」,确认「任务结束音」那行左侧的 [✓] 是勾上的(取消勾选 = 静音)。若自定义片段文件被删,会回退/静音。跟随按压音量 N% 变成 N%)。没拖过时它跟随①区「按压音效」的音量 —— 摘要里会写明,滑块也显示实际生效值。想让某类提示更轻就把自己的滑块调小;想整体轻就调①区。点「恢复默认」会把这几条都退回"跟随①区"。(0.3.17 之前这个滑块确实不生效,是本版修好的。)⚠ 设置保存失败:<原因>(例如数据目录只读、接口被拦)。看到这条提示说明这次改动没有落盘,请按原因处理后再保存一次。? 圈圈里。.dshw-usage.json 的 accounting.books 里。当前版本已让界面把历史本里的日期正常显示(标注「已观测消费 · 历史账户」),并在「小鲸鱼记账」面板顶部提示「检测到 N 个记账本」;两个本不会被相加(插件无法判断两次是不是同一个账户),但同一天的明细可以在该面板的「每日与逐条明细」里逐日查看。whale-widget.js;仍不行请反馈浏览器型号。assets/whale-widget.js 由宿主按 mtime 热读取,硬刷新(Ctrl+F5)即可;改了宿主 lib/index.js 必须重启 dsh web。deepseek-flash 即 DeepSeek-V4.1-Flash,旧名 deepseek-v4-flash / -vision-exp 现在也由同一颗 V4.1-Flash 提供并按 Flash 计价(面板里已加标注)。金额按 CNY / 百万 tokens 计,[空闲时段, 高峰时段];高峰 = 工作日 9:00–12:00、14:00–18:00(北京时间),空闲价为高峰价的一半;2026-08-23 起周末全天按谷价。表在 lib/index.js 顶部 PRICING / BASE_PRICE / PRO_PRICE,官方调价时改这里。
| 模型 | 缓存命中 | 缓存未命中 | 输出 |
|---|---|---|---|
deepseek-flash(DeepSeek-V4.1-Flash) | 0.02 / 0.04 | 1 / 2 | 4 / 8 |
deepseek-v4-pro(V4 Pro) | 0.15 / 0.30 | 4.5 / 9.0 | 13.5 / 27.0 |
旧模型名
deepseek-v4-flash、deepseek-v4-flash-vision-exp仍可调用,按 Flash 价计费。
lib/index.js 是宿主本体、lib/accounting.mjs 是记账内核(定点金额运算 + 观测/校正账本)、assets/whale-widget.js 是前端本体;宿主改动(含记账内核)需重启 dsh web,仅前端改动硬刷新页面即生效。whale-widget-prompt.md。dsh plugin --profile web add link:. 后,改前端 → Ctrl+F5;改宿主 → 重启 dsh web。playTaskEndSound() 读的是①区全局音量、并附了可复用的补丁与两个预打版压缩包供对比。这两个都是真 bug(第二个是我顺着他的思路查出来的),0.3.17 已按"解析器 + 三态音量"的方式修复(比补丁覆盖面更广:音效组那条路也修了),并新增了一条 CI 检查专门拦这类"控件有值、没有消费方"的问题。感谢他的报告。lib/index.js 里用密钥哈希当账户标识、accounting.mjs 的 observeBalance / currentBook 只读 active 本)与数据佐证 —— 让这次能一次做实"数据没丢、只是没有入口"这个判断。0.3.16 据此修复(旧本日期照常显示并标注「已观测消费 · 历史账户」)。感谢他。GET /dsh-whale/wait.json 的数据形状 {ok, pending:{kind,id,ts}} 与主线最终方案一致;本 README 的 wait.json 路由说明即采纳其写法)。0.3.16 的提问/授权提示音效与常驻气泡按主线方案落地(四入口面板 / 每事件音量与试听 / 抢占置顶)。感谢他,也欢迎他继续参与这个项目的工程化改进。deepseekAccount 服务的推荐调用方式,以及三个集成坑:账户标识字符集、赠金要计入基准、服务可能不存在)由 GitHub 用户 @yybai25 在 #157 中给出完整规格与已在自己机器上验证过的参考实现;0.3.14 据此实现(只调 DSH 服务、不接触账号令牌)。感谢他的贡献。quota.json.windows、按窗口展示与紧凑重置倒计时、「订阅额度」模块的窗口选择)由 GitHub 用户 @ELFsay 提交(#99),已合入 main。感谢他的贡献。cordis.patch.yml + bundle 结构就来自这里);本项目代码基于 MIT License 开源,详见 LICENSE。
⚠️ assets/ 下的美术素材(图片 / 动图 / 音效)不在 MIT 覆盖范围内:它们由维护者提供或使用 AI 工具生成,按「原样(as-is)」随插件分发、仅供运行本插件使用,不授予再许可、也不声明为原创作品。逐项来源、元数据清理说明与权利主张(takedown)方式见 PROVENANCE.md。
277 followers · starred Sep 2026
230 followers · starred Aug 2026
507 followers · starred Aug 2026
98 followers · starred Oct 2026
DeepSeek Harness(DSH)一只住在 DSH 界面右下角的小鲸鱼娘,帮你盯着DeepSeek账户余额。QQ弹弹,支持拖拽吸附、左吸附翻转、数字滚动动画,随界面自动启用,建议直接喊来你的dsh安装
JavaScript
5,267
81 commits
updated Oct 11, 2026

DeepSeek Harness(DSH)Web 界面右下角的常驻挂件:小鲸鱼气泡图 + DeepSeek API 余额 + 今日已用 + 每轮对话消耗,并且泡泡内容可以完全自定义(点击序列、模块化排版、并列加权出泡、随机语句/随机图片)。标准 DSH bundle 插件,dsh plugin 一键安装,无需任何会话令牌。
⚠️ Codex 版小鲸鱼已迁至独立仓库 → https://github.com/Yang-huai406/Codex-Whale-Public(已安装用户无需重装;详见下方「两条分支怎么选」)
本仓库现在只维护一条产品线(main,同一个包同时支持 DSH Web 与官方桌面客户端)。按你要挂在哪里选:
| 你要挂在哪 | 用哪条分支 | 安装方式 |
|---|---|---|
| DSH Web 界面右下角(就是这个 README 描述的插件) | main(默认分支) | dsh plugin --profile web add dsh-whale-widget(推荐,装 npm 已发布版);也可以从本仓库装 dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget,但那样装的是 main 当前状态、不跟随已发布版本 |
| 官方桌面客户端(Electron)右下角 | main(同一个包) | ⚠️ 不能用 --profile web(桌面端读的是 desktop profile,CLI 也拒绝 --profile desktop)—— 在桌面端会话里让 DSH 自己装,见下方「官方桌面端(Electron 客户端)请先看这一节」 |
| Codex 桌面应用(跟随 Codex 窗口、无独立网页) | ⚠️ 已迁出本仓库 | 新仓库 · 最新版下载 · 已安装用户无需重装 Codex 版迁移公告:本次迁移保留了开发历史、历代版本与作者贡献,并清理了旧图片中的非必要元数据(贡献者致谢见文末「致谢」)。后续更新、问题反馈与版本发布都在新仓库;反馈问题时请注明版本、系统和复现步骤,勿上传密钥、完整配置或未脱敏日志。 |
⚠️ 两条线互不兼容:Codex 版不能用 dsh plugin … add 装进 DSH 网页,本仓库的插件也不能在 Codex 桌面里运行。
⚠️ 安装方式二选一、别混用(npm 名 / github:)—— 它们是同一个包名,先后安装会并存冲突;已经是 github: 装的,要换 npm 名请先 dsh plugin --profile web remove dsh-whale-widget。
DEEPSEEK_API_KEY;② DSH 账号登录态 —— 通过「设置 → 账号与余额」登录了 DeepSeek 账号、又没配 API key 时自动使用(不需要去 platform 建 key).dshw-usage-archive.json);金额按 8 位小数记账、显示保留两位{cost} 引用),入口:菜单 → 「音效与提示」→ 「全局设置」→ 展开「每轮消耗提示」→「编辑提示内容」deepseek-flash → DeepSeek-V4.1-Flash,旧名标注"同 V4.1 Flash")默认音效组 · 100%、自动关 180s · 叮~),点一行才展开该区的设置项(可同时展开多个)。每个音效都有独立音量,每行带「试听」;音效行左侧的 [✓] 决定该音效响不响(不响 = 仍可冒泡)。底栏 取消 / 恢复默认 / 保存 —— 面板内的改动只落内存,点「保存」才生效,点「取消」完整还原(「恢复默认」之后点取消同样能撤销)...,0 = 不截断)
{balance_ds},老配置里的模块照旧显示,无需重配);赠金({bonus_ds})与充值余额({recharge_ds})是单独拆出来的两个模块,取不到数时显示 —(真的为 0 才显示 0.00)v0.3.19-beta){cost});开关、自动关闭秒数、提示音量、任务结束音效与内容编辑入口都在「音效与提示 → 全局设置」面板的「每轮消耗提示」区(主菜单不再单列这一行){session} 会替换成当前对话名(读不到就显示「当前对话」,超长自动截断为 12 字符 + ...)。同一个未回答的提问只响一次(刷新页面也不会重复响)assets/minecraft-exp-orb.wav)与 A(assets/task-end-a.wav),也可选任意片段或音效组[✓] 决定「响不响」(不响 = 仍会冒泡提示)跟随按压音量 N%);一旦你拖过那个滑块,就按你设的值播(摘要只显示百分比)。这样既能"一个总音量管全局",也能单独压低某类提示音。角色 1 · 泡泡图 2、音效组 3 · 片段 4),点一行才展开明细;「导入片段」在音频那一区里;收起/展开时会顺带停掉正在试听的那一段petpet、money1 两张图,也可上传 png/gif,供图片/随机图片模块使用除内置的 DeepSeek 余额外,可在「小鲸鱼记账 → 模型」里添加任意厂商;每个模型独立配置余额预警 / 今日预算 / 额度:
probeUrl 探活验证 key,余额显示「—」,今日已用按会话事件估算):硅基流动(CN / EN)、火山方舟 Ark、OpenAI、Anthropic Claude、Google Gemini、xAI Grok、Groq、Mistral AI、Together AI、Fireworks AI、DeepInfra、Cerebras、阿里云百炼(通义千问)、百度千帆(文心)、腾讯混元、讯飞星火、魔搭 ModelScope、本地模型(Ollama / LM Studio)OPENROUTER_API_KEY);删除模型会连带清理该模型的额度模块与设置a.b[0].c 与 scale 乘数);点「测试连通性」可先验证 keyinput + cacheRead + output,推理 token 已含在 output 内,跨天保留),也可切换手动填写;支持「不重置 / 每日 / 每月」kind:'quota' 模板):直接读厂商官方接口的「窗口已用% + 重置时间」,与上面按会话统计的额度互补。支持一个接口返回多个窗口(目前 OpenCode Go 为 5h / 周 / 月三窗口),逐窗口展示已用百分比与各自的紧凑重置倒计时;模板用 quota.json.windows 描述各窗口的字段路径{balance}、{today}、{quota}、{quota_used}、{quota_left}、{quota_total}、{quota_reset}说明:并非所有厂商都提供「用 API key 查余额」的接口。硅基流动的余额接口已被官方下线(2026-08-11 更新公告:
/user/info自 2026-08-14 起停止服务,「后续将适时提供替代 API」,截至发版仍未见替代接口),火山方舟的余额 / 用量与阿里云百炼 / 百度千帆 / 腾讯混元一样属于各家云平台 AK/SK 签名的 OpenAPI,OpenAI / Anthropic / Gemini / xAI / Groq / Mistral / Together / Fireworks / DeepInfra / Cerebras 则根本没有公开的余额查询接口 —— 这些模板统一是「无余额接口 + 探活验证 key」,今日已用按会话事件估算。厂商的订阅额度接口(智谱 / Kimi Coding / MiniMax Coding / OpenCode Go)只对订阅套餐账号有效:Token 资源包账号调用智谱接口会返回「当前用户不存在coding plan」,这种情况请用上面的「额度(订阅 / 资源包)」自动统计。模板只提供默认值:选完模板后可以随意改写接口地址与字段路径;留空的字段会继续沿用模板默认值(不会因为留空而失效)。
ℹ️ 先分清楚:这一节说的是本插件读取本机 Codex 会话日志的能力(属于
main,就是把 Codex 当数据源), 与**「Codex 版小鲸鱼」挂件**(跟随 Codex 窗口的那个端口)是两回事 —— 后者已迁出本仓库,见「两条分支怎么选」里的「Codex 版迁移公告」。
⚠️ 限制:Codex 支持目前只是部分接口适配,本挂件不能安装到 Codex 里(它是 DSH Web 插件,Codex 仅作为数据来源被读取);订阅窗口没有真实订阅样本可验证,遇异常欢迎反馈。
挂件可以直接读本机 Codex 的会话日志统计 token 用量 —— 因此不限于 DSH 内部,你在 Codex CLI / 桌面版里跑的消耗也能看到。
$CODEX_HOME/sessions/YYYY/MM/DD/rollout-*.jsonl(含 archived_sessions/),明文 JSONL;只读本机文件、不联网、不需要密钥,也不会写入 ~/.codextotal_token_usage)的差值累加,天然避免同一轮多条记录被重复计数;模型归属由 turn_context.payload.model 判定;按天 + 模型聚合,带增量缓存($DSH_HOME/.dshw-codex.json,只存聚合与文件偏移)Codex 今日 x · 近7天 y tokens;模型子菜单显示今日 / 本月 / 累计 / 近7天与会话文件数;「测试」按钮直接返回本地统计rate_limits 带窗口快照,有 ChatGPT 订阅时子菜单自动追加 5h 已用 x% · 2小时30分后重置 | 周 已用 y% · 3天后重置(字段名已做容错;API-key 计费或无订阅时该行不显示)dsh-whale-widget/
├── package.json # DSH bundle 插件元数据(dsh.bundle.patch 指向 cordis.patch.yml;顶层 icon 指向 icon.png)
├── icon.png # 插件列表图标(256×256 PNG,含透明;宿主读成 data URL 塞进 meta.icon,必须是正方形)
├── README.md # 本文件
├── cordis.patch.yml # 插件挂载声明
├── lib/
│ ├── index.js # 宿主侧插件本体(路由 + 记账 + 音效/图片/角色服务)
│ └── accounting.mjs # 记账内核(定点金额运算 + 余额观测/校正账本)
├── assets/
│ ├── whale-widget.js # 前端挂件本体(由宿主按 mtime 热读取)
│ ├── DSH2.png # README 顶部展示图
│ ├── DSniang1.png # 小鲸鱼本体(cut-out,气泡由代码绘制)
│ ├── DSniang02.png # 备用整图(兼容旧版手动安装路径)
│ ├── rua.gif # 随机台词/撒娇动图(可选)
│ ├── Ya1.mp3 / Ya2.mp3 # 预置音效「小黄鸭」按压 / 松开
│ ├── D1.mp3 / D2.mp3 # 预置音效「音效1」按压 / 松开
│ ├── minecraft-exp-orb.wav # 任务结束音内置默认音效(Minecraft·经验球)
│ ├── task-end-a.wav # 任务结束音内置预设(A)
│ ├── bubble-petpet.gif # 内置泡泡图:petpet
│ └── bubble-money1.gif # 内置泡泡图:money1(余额预警默认内容的配图)
└── whale-widget-prompt.md # 完整规格/维护提示词(面向二次开发)
运行时数据(都放在 $DSH_HOME,默认 ~/.dsh;用环境变量 DSH_HOME 可以改到别处):
| 文件 / 目录 | 用途 |
|---|---|
.dshw-size.json | 挂件外观与开关(缩放、音量、音效组、峰值样式、吸附相关等) |
.dshw-usage.json | 记账账本 + 按日余额观测/校正摘要 + 用量设置(任务结束音、余额预警、今日预算、每轮消耗提示内容,以及 events:按压 / 每轮消耗 / 提问 / 授权四个事件的音效选择、独立音量、冒泡配置;每轮消耗的自动关闭秒数存在 .dshw-size.json 的 turnCostCloseMs) |
.dshw-usage.json.before-recharge-fix.bak | 旧格式账本备份(0.3.1 首次写入旧账本前自动创建;已存在则不覆盖) |
.dshw-turn.json | 每轮消耗的 seq(避免热重载后前端把新轮次当旧轮次) |
.dshw-bubble.json | 自定义泡泡配置(点击序列 + 模块库 + 点按角色推进队列开关) |
.dshw-api.json | 自定义 API 模型注册表(厂商 / 凭据名 / 接口字段 / 自定义单价 / 额度与用量累计;不含密钥) |
.dshw-usage-archive.json | 账本归档(超过保留期的逐轮明细与逐日汇总;明细 90 天/2 万条、逐日 365 天) |
.dshw-codex.json | Codex 本地会话统计缓存(按天/模型聚合 + 文件偏移;不含任何凭据) |
whale-roles/ | 自定义角色图 + roles.json 索引 |
whale-audio/ | 音频片段 <id>.wav + audio.json 索引(音效组/片段) |
whale-bubble-imgs/ | 泡泡图库图片 + bubble-imgs.json 索引 |
桌面端读的不是 web profile。 官方桌面客户端用的是 desktop profile(%USERPROFILE%\.dsh\profiles\desktop),而 dsh plugin 命令行按设计拒绝碰它:
error: profile "desktop" is managed exclusively by the Electron application
所以下面「方式 A~D」里的 --profile web 命令对桌面端不适用 —— 按它装完,插件落在 web profile 里,而桌面窗口读的是 desktop profile,一个字也读不到。表现就是「右下角什么都没有(连 ☰ 也没有)、控制台也不报错」。
桌面端的正确装法:明确使用当前宿主内置的 plugin_manager。
在桌面客户端的会话里可直接说:
请使用当前桌面端内置的
plugin_manager安装dsh-whale-widget。先核对当前 profile 和是否已有同名插件;已有安装时先报告来源与版本。按该工具支持的操作完成后,告诉我安装结果及是否需要重启。
plugin_manager 的作用域是当前 profile(桌面端为 desktop),由宿主使用其自带的包管理器完成安装与挂载登记。需要固定版本时,将安装规格改成 dsh-whale-widget@<目标版本>。这条说明用于减少安装前后的无关探索(#194);不需要自行构造认证 cookie、调用底层 RPC 或改写宿主管理的 profile 文件。工具不可用或操作不受支持时,先说明缺少哪项宿主能力,不绕过桌面端限制改用 --profile web。
首次安装与升级的生效方式(#162):
"application":"applied",但这不保证当前窗口已显示挂件。若装完没有出现,完全退出客户端(含系统托盘)后重新打开,再按下方两条自检排查。"restart-required" 时完全退出并重开,随后重新核对实际版本。0.1.7-rc.2,页面没有升级入口,重新“添加”带版本的同名包也可能只返回“已安装”。先检查该宿主内置工具是否支持同来源更新;若工具也不支持,保留当前安装,按宿主支持的升级方案处理。只有明确需要卸载再安装或迁移来源时,才先保留原来源、精确版本和用户数据的恢复办法;不要把卸载、删除依赖目录/锁文件当作通用更新步骤。命令行侧的 dsh web 使用自己的 web profile:更新后重启宿主,再在浏览器按 Ctrl+F5。
装完怎么自检(两条分别对应宿主半区与客户端半区):
%USERPROFILE%\.dsh\.dshw-turn.json 存在,且 seq 随对话递增;%APPDATA%\@deepseek-ai\dsh-desktop\Local Storage\leveldb 里出现 dshw-pos / dshw-last-seq —— 这两个键只有挂件前端会写。桌面端界面里看不到插件版本号时,可以看 %USERPROFILE%\.dsh\profiles\desktop\package.json 的 dsh.profile.bundles 和同目录的 pnpm-lock.yaml。
下面方式 A~D 都是 Web(
dsh web) 的安装方式。
适用于别人直接发给你一个 zip,或你手上已有一份解压好的插件目录(目录里应有 package.json、cordis.patch.yml、lib/、assets/、README.md)。
# 1) 若是 zip:先解压到一个固定、以后不会移动或删除的目录(不要放临时目录/下载目录)
# 例:D:\Plugins\dsh-whale-widget
# 要安装的是「包含 package.json 的那一层」,不要多套一层同名目录
# 2) 确认关键文件都在(缺 assets/ 会导致没图、没声)
Test-Path "D:\Plugins\dsh-whale-widget\package.json",
"D:\Plugins\dsh-whale-widget\lib\index.js",
"D:\Plugins\dsh-whale-widget\assets\whale-widget.js"
# 3) 如果之前从 GitHub / npm 装过同名插件,先卸载避免版本冲突
dsh plugin --profile web remove dsh-whale-widget
# 4) 用绝对路径安装(路径含空格要加引号)
dsh plugin --profile web add link:D:\Plugins\dsh-whale-widget
说明:
link: 是软链安装:源目录里的文件改了立即生效;但安装后不能移动/重命名该目录,移动了要重新 add 一次dsh plugin --profile web add file:D:\Plugins\dsh-whale-widget(此后源目录再改不会同步,需重新 add)assets/minecraft-exp-orb.wav、assets/task-end-a.wav 等内置资源;删掉 assets 里的文件会让对应功能静默降级(无图/无声)dsh web,再 F5 刷新浏览器无需本地克隆,一条命令安装:
dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget
说明:
$env:http_proxy="http://<ip>:<port>"; $env:https_proxy="http://<ip>:<port>"; $env:all_proxy="socks5://<ip>:<port>"; dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget
dsh web,再 F5 刷新浏览器在仓库根目录(package.json 所在目录)执行:
dsh plugin --profile web add link:.
说明:
dsh plugin 会把参数转发给 pnpm,并在成功后自动把 dsh-whale-widget 加入 dsh.profile.bundleslink:. 表示链接当前目录(仓库根目录本身就是插件包)。如果仓库在别处,用绝对路径:
dsh plugin --profile web add link:D:\你的路径\DeepSeek-Balance-Whale-Widget
link:.\dsh-whale-widget——仓库里没有 dsh-whale-widget/ 子目录,这样会安装成普通依赖而非插件dsh web,再 F5 刷新浏览器add link:<新路径>;若提示冲突,先 dsh plugin --profile web remove dsh-whale-widget 再 adddsh plugin --profile web add dsh-whale-widget
plugin_manager 提示)请帮我安装插件 dsh-whale-widget。可能的来源有两种:GitHub 仓库
MeteorNOX/DeepSeek-Balance-Whale-Widget,或者我本地已经有这个插件的「完整资源包」。
先确认运行形态:如果当前是官方桌面客户端,请使用宿主内置 plugin_manager,
不要执行下面的 Web 命令,也不要自行构造认证/RPC或修改 desktop profile。
以下步骤仅用于 dsh web:
1. 确认 DSH 安装器使用的 pnpm 可用;若提示找不到 pnpm,先报告安装器所用路径和版本,
按该 DSH 版本的安装说明处理,不直接假定需要全局安装或重装插件。
2. 在 Web profile 安装(按我实际拿到的来源任选一种):
【来源一:从 GitHub 安装】
dsh plugin --profile web add github:MeteorNOX/DeepSeek-Balance-Whale-Widget
或从本地 git 仓库链接安装:
dsh plugin --profile web add link:<仓库绝对路径>
(注意:仓库根目录就是插件包,不要写成 link:.\dsh-whale-widget 这种带子目录的路径)
【来源二:我本地已有完整资源包(zip 或已解压目录)】
先确认「完整资源包」长什么样:一个目录,里面应当有
package.json、cordis.patch.yml、lib/index.js、
assets/(含 whale-widget.js、DSniang1.png、Ya1.mp3、minecraft-exp-orb.wav、task-end-a.wav 等)、README.md
然后按下面做:
a) 如果给我的是 zip:先解压到一个**固定、以后不会移动或删除**的目录,例如
D:\Plugins\dsh-whale-widget
不要解压到临时目录/下载目录/会被清理的位置;也不要多套一层——
要安装的是**包含 package.json 的那一层**,不是外面那个同名压缩包目录
b) 检查文件完整性(任意一条 False 就先告诉我,不要继续装):
Test-Path "<资源包目录>\package.json"
Test-Path "<资源包目录>\lib\index.js"
Test-Path "<资源包目录>\assets\whale-widget.js"
并确认 package.json 里 name 是 dsh-whale-widget、带 dsh.bundle.patch 字段
c) 如果之前从 GitHub / npm 装过同名插件,先卸载避免版本冲突:
dsh plugin --profile web remove dsh-whale-widget
d) 用**绝对路径**安装(路径含空格要加引号):
dsh plugin --profile web add link:<资源包目录>
link: 是软链安装:源目录改了立即生效,但安装后不能移动/重命名该目录;
移动后必须重新执行一次 add。若想按拷贝安装可用:
dsh plugin --profile web add file:<资源包目录>
(file: 以后源目录改动不会同步,需要重新 add)
3. 如果报 pnpm 阻止构建脚本(allowBuilds 相关),先确认被阻止的是哪个包。
本插件没有安装/编译脚本;不要因此放行所有依赖的构建脚本,按具体报错处理。
4. 重启 dsh web,然后 F5 刷新浏览器
安装后验证:
- dsh --profile web --dump-config 应该能看到 dsh-whale-widget 在 bundles 里
- curl http://127.0.0.1:3080/dsh-whale/balance.json 应返回 200 JSON(含 totalBalance)
- curl http://127.0.0.1:3080/dsh-whale/widget.js 应返回 200 JS
- curl "http://127.0.0.1:3080/dsh-whale/audio-fragment.wav?id=exp_orb" 应返回 200 audio/wav
- curl "http://127.0.0.1:3080/dsh-whale/audio-fragment.wav?id=end_a" 也应返回 200 audio/wav
(用来确认资源包里的内置音效已随包就位;若是 404 说明 assets/ 不完整)
另外请检查 DSH 凭据里是否配置了 DEEPSEEK_API_KEY(没有就提示用户配置;如果用户是用 DSH 账号登录的,较新 DSH 上不配 key 也能取余额,**别把"没 key"当成故障**)。
余额有两种取数方式(API key 优先,两者互不干扰):
DEEPSEEK_API_KEY(推荐):DeepSeek API 密钥,用于拉取余额(GET https://api.deepseek.com/user/balance)。在 DSH 凭据服务里配置(凭据管理界面 / .dsh/.credentials.yaml)。0.1.7-rc.2)才有这个服务;老版本、未登录、或账号没有余额钱包时,会回到下面的「未配置」提示。不需要
DEEPSEEK_PLATFORM_TOKEN。早期版本的"实时·令牌"模式已下线,今日已用统一由小鲸鱼记账(余额差 + 会话事件)计算,零令牌开箱即用。
插件会把凭据交给谁、以及谁能改这件事的规则:
{base} 指向你自己填的地址),插件默认不会把凭据发过去,而是返回一条明确提示。
127.0.0.1 / localhost / [::1],一律 403。
DSHW_ADMIN_HOSTS=192.0.2.10:3080,myhost.lan(逗号分隔,可带端口;默认空)。https://user:pass@host/),凭据名只允许字母、数字与下划线。添加自定义模型时,还会按需用到各自厂商的凭据名(都可不配,用到哪个配哪个):
| 凭据名 | 用途 |
|---|---|
OPENROUTER_API_KEY | OpenRouter 余额(/api/v1/credits) |
MOONSHOT_API_KEY | Kimi / Moonshot 大陆站余额(人民币) |
MOONSHOT_INTL_API_KEY | Kimi / Moonshot 国际站余额(美元,独立账号体系) |
SILICONFLOW_API_KEY | 硅基流动 /v1/models 探活 |
ARK_API_KEY | 火山方舟 /api/v3/models 探活 |
ZHIPU_API_KEY | 智谱(订阅额度接口 / Coding 端点) |
OPENCODE_GO_API_KEY | OpenCode Go 订阅额度(opencode.ai/zen/go/v1/usage,鉴权为 Authorization: Bearer <key>) |
CUSTOM_API_KEY | 自定义 HTTP / OpenAI 兼容中转站 |
⚠️ 自定义模型面板里的「凭据名」决定密钥写进哪个 ref。换厂商时请确认这一栏跟着模板变了,否则新密钥会写进上一家厂商的凭据名里(覆盖掉原来的 key)。v679 起新增模型会自动跟随模板。
dsh plugin --profile web remove dsh-whale-widget
如果你之前按旧方式手动安装过(复制 whale-balance.mjs + 改 cordis.patch.yml),先清理:
$web = "$env:USERPROFILE\.dsh\profiles\web"
Remove-Item "$web\whale-balance.mjs" -ErrorAction SilentlyContinue
Remove-Item "$web\whale-balance.cjs" -ErrorAction SilentlyContinue
Remove-Item "$web\DSniang1.png" -ErrorAction SilentlyContinue
Remove-Item "$web\DSniang02.png" -ErrorAction SilentlyContinue
然后编辑 $web\cordis.patch.yml,删除这段旧补丁:
- insert:
- id: whale-balance-widget
name: ./whale-balance.mjs?v=1
如果里面只有这段,直接改成:
[]
清理后再执行上面的安装命令。
dsh --profile web --dump-config | Select-String -Pattern "whale"
curl http://127.0.0.1:3080/dsh-whale/balance.json
curl http://127.0.0.1:3080/dsh-whale/size.json
curl http://127.0.0.1:3080/dsh-whale/widget.js
curl http://127.0.0.1:3080/dsh-whale/image.png
curl http://127.0.0.1:3080/dsh-whale/audio.json
/dsh-whale/balance.json → 200 JSON,含 {ok:true, totalBalance, currency, todayUsage}/dsh-whale/size.json → GET 返回配置;PUT 写入/dsh-whale/widget.js → 200 JS(前端挂件本体)/dsh-whale/image.png → 200 image/png/dsh-whale/audio.json → 200,含 groups / fragments(其中内置片段 exp_orb = Minecraft·经验球、end_a = A)/dsh-whale/audio-fragment.wav?id=exp_orb → 200 audio/wav(内置任务结束音;无需用户导入)/dsh-whale/audio-fragment.wav?id=end_a → 200 audio/wav(内置任务结束音 A)/dsh-whale/wait.json → 200 JSON,含 {ok:true, pending};pending 为当前挂起的「提问 / 授权」({kind:'question'|'approval', id, ts})或 null —— 这是「提问提示 / 授权提示」音效与常驻气泡的数据源(默认每秒轮询一次)/dsh-whale/about.json → 200 JSON:菜单底部版号那行点开后的「关于 / 自检」面板数据源(版本、通道、文件路径与时间、数据落点、记账/余额/Codex 状态;路径已脱敏,点开才请求)/dsh-whale/update-check.json → 200 JSON:检查更新({ok, current, latest, hasUpdate, source});点了才联网,镜像优先(npmmirror → jsdelivr → unpkg → npmjs)+ npm view 兜底,宿主侧 10 分钟缓存⚠️ 关于上面这些
curl:全部 26 个/dsh-whale/*路由都已接入 DSH 浏览器信任栅栏(connection.requestRejection)。 因此不带会话凭据的裸curl会返回 401(伪造Host头则是 403)—— 这是预期行为,不是接口坏了。 想验证接口是否存活,看返回 401/403 即说明路由已注册且栅栏在工作;在浏览器里访问同一条路径(带会话)才是 200。 另外自 0.3.15 起,写请求(POST/PUT/PATCH/DELETE)还必须是本机来源(Host 为127.0.0.1/localhost/[::1]),否则 403 —— 详见上方「安全边界」。
exit 1 / pnpm failed:这些是汇总错误,不能据此认定插件代码有错,也不能直接归因网络。若明确出现“找不到 pnpm / 不是内部或外部命令”(#145),先检查宿主安装器使用的包管理器与启动环境;桌面端尤其要区分宿主自带工具和终端 PATH 中的工具。诊断时请提供:
web 或 desktop),首次安装还是升级。.plugin-manager/logs/operation-*/pnpm.log,再对照 hub.log;同时说明是否使用代理/镜像、失败请求的目标域名和状态码。ERR_PNPM_ADDING_TO_ROOT、Invalid time value、Failed to fetch 应分别定位,不按同一原因处理。node_modules、锁文件或修改全局 registry。相关issue由报告者验证效果后决定是否关闭。dsh web):确认安装命令成功;dsh --profile web --dump-config 里能看到 dsh-whale-widget;重启 dsh web 后 F5。desktop profile,不能用 --profile web(而 --profile desktop 会被 CLI 拒绝,这是设计如此)。正确入口见上面「官方桌面端(Electron 客户端)请先看这一节」,并用那里的两条自检判断是「没装到位」还是「装了但没渲染」。新装也建议重开一次客户端(issue #162:热生效不一定够)。/dsh-whale/*)的访问校验:默认只接受回环地址(127.0.0.1 / localhost / [::1])的请求,并拒绝跨站标记(Sec-Fetch-Site: cross-site)与 Origin 和 Host 不同源的请求 —— 这是防「恶意网页读写本机接口」的信任栅栏(issue #92 / #136)。如果你把 dsh web 放在反向代理或局域网地址后面,请用环境变量声明允许的 Host(逗号分隔,可带端口),否则会被 403:
DSHW_TRUSTED_HOSTS=dsh.example.com,10.0.0.5:3080 dsh web
assets/ 完整(DSniang1.png、*.mp3、minecraft-exp-orb.wav 等);缺失时相关功能静默降级。选项 → 文件类型 / 站点排除,把 127.0.0.1 与 localhost 加进去;其它管理器同理,关键词是"排除本机地址 / 不监控该站点")。关掉挂件音效开关并不能消除弹窗 —— 音效元素在页面初始化时就会建立。[✓](不勾 = 静音、但照旧冒泡),再在下拉里选一个音效;不需要提示就把该区入口行左边的总开关 [✓] 取消。(入口行右侧的摘要会实时显示当前配置。).dshw-usage.json)被外部改坏或结构异常,插件拒绝覆盖它以免丢数据。先把它备份改名让插件重建,再按需用「余额校正」补账。403 / 在别的机器上改了配置不生效:0.3.15 起写操作只能在运行 DSH 的那台机器上、用 127.0.0.1(本机地址)打开界面进行。从局域网或反向代理访问时,读没问题、写会被拒。需要远端管理就用 DSHW_ADMIN_HOSTS 显式授权那台机器(见「凭据 → 安全边界」)。--:先等一次成功的余额观测;统计从该观测时刻开始,起点之前的消费不在此区间内。[✓] 是勾上的(入口行右侧摘要会直接显示 已关闭 或当前配置);一轮对话要完整结束(turn/end)才结算。余额变化泡泡与消耗泡泡抢层时,提醒会退化为居中卡片。{cost});同一区里能设自动关闭秒数、提示音量与任务结束音效。A,另有内置的 Minecraft·经验球可选);到「音效与提示 → 全局设置」→ 展开「每轮消耗提示」,确认「任务结束音」那行左侧的 [✓] 是勾上的(取消勾选 = 静音)。若自定义片段文件被删,会回退/静音。跟随按压音量 N% 变成 N%)。没拖过时它跟随①区「按压音效」的音量 —— 摘要里会写明,滑块也显示实际生效值。想让某类提示更轻就把自己的滑块调小;想整体轻就调①区。点「恢复默认」会把这几条都退回"跟随①区"。(0.3.17 之前这个滑块确实不生效,是本版修好的。)⚠ 设置保存失败:<原因>(例如数据目录只读、接口被拦)。看到这条提示说明这次改动没有落盘,请按原因处理后再保存一次。? 圈圈里。.dshw-usage.json 的 accounting.books 里。当前版本已让界面把历史本里的日期正常显示(标注「已观测消费 · 历史账户」),并在「小鲸鱼记账」面板顶部提示「检测到 N 个记账本」;两个本不会被相加(插件无法判断两次是不是同一个账户),但同一天的明细可以在该面板的「每日与逐条明细」里逐日查看。whale-widget.js;仍不行请反馈浏览器型号。assets/whale-widget.js 由宿主按 mtime 热读取,硬刷新(Ctrl+F5)即可;改了宿主 lib/index.js 必须重启 dsh web。deepseek-flash 即 DeepSeek-V4.1-Flash,旧名 deepseek-v4-flash / -vision-exp 现在也由同一颗 V4.1-Flash 提供并按 Flash 计价(面板里已加标注)。金额按 CNY / 百万 tokens 计,[空闲时段, 高峰时段];高峰 = 工作日 9:00–12:00、14:00–18:00(北京时间),空闲价为高峰价的一半;2026-08-23 起周末全天按谷价。表在 lib/index.js 顶部 PRICING / BASE_PRICE / PRO_PRICE,官方调价时改这里。
| 模型 | 缓存命中 | 缓存未命中 | 输出 |
|---|---|---|---|
deepseek-flash(DeepSeek-V4.1-Flash) | 0.02 / 0.04 | 1 / 2 | 4 / 8 |
deepseek-v4-pro(V4 Pro) | 0.15 / 0.30 | 4.5 / 9.0 | 13.5 / 27.0 |
旧模型名
deepseek-v4-flash、deepseek-v4-flash-vision-exp仍可调用,按 Flash 价计费。
lib/index.js 是宿主本体、lib/accounting.mjs 是记账内核(定点金额运算 + 观测/校正账本)、assets/whale-widget.js 是前端本体;宿主改动(含记账内核)需重启 dsh web,仅前端改动硬刷新页面即生效。whale-widget-prompt.md。dsh plugin --profile web add link:. 后,改前端 → Ctrl+F5;改宿主 → 重启 dsh web。playTaskEndSound() 读的是①区全局音量、并附了可复用的补丁与两个预打版压缩包供对比。这两个都是真 bug(第二个是我顺着他的思路查出来的),0.3.17 已按"解析器 + 三态音量"的方式修复(比补丁覆盖面更广:音效组那条路也修了),并新增了一条 CI 检查专门拦这类"控件有值、没有消费方"的问题。感谢他的报告。lib/index.js 里用密钥哈希当账户标识、accounting.mjs 的 observeBalance / currentBook 只读 active 本)与数据佐证 —— 让这次能一次做实"数据没丢、只是没有入口"这个判断。0.3.16 据此修复(旧本日期照常显示并标注「已观测消费 · 历史账户」)。感谢他。GET /dsh-whale/wait.json 的数据形状 {ok, pending:{kind,id,ts}} 与主线最终方案一致;本 README 的 wait.json 路由说明即采纳其写法)。0.3.16 的提问/授权提示音效与常驻气泡按主线方案落地(四入口面板 / 每事件音量与试听 / 抢占置顶)。感谢他,也欢迎他继续参与这个项目的工程化改进。deepseekAccount 服务的推荐调用方式,以及三个集成坑:账户标识字符集、赠金要计入基准、服务可能不存在)由 GitHub 用户 @yybai25 在 #157 中给出完整规格与已在自己机器上验证过的参考实现;0.3.14 据此实现(只调 DSH 服务、不接触账号令牌)。感谢他的贡献。quota.json.windows、按窗口展示与紧凑重置倒计时、「订阅额度」模块的窗口选择)由 GitHub 用户 @ELFsay 提交(#99),已合入 main。感谢他的贡献。cordis.patch.yml + bundle 结构就来自这里);本项目代码基于 MIT License 开源,详见 LICENSE。
⚠️ assets/ 下的美术素材(图片 / 动图 / 音效)不在 MIT 覆盖范围内:它们由维护者提供或使用 AI 工具生成,按「原样(as-is)」随插件分发、仅供运行本插件使用,不授予再许可、也不声明为原创作品。逐项来源、元数据清理说明与权利主张(takedown)方式见 PROVENANCE.md。
277 followers · starred Sep 2026
230 followers · starred Aug 2026
507 followers · starred Aug 2026
98 followers · starred Oct 2026