Bundle
@local/ds-balance
DeepSeek API 余额查询:左下角小字余额 + 刷新按钮,HTTP 端点与模型工具,默认激活
- Source
- kte66
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 13 days ago
Readme
# ds-balance — DeepSeek 余额查询插件(文件式 / 默认激活)
> **介绍**:给 DeepSeek Harness 使用的余额查询插件,目前只支持 DeepSeek,其他 API 后续支持接入。
在 DeepSeek Harness 左下角(输入框工具行左端)显示一个小字余额条 `¥ 110.00` + `↻`
刷新按钮,定时自动刷新;设置页可配置刷新间隔与**低余额告警阈值**(低于阈值余额变红
`⚠` 并提示充值);对话里说「查一下余额」也可走
`deepseek_balance` 模型工具。随 DSH 启动自动加载,无需审批。
---
## 安装方式 0:把这段话发给 AI,自动安装(推荐)
把下面代码块整段发给 DeepSeek Harness 的助手(或任何能操作文件系统的 AI 编码助手),
它就会自动完成安装接线;你也可以直接对助手说「按 README 的安装方式 0 帮我装」。
```text
你是 DeepSeek Harness 的代码助手。请帮我安装「DeepSeek 余额查询」插件。
插件介绍:给 DeepSeek Harness 使用的余额查询插件,目前只支持 DeepSeek,其他 API 后续支持接入。
插件目录:<插件目录的绝对路径,即本仓库根目录,例如 C:\code\dsh\plugin\ds-balance>
请按以下步骤自动完成安装:
1. 读取插件目录下的 README.md、package.json、cordis.patch.yml,
确认包名 @local/ds-balance 以及 dsh.bundle.patch / dsh.client 声明无误。
2. 定位 DSH profile:
$DSH_HOME 下(Windows 默认 C:\Users\<用户名>\.dsh,macOS/Linux 为 ~/.dsh)的
profiles/<profile名>/package.json(默认 profile 为 web)。
3. 修改 profile 的 package.json(写 $DSH_HOME 下的文件可能超出文件沙箱,如被拒请向用户申请提权):
- dependencies 中增加 "@local/ds-balance": "link:<插件目录绝对路径>"(Windows 请用正斜杠,如 link:C:/code/dsh/plugin/ds-balance);
- dsh.profile.bundles 数组末尾追加 "@local/ds-balance"。
4. 建立目录链接,让 bundle 解析器(dsh 安装目录 → profile 目录)能找到插件包:
- Windows:在 profiles/<profile名>/node_modules/@local/ 下创建目录联接(junction)指向插件目录;
- macOS/Linux:ln -s <插件目录> profiles/<profile名>/node_modules/@local/ds-balance;
- 或者直接在 profile 目录运行 pnpm install 也可。
5. 验证解析:执行
node -e "console.log(require.resolve('@local/ds-balance/package.json', { paths: ['<profile绝对路径>'] }))"
应输出插件包的 package.json 路径。
6. 检查凭证:$DSH_HOME/.credentials.yaml 中是否有 DEEPSEEK_API_KEY;
若缺失,提示用户配置(插件不硬编码密钥,缺失时余额条会显示「余额 —」)。
7. 完成并告知用户:重启 DSH(dsh web / 重启服务)后生效;
重启后访问 http://127.0.0.1:3080/ds-balance 应返回 JSON(含 balance_infos)而非 HTML 首页。
```
> 提示:段落里的 `<插件目录绝对路径>`、`<用户名>`、`<profile名>` 是占位符,粘贴前替换成实际值;
> 不替换也能装——助手一般会自行推断或向你确认。
---
## 1. 能不能在其他电脑上直接用?
**插件包本身可以**:本目录零第三方依赖(Host 代码 `lib/index.js` 无任何 import),
拷到任何机器即可作为 DSH 的 bundle 插件加载。
**但"直接生效"还需要每台目标机器完成 4 步接线**(约 2 分钟,最快路径见[「安装方式 0」](#安装方式-0把这段话发给-ai自动安装推荐)):
1. 把本目录放到目标机器的任意位置(下文以 `C:\code\dsh\plugin\ds-balance` 为例)
2. 在 DSH profile 组合里登记它(见 §3)
3. 建一个 node_modules 目录链接(见 §4)
4. 配置 DeepSeek API Key(见 §5)
5. 重启 DSH
> 一句话:插件是"可移植的零件",接线是"每台机器的装配",README 就是装配说明。
---
## 2. 目录结构
```
ds-balance/
├── package.json # 包声明:dsh.bundle.patch + dsh.client(客户端 bundle 入口)
├── cordis.patch.yml # 组合补丁:insert 一行插件(- id: ds-balance, name: '@local/ds-balance')
└── lib/
├── index.js # Host:HTTP 端点 GET /ds-balance + 模型工具 deepseek_balance(零 import)
└── client.js # 浏览器半部:手写经典脚本 bundle(__ModuleLoader__.load),改完刷新页面即生效
```
配套开发笔记见同目录 [`PLUGIN-DEV-MEMO.md`](PLUGIN-DEV-MEMO.md)。
---
## 3. 接线 A:登记到 profile 组合
找到目标机器使用的 profile(本机是 `web`):`$DSH_HOME/profiles/<profile名>/package.json`
(Windows 默认 `$DSH_HOME` = `C:\Users\<用户>\.dsh`)。
**a) `dependencies` 增加一行**(指向你放置插件的位置):
```jsonc
"dependencies": {
// ...原有依赖...
"@local/ds-balance": "link:C:/code/dsh/plugin/ds-balance" // ← 改为实际路径
}
```
**b) `dsh.profile.bundles` 末尾追加包名**:
```jsonc
"dsh": {
"profile": {
"bundles": [
// ...原有 bundles...
"@local/ds-balance" // ← 追加
]
}
}
```
> profile 组合加载顺序:dsh 安装目录 → profile 目录。bundle 必须能被 Node 从 profile
> 解析到(下一步建链接),否则启动会报 `cannot resolve profile bundle`。
---
## 4. 接线 B:建 node_modules 链接
让 `resolveBundleDir` 能在 profile 目录解析到插件包。二选一:
**方式一(推荐,无需 pnpm):目录联接 / 符号链接**
Windows(管理员或普通用户均可,junction 无需提权):
```powershell
New-Item -ItemType Directory -Path "$env:USERPROFILE\.dsh\profiles\web\node_modules\@local" -Force
New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\web\node_modules\@local\ds-balance" `
-Target "C:\code\dsh\plugin\ds-balance"
```
macOS / Linux:
```bash
mkdir -p "$HOME/.dsh/profiles/web/node_modules/@local"
ln -s "/path/to/ds-balance" "$HOME/.dsh/profiles/web/node_modules/@local/ds-balance"
```
**方式二:pnpm install**(profile 目录下执行,会按 `link:` 依赖建立正式链接)
```bash
cd "$HOME/.dsh/profiles/web" && pnpm install
```
验证解析成功:
```bash
node -e "console.log(require.resolve('@local/ds-balance/package.json', { paths: ['$HOME/.dsh/profiles/web'] }))"
```
---
## 5. 接线 C:配置 API Key(每台机器私有)
插件每次查询时通过凭证 seam 实时读取,**不硬编码**。目标机器需要:
```
# $DSH_HOME/.credentials.yaml
DEEPSEEK_API_KEY: sk-xxxx
```
缺失时插件不报错,余额条显示红色 `余额 —`,悬停提示「未配置 DEEPSEEK_API_KEY」。
---
## 6. 接线 D:重启 & 验证
1. 重启 DSH(`dsh web` / 重启服务)
2. 验证:
- 浏览器打开 `http://127.0.0.1:3080/ds-balance` → 应返回 JSON(含 `balance_infos`),
而不是 HTML 首页
- 对话页左下角出现小字余额 + `↻` 按钮(默认 60s 自动刷新)
- 设置 → 「DeepSeek 余额」可改刷新间隔(5–86400 秒,存 localStorage)
- 对话中说「查一下余额」→ `deepseek_balance` 工具输出明细
---
## 7. 卸载
1. 从 profile `package.json` 删除 `link:` 依赖和 bundles 里的 `@local/ds-balance`
2. 删除 `profiles/<profile>/node_modules/@local/ds-balance` 链接
3. 删除插件目录
4. 重启 DSH
---
## 8. 跨平台注意事项(macOS / Linux 兼容)
- **HTTP 客户端(已自动处理)**:Host 自动检测平台选择 curl 可执行文件名——
Windows 用 `curl.exe`,macOS/Linux 用 `curl`(系统自带,无需安装)。
`lib/index.js` 顶部 `CURL_NAME` 常量即平台判断,无需手动改动。
- **目录链接**:Windows 用 junction,POSIX 用 `ln -s`(见 §4)。
- **凭证**:`$DSH_HOME` 随平台不同(macOS 为 `~/.dsh`),但 `.credentials.yaml` 的键名
`DEEPSEEK_API_KEY` 一致。
- **其余部分**:客户端 bundle 是纯浏览器代码、Host 零 import、`webServer` 路由用 Node
标准 http 对象——三平台行为一致。
---
## 9. 行为开关(改 `lib/client.js` 后刷新页面即生效,无需重新构建)
| 想改 | 位置 |
| --- | --- |
| 取消隐藏左下角 "Cordis Plugin" 徽标 | 删除 `sidebar.footer.action` 那段 `cordis-panel` 注册(含注释) |
| 改默认刷新间隔 | `DEFAULT_CONFIG.intervalMs`(60000) |
| 改默认告警阈值 | `DEFAULT_CONFIG.lowBalanceThreshold`(10,0 = 关闭告警) |
| 改默认币种/显示格式 | `BalancePill` 的 label 逻辑 |
| 关闭默认自动刷新 | `DEFAULT_CONFIG.autoRefresh: false` |
> 刷新间隔、自动刷新开关、低余额告警阈值是**同一份配置**(`ds-balance:config`,存 localStorage),
> 都在 设置 → DeepSeek 余额 页里改。余额低于阈值时数字变红并显示 `⚠`,悬停提示
> 「余额不足,请及时充值」。
> ⚠️ 若保留徽标隐藏,`cordis-panel` 注册必须带 `priority: -1`(遮蔽者用更低 priority,
> 不能用同 id 同 priority 去撞内置 `dsh-client-ui-cordis`,否则会把整个 Cordis 面板加载搞挂)。
> 详见 [`PLUGIN-DEV-MEMO.md`](PLUGIN-DEV-MEMO.md) 坑 1。
---
## 10. 工作原理速览
```
浏览器端 lib/client.js DSH Host lib/index.js
┌────────────────────────────┐ 同源 ┌──────────────────────────────┐
│ 左下角小字余额条 + ↻ 按钮 │ fetch │ webServer 路由 GET /ds-balance │
│ 设置页(间隔, localStorage) │ ─────────► │ → credentials 读 API Key │
│ deepseek_balance 工具调用 │ │ → subprocess spawn curl │
└────────────────────────────┘ │ → https://api.deepseek.com/ │
│ user/balance │
└──────────────────────────────┘
```
- 数据通道:`webServer` HTTP 路由(绕开 typert Remote 生成器)
- 工具注册:`ctx.tools.register` 手写定义(零 import)
- 凭证:`ctx.credentials.resolve('DEEPSEEK_API_KEY')` 每次实时解析
---
## 11. 安全说明
| 项 | 说明 |
| --- | --- |
| 密钥去向 | 只在本机、只发给 DeepSeek 官方接口(`Authorization: Bearer` 头) |
| 命令行不暴露 | 密钥写入一次性临时 header 文件(`node:fs`,0600 权限),curl 用 `-H @file` 读取,请求结束**立即删除**(`finally` 兜底,成功失败都清) |
| 不进浏览器 | 客户端只 `fetch('/ds-balance')`,返回体只有余额数据,无密钥 |
| 不进仓库/日志 | 密钥零硬编码;响应/工具输出/日志均不含密钥 |
| 遗留说明 | `.credentials.yaml` 本身明文存密钥(DSH 凭证机制设计);临时 header 文件仅在查询瞬间存在于系统临时目录 |
---
## 12. 升级注意事项
**DSH 升级(npm 更新 / 覆盖安装)不会让插件失效**:
- 插件文件在 `C:\code\dsh\plugin\`,升级不触碰;
- profile 的 `package.json` 升级自愈逻辑(`normalizeShippedProfile`)**只重写还等于出厂默认 bundles 列表的 profile**;
你的列表已含 `@local/ds-balance`(用户自定义),升级会原样保留;
- `node_modules/@local/ds-balance` 目录联接在 profile 目录下,不在安装目录,升级不动。
**升级后如遇到问题,按优先级检查**:
1. 启动报 `cannot resolve profile bundle "@local/ds-balance"` → profile 的 node_modules 被重建/清理过,
按 README §4 重新建链接(或 `pnpm install`)即可;
2. 插件加载了但报错 → 可能是 DSH 新版的破坏性变更(槽位名 / `tools.register` 规范 / bundle 协议),
按报错适配插件代码(通常是小改动);
3. 一切正常但余额不显示 → 走 §6 验证清单(`/ds-balance` 应返回 JSON 而非 HTML)。
Install
dsh plugin --profile web add github:kte66/dsh-balance
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install local-ds-balance from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.