From ac56c4743da15b34227a1db2e70abcf6378bed0a Mon Sep 17 00:00:00 2001 From: GeekRicardo Date: Tue, 18 Aug 2026 18:49:42 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=8F=92=E4=BB=B6=E6=9B=B4=E5=90=8D?= =?UTF-8?q?=E4=B8=BA=20dsh-balance=EF=BC=8CREADME=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=9F=A9=E9=98=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 目录/包名 deepseek-balance → dsh-balance(cordis.patch.yml、dsh.plugin.json、 install.sh、client 加载 id、host 日志标签同步更新) - README 增加支持的供应商表格(provider/供应商/展示/密钥/接口) --- README.md | 47 ++++++++++++++++++++++++----------------------- cordis.patch.yml | 8 ++++---- dsh.plugin.json | 4 ++-- install.sh | 14 +++++++------- lib/client.js | 8 ++++---- lib/index.js | 12 ++++++------ package.json | 8 ++++---- 7 files changed, 51 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index b543b9d..eb39371 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,35 @@ -# deepseek-balance +# dsh-balance -DeepSeek Harness web 插件:在**输入框下方状态栏**展示当前供应商的余额/用量,按 **provider** 实时切换。 +DeepSeek Harness web 插件:在**输入框下方状态栏**展示当前供应商的余额/用量,按 **provider** 实时切换(2 秒轮询),余额/用量 5 分钟缓存。 -| 当前模型 provider | 展示内容 | 数据源 | -| --- | --- | --- | -| `deepseek`(DeepSeek 官方) | `● 本会话 ¥X.XX · ● 余额 ¥465.xx` | `DEEPSEEK_API_KEY` → `GET api.deepseek.com/user/balance` | -| `kimi-coding`(Kimi For Coding) | `5小时 3% 4h15m · 7天 31% 6d0h · 5分钟前` | `KIMI_CODING_API_KEY` → `GET api.kimi.com/coding/v1/usages` | -| `opencode-go`(OpenCode Go) | `5小时 2% 3h50m · 7天 9% 4d2h · 30天 26% 22d1h · 5分钟前` | `OPENCODE_GO_API_KEY` → `GET opencode.ai/zen/go/v1/usage` | -| 其他 provider | 不显示(返回 null) | — | +## 支持的供应商 -## 实时性(v2+ 优化) +| provider | 供应商 | 展示内容 | 密钥 | 接口 | +| --- | --- | --- | --- | --- | +| `deepseek` / `deepseek-official` | DeepSeek 官方 | `● 本会话 ¥X.XX · ● 余额 ¥465.46` | `DEEPSEEK_API_KEY` | `GET api.deepseek.com/user/balance` | +| `kimi-coding` | Kimi For Coding | `5小时 3% 4h15m · 7天 31% 6d0h · 5分钟前` | `KIMI_CODING_API_KEY`(兼容 `KIMI_CODE_API_KEY`/`KIMI_API_KEY`) | `GET api.kimi.com/coding/v1/usages` | +| `opencode-go` | OpenCode Go | `5小时 8% 3h · 7天 3% 5d0h · 30天 1% 27d · 5分钟前` | `OPENCODE_GO_API_KEY`(兼容 `OPENCODE_API_KEY`) | `GET opencode.ai/zen/go/v1/usage` | +| 其他 provider | — | 不显示(返回 null) | — | — | -- **2 秒轮询**:切换模型/切换对话后最多 2 秒更新,不再等 60 秒。 -- **按 provider 判断**:用 `agentDefaultModel.currentSelection()`(当前选中,切换即更新),不再用「最近一次请求的模型」,避免切了模型但没发消息时读数停留在旧模型。 +> `deepseek` 与 `deepseek-official` 是 DeepSeek 官方的两条 provider 路由(DSH 自带 `dsh-llm-deepseek` 与 pi-ai catalog),余额接口相同,都展示官方余额。 + +## 实时性 + +- **2 秒轮询**:切换模型/切换对话后最多 2 秒更新。 +- **按 provider 判断**:用 `agentDefaultModel.currentSelection()`(当前选中,切换即更新),不依赖「最近一次请求的模型」。 - **5 分钟缓存**:余额/用量实际查询每 5 分钟一次(host 端按 provider 缓存),切走再切回强制刷新一次。 -- 切换对话:client 按 `sessionId` 变化重新加载,DeepSeek 的本会话花费按 session 分别累计。 +- 切换对话:client 按 `sessionId` 重新加载;DeepSeek 本会话花费按 session 分别累计(`llm/stream` token × models.dev 单价估算)。 ## 一键安装 ```bash -curl -fsSL https://raw.githubusercontent.com/GeekRicardo/deepseek-balance/main/install.sh | bash +curl -fsSL https://raw.githubusercontent.com/GeekRicardo/dsh-balance/main/install.sh | bash ``` 脚本做的事(可先 `--dry-run` 预览): -1. 在 `~/.dsh/profiles/web/package.json` 写入依赖 `"deepseek-balance": "github:GeekRicardo/deepseek-balance"`; -2. 把 `deepseek-balance` 追加进 `dsh.profile.bundles`; +1. 在 `~/.dsh/profiles/web/package.json` 写入依赖 `"dsh-balance": "github:GeekRicardo/dsh-balance"`; +2. 把 `dsh-balance` 追加进 `dsh.profile.bundles`; 3. `cd ~/.dsh/profiles/web && pnpm install`; 4. 校验 bundles 已注册,提示重启。 @@ -38,8 +42,8 @@ pm2 restart dsh-web # 若用 pm2 托管;否则用你的启动方式重启 ## 卸载 ```bash -# 1. 从 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 移除 "deepseek-balance" -# 2. 移除 dependencies 里的 "deepseek-balance" +# 1. 从 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 移除 "dsh-balance" +# 2. 移除 dependencies 里的 "dsh-balance" # 3. cd ~/.dsh/profiles/web && pnpm install # 4. 重启 DSH ``` @@ -47,24 +51,21 @@ pm2 restart dsh-web # 若用 pm2 托管;否则用你的启动方式重启 ## 前置条件 - DeepSeek Harness 已初始化 web profile(`~/.dsh/profiles/web` 存在)。 -- `~/.dsh/.credentials.yaml` 里配置对应供应商的密钥: - - DeepSeek:`DEEPSEEK_API_KEY` - - Kimi Coding:`KIMI_CODING_API_KEY`(也兼容 `KIMI_CODE_API_KEY` / `KIMI_API_KEY`,可选 `KIMI_CODE_BASE_URL` 覆盖) - - OpenCode Go:`OPENCODE_GO_API_KEY`(也兼容 `OPENCODE_API_KEY`) +- `~/.dsh/.credentials.yaml` 里配置对应供应商的密钥(见上表)。 - Node.js ≥ 20、pnpm 可用。 ## 工作原理 | 半区 | 职责 | | --- | --- | -| Host | 监听 `llm/stream` 按 session 累计 DeepSeek 官方模型的 token;经 `credentials` 读密钥,按 provider 查对应接口(DeepSeek `/user/balance`、Kimi `/coding/v1/usages`);5 分钟缓存;注册 `/deepseek-balance/status` HTTP route | +| Host | 监听 `llm/stream` 按 session 累计 DeepSeek 官方模型的 token;经 `credentials` 读密钥,按 provider 查对应接口;5 分钟缓存;注册 `/dsh-balance/status` HTTP route | | Client | 在 `conversation.composer.dock` 槽位渲染状态栏,`fetch` 轮询该 route(2s),按 provider 分发渲染 | ### DeepSeek 计费口径(重要) - DeepSeek 官方 API **不返回金额**,只返回 token 数。金额是 `token × 单价` 的**估算**,不是账单。 - 单价来自第三方 [models.dev](https://models.dev)(USD/百万 token),按模型前缀匹配;拉取失败回落到内置单价;汇率固定 7.2。 -- 本会话花费是**内存态**,从插件加载后的下一次模型调用开始累计,重启清零,不持久化。 +- 本会话花费是**内存态**,插件加载后开始累计,重启清零,不持久化。 ### Kimi Coding 用量口径(重要) diff --git a/cordis.patch.yml b/cordis.patch.yml index 15d150e..833562b 100644 --- a/cordis.patch.yml +++ b/cordis.patch.yml @@ -1,7 +1,7 @@ -# deepseek-balance bundle patch +# dsh-balance bundle patch # -# 安装后(dependencies + dsh.profile.bundles 均含 deepseek-balance), +# 安装后(dependencies + dsh.profile.bundles 均含 dsh-balance), # 启动时 profile boot 会合并本 patch,把插件行插入 host composition。 - insert: - - id: deepseek-balance - name: 'deepseek-balance' + - id: dsh-balance + name: 'dsh-balance' diff --git a/dsh.plugin.json b/dsh.plugin.json index de7f826..73d7a6c 100644 --- a/dsh.plugin.json +++ b/dsh.plugin.json @@ -1,9 +1,9 @@ { - "name": "deepseek-balance", + "name": "dsh-balance", "description": "DeepSeek Harness web 插件:状态栏展示 DeepSeek 余额与本会话估算花费", "version": "1.0.0", "entry": { - "name": "deepseek-balance", + "name": "dsh-balance", "inject": [] }, "client": { diff --git a/install.sh b/install.sh index 46e31cc..c201fbe 100755 --- a/install.sh +++ b/install.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash # ============================================================================= -# deepseek-balance 一键安装脚本(macOS / Linux / Windows Git Bash) +# dsh-balance 一键安装脚本(macOS / Linux / Windows Git Bash) # # 包只在 GitHub、不发 npm,因此本脚本直接把 github 依赖写进 profile 的 # package.json(dependencies + dsh.profile.bundles),再 pnpm install 拉取。 # 下次启动 DSH 时 profile boot 会读取包内 cordis.patch.yml 自动挂载插件行。 # # 用法: -# curl -fsSL https://raw.githubusercontent.com/GeekRicardo/deepseek-balance/main/install.sh | bash +# curl -fsSL https://raw.githubusercontent.com/GeekRicardo/dsh-balance/main/install.sh | bash # # 或下载后本地运行:bash install.sh [--dry-run] [--restart] # @@ -22,10 +22,10 @@ set -euo pipefail for arg in "$@"; do if [ "$arg" = "-h" ] || [ "$arg" = "--help" ]; then cat <<'EOF' -deepseek-balance 一键安装脚本 +dsh-balance 一键安装脚本 用法: - curl -fsSL https://raw.githubusercontent.com/GeekRicardo/deepseek-balance/main/install.sh | bash + curl -fsSL https://raw.githubusercontent.com/GeekRicardo/dsh-balance/main/install.sh | bash 或:bash install.sh [--dry-run] [--restart] --dry-run 只打印将要执行的操作,不写任何文件 @@ -40,8 +40,8 @@ done DSH_HOME="${DSH_HOME:-${HOME:-${USERPROFILE:-}}/.dsh}" PROFILE_DIR="$DSH_HOME/profiles/web" PKG_JSON="$PROFILE_DIR/package.json" -PKG="deepseek-balance" -GH_DEP="github:GeekRicardo/deepseek-balance" +PKG="dsh-balance" +GH_DEP="github:GeekRicardo/dsh-balance" DRY_RUN=false RESTART=false @@ -116,7 +116,7 @@ if ! node -e ' const bundles = p.dsh?.profile?.bundles ?? []; process.exit(bundles.includes(process.argv[2]) ? 0 : 1); ' "$PKG_JSON" "$PKG"; then - die "deepseek-balance 未出现在 dsh.profile.bundles 中,挂载未注册,请检查 pnpm install 输出。" + die "dsh-balance 未出现在 dsh.profile.bundles 中,挂载未注册,请检查 pnpm install 输出。" fi say "bundle 已注册:dsh.profile.bundles 包含 ${PKG}(下次启动自动挂载)" diff --git a/lib/client.js b/lib/client.js index 5322f3b..94b4858 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,5 +1,5 @@ window.__ModuleLoader__.load({ - id: "deepseek-balance", + id: "dsh-balance", factory: (require) => { var module = { exports: {} }; var exports = module.exports; @@ -7,7 +7,7 @@ window.__ModuleLoader__.load({ var inject = ["slots"]; - var STYLE_ID = "deepseek-balance-style"; + var STYLE_ID = "dsh-balance-style"; var cssText = ".dsb-readout { display: inline-flex; align-items: center; gap: 10px; font-size: 11px; line-height: 1.5; " + "color: var(--dsw-alias-label-secondary); white-space: nowrap; user-select: none; } " + @@ -272,7 +272,7 @@ window.__ModuleLoader__.load({ var alive = true; function load() { var qs = sessionId ? "?sessionId=" + encodeURIComponent(String(sessionId)) : ""; - fetch("/deepseek-balance/status" + qs) + fetch("/dsh-balance/status" + qs) .then(function (r) { return r.json(); }) @@ -312,7 +312,7 @@ window.__ModuleLoader__.load({ ensureStyle(); ctx.slots.inject("conversation.composer.dock", function () { return ctx.slots.register( - { name: "conversation.composer.dock", id: "deepseek-balance", order: 10, label: "余额" }, + { name: "conversation.composer.dock", id: "dsh-balance", order: 10, label: "余额" }, function (props) { return React.createElement(StatusReadout, { sessionId: props && props.sessionId }); }, diff --git a/lib/index.js b/lib/index.js index b5fd519..2fcb7f3 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,4 +1,4 @@ -// deepseek-balance — host face(DeepSeek + Kimi Coding 双供应商) +// dsh-balance — host face(DeepSeek + Kimi Coding 双供应商) // // 职责(全部进程内、可逆): // 1. 监听 `llm/stream` 瀑布事件,按 session 累计 DeepSeek 官方模型的 token 用量。 @@ -8,7 +8,7 @@ // provider = kimi-coding → 展示 Kimi Coding 订阅用量(KIMI_CODING_API_KEY, // GET https://api.kimi.com/coding/v1/usages,5 小时窗口 / 每周配额 / 刷新时间)。 // 4. 两类余额/用量都按 provider 做 5 分钟内存缓存;切走再切回强制刷新一次。 -// 5. 注册 /deepseek-balance/status HTTP route 供 client 2 秒轮询。 +// 5. 注册 /dsh-balance/status HTTP route 供 client 2 秒轮询。 const inject = ["webServer", "credentials", "subprocess"]; @@ -130,7 +130,7 @@ function apply(ctx) { try { recordUsage(options, usage); } catch (error) { - console.error("deepseek-balance: record usage failed", error); + console.error("dsh-balance: record usage failed", error); } } } @@ -206,7 +206,7 @@ function apply(ctx) { pricing.source = "live"; } } catch (error) { - console.error("deepseek-balance: fetch pricing failed, using fallback", error); + console.error("dsh-balance: fetch pricing failed, using fallback", error); } finally { pricingPromise = null; } @@ -583,7 +583,7 @@ function apply(ctx) { () => ctx.webServer.register({ kind: "exact", - path: "/deepseek-balance/status", + path: "/dsh-balance/status", handler: async (req, res) => { if (!isTrusted(req)) { writeJson(res, 403, { ok: false, error: "forbidden" }); @@ -598,7 +598,7 @@ function apply(ctx) { } }, }), - "deepseek-balance: /deepseek-balance/status route", + "dsh-balance: /dsh-balance/status route", ); } diff --git a/package.json b/package.json index 8c8f536..7662e1d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "deepseek-balance", - "version": "1.0.0", - "description": "DeepSeek Harness web 插件:输入框下方状态栏展示当前供应商的余额/用量 —— DeepSeek 官方账户余额 + 本会话估算花费,或 Kimi Coding 订阅用量(5小时/7天/刷新时间)。按 provider 判断、2 秒轮询实时切换。", + "name": "dsh-balance", + "version": "1.1.0", + "description": "DeepSeek Harness web 插件:输入框下方状态栏展示当前供应商的余额/用量 —— DeepSeek 官方余额 + 本会话花费、Kimi Coding 订阅用量(5小时/7天)、OpenCode Go 订阅用量(5小时/7天/30天)。按 provider 判断、2 秒轮询实时切换、5 分钟缓存。", "type": "module", "main": "lib/index.js", "exports": { @@ -36,7 +36,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/GeekRicardo/deepseek-balance" + "url": "https://github.com/GeekRicardo/dsh-balance" }, "peerDependencies": { "react": "^18.2.0"