chore: 插件更名为 dsh-balance,README 增加支持矩阵
- 目录/包名 deepseek-balance → dsh-balance(cordis.patch.yml、dsh.plugin.json、 install.sh、client 加载 id、host 日志标签同步更新) - README 增加支持的供应商表格(provider/供应商/展示/密钥/接口)
This commit is contained in:
@@ -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 用量口径(重要)
|
||||
|
||||
|
||||
+4
-4
@@ -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'
|
||||
|
||||
+2
-2
@@ -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": {
|
||||
|
||||
+7
-7
@@ -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}(下次启动自动挂载)"
|
||||
|
||||
|
||||
+4
-4
@@ -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 });
|
||||
},
|
||||
|
||||
+6
-6
@@ -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",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user