dsh-provider-usage 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lizhouai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ <p align="right">
2
+ <strong>English</strong> · <a href="./README_ZH.md">简体中文</a>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/dsh-provider-usage"><img src="https://img.shields.io/npm/v/dsh-provider-usage.svg?cacheSeconds=300" alt="npm version"></a>
7
+ <a href="./LICENSE"><img src="https://img.shields.io/npm/l/dsh-provider-usage.svg?cacheSeconds=300" alt="MIT license"></a>
8
+ <img src="https://img.shields.io/badge/DeepSeek%20Harness-plugin-202724" alt="DeepSeek Harness plugin">
9
+ </p>
10
+
11
+ # dsh-provider-usage
12
+
13
+ **Every provider's balance, one glance away.** A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) plugin that floats a draggable quota ball over the Web GUI — no more logging into each provider console to check whether you are about to run out of credit mid-session.
14
+
15
+ ## Features
16
+
17
+ - **Auto-detection** — enumerates the provider routes registered in the current profile (`ctx.llm`); zero configuration for well-known routes.
18
+ - **Per-kind wire adapters**:
19
+ - **DeepSeek** (`deepseek-official`, …) → `GET {baseURL}/user/balance` (total / granted / topped-up balance)
20
+ - **Kimi Code subscription** (`kimi-coding`) → `GET {baseURL}/v1/usages` (weekly quota and rate-limit windows, with reset countdown)
21
+ - **Moonshot open platform** (`moonshotai-cn` / `moonshotai`) → `GET {baseURL}/users/me/balance`
22
+ - **Credentials stay safe** — API keys are resolved per request through the harness credentials service (environment variables / `~/.dsh/.credentials.yaml`); never cached, never written to disk.
23
+ - **Floating ball widget** — a draggable floating ball opens the quota panel; drop it anywhere, and a home button in the panel sends it back to its default spot. The halo around the ball encodes provider health: green all good, amber some quota below 30% left, red on query failure / missing key / usage ≥90%.
24
+ - **Version badge** — the panel header shows the running plugin version next to the title, so it is obvious which release is loaded.
25
+ - **Bilingual panel** — built-in Chinese/English UI; follows the harness language by default, with a one-click toggle in the panel header (persisted in localStorage).
26
+ - **Configurable refresh** — adjustable in the panel (15s–30min, persisted in localStorage); the default comes from the plugin config.
27
+ - **Manual providers** — add arbitrary gateways (e.g. a self-hosted DeepSeek-compatible endpoint) via config.
28
+
29
+ ## Screenshots
30
+
31
+ ![Quota panel in English](docs/panel-en.png)
32
+
33
+ ## Install
34
+
35
+ > [!NOTE]
36
+ > Requires an existing [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) installation.
37
+
38
+ ### npm
39
+
40
+ ```sh
41
+ dsh plugin --profile web add dsh-provider-usage@latest
42
+ ```
43
+
44
+ ### Build from source
45
+
46
+ ```sh
47
+ git clone https://github.com/lizhouai/dsh-provider-usage.git
48
+ cd dsh-provider-usage
49
+ pnpm install
50
+ pnpm build
51
+ pnpm pack # produces dsh-provider-usage-<version>.tgz
52
+ dsh plugin --profile web add ./dsh-provider-usage-<version>.tgz
53
+ ```
54
+
55
+ Install the **tarball**, not the repo directory: `dsh plugin add .` links the repo, whose own `node_modules` then shadows the harness's shared `@deepseek-ai/cordis` instance and the host half never registers (RPC 404). The link form is still handy for client-only UI iteration — the browser bundle is self-contained, so a rebuild + page refresh picks it up — but switch to the tarball (or the npm release) whenever you need the host half. If pnpm fails with `EPERM ... symlink` while replacing a linked install, delete the stale `node_modules/dsh-provider-usage` junction in the profile directory and retry.
56
+
57
+ Restart `dsh web` after changing the plugin set (a plugin add/remove requires a restart; afterwards, code changes only need a rebuild + re-add + page refresh).
58
+
59
+ ## Upgrade
60
+
61
+ ```sh
62
+ dsh plugin --profile web add dsh-provider-usage@latest
63
+ ```
64
+
65
+ Then restart `dsh web` and refresh the page. If the release you want was published very recently, your profile's supply-chain cooldown (`minimumReleaseAge`) may silently keep the older version — pin the exact version instead (`dsh plugin --profile web add dsh-provider-usage@0.1.5`) and dsh will exempt it automatically. The version badge in the panel header confirms which release is actually loaded.
66
+
67
+ ## Configuration
68
+
69
+ Defaults work out of the box: the plugin auto-detects every provider route of the active profile. A trusted profile can tune behavior in `~/.dsh/profiles/web/cordis.patch.yml`:
70
+
71
+ ```yaml
72
+ - insert:
73
+ - id: provider-usage
74
+ name: dsh-provider-usage
75
+ config:
76
+ refreshSeconds: 60 # suggested panel refresh interval (5–86400)
77
+ autoDetect: true # enumerate provider routes from the llm registry
78
+ providers: [] # manual specs; an id matching a detected route overrides it
79
+ ```
80
+
81
+ | Field | Type | Default | Description |
82
+ | --- | --- | --- | --- |
83
+ | `refreshSeconds` | number | `60` | Suggested widget refresh interval in seconds (5–86400) |
84
+ | `autoDetect` | boolean | `true` | Enumerate live provider routes from the llm registry |
85
+ | `providers` | array | `[]` | Manual provider specs: `{id, kind, baseURL, apiKeyEnv, displayName?, enabled?}`, `kind ∈ deepseek / kimi-coding / moonshot` |
86
+
87
+ The same fields can be hot-updated under the `provider-usage:` namespace in `~/.dsh/settings.yaml`.
88
+
89
+ ### Adding a manual provider
90
+
91
+ ```yaml
92
+ config:
93
+ providers:
94
+ - id: my-deepseek-gateway
95
+ kind: deepseek
96
+ baseURL: https://my-gateway.example.com
97
+ apiKeyEnv: MY_GATEWAY_KEY
98
+ displayName: My Gateway
99
+ ```
100
+
101
+ ## How it works
102
+
103
+ - **Host half** (`src/index.ts`): `UsageService extends TypertRemoteService` exposes `usage/list` via `@Remote('list')` (SRC mode, no codegen). Config is declared with schemastery, and `installSettingsSection` enables hot updates from settings.
104
+ - **Client half** (`src/client/`): a `window.__ModuleLoader__.load({id, factory})` bundle (built by tsdown) registers into the `sidebar.footer.action` slot and polls `usage/list` through `ctx.connection.rpc.call('/api', 'usage/list', {args:{}})` on its own interval. The service stays stateless — every poll fetches live values.
105
+
106
+ ## License
107
+
108
+ [MIT](./LICENSE)
package/README_ZH.md ADDED
@@ -0,0 +1,108 @@
1
+ <p align="right">
2
+ <a href="./README.md">English</a> · <strong>简体中文</strong>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/dsh-provider-usage"><img src="https://img.shields.io/npm/v/dsh-provider-usage.svg?cacheSeconds=300" alt="npm version"></a>
7
+ <a href="./LICENSE"><img src="https://img.shields.io/npm/l/dsh-provider-usage.svg?cacheSeconds=300" alt="MIT license"></a>
8
+ <img src="https://img.shields.io/badge/DeepSeek%20Harness-plugin-202724" alt="DeepSeek Harness plugin">
9
+ </p>
10
+
11
+ # dsh-provider-usage
12
+
13
+ [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 插件:在 Web GUI 上悬浮一个可任意拖动的额度球,实时查看所有已配置 LLM provider 的账户额度——不用再逐个登录 provider 控制台确认余额。
14
+
15
+ ## 功能
16
+
17
+ - **自动探测** —— 自动枚举当前 profile 中已注册的 provider 路由(`ctx.llm`),常见路由零配置。
18
+ - **按 provider 类型查询额度**:
19
+ - **DeepSeek**(`deepseek-official` 等)→ `GET {baseURL}/user/balance`(余额,含赠送/充值明细)
20
+ - **Kimi Code 订阅**(`kimi-coding`)→ `GET {baseURL}/v1/usages`(每周配额及各限速窗口,含重置倒计时)
21
+ - **Moonshot 开放平台**(`moonshotai-cn` / `moonshotai`)→ `GET {baseURL}/users/me/balance`
22
+ - **密钥安全** —— 通过 harness 凭据服务按次解析(环境变量 / `~/.dsh/.credentials.yaml`),不缓存、不落地。
23
+ - **悬浮球入口** —— 可任意拖动的悬浮球点击弹出额度面板,面板头部的归位按钮可一键回到默认位置;球体光晕表达健康度:绿色全部正常、黄色有配额剩余不足 30%、红色查询失败/缺密钥/用量 ≥90%。
24
+ - **版本徽章** —— 面板标题旁显示当前运行的插件版本,一眼确认加载的是哪个发布版。
25
+ - **中英双语** —— 面板内置中英文界面,默认跟随 harness 系统语言,标题栏按钮一键切换(localStorage 持久化)。
26
+ - **刷新周期可调** —— 面板内调整(15s–30min,localStorage 持久化),默认值由插件配置提供。
27
+ - **手动 provider** —— 可通过配置添加任意网关(如自建 DeepSeek 兼容端点)。
28
+
29
+ ## 截图
30
+
31
+ ![额度面板(中文)](docs/panel-zh.png)
32
+
33
+ ## 安装
34
+
35
+ > [!NOTE]
36
+ > 需要先安装 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)。
37
+
38
+ ### npm
39
+
40
+ ```sh
41
+ dsh plugin --profile web add dsh-provider-usage@latest
42
+ ```
43
+
44
+ ### 从源码构建
45
+
46
+ ```sh
47
+ git clone https://github.com/lizhouai/dsh-provider-usage.git
48
+ cd dsh-provider-usage
49
+ pnpm install
50
+ pnpm build
51
+ pnpm pack # 产出 dsh-provider-usage-<version>.tgz
52
+ dsh plugin --profile web add ./dsh-provider-usage-<version>.tgz
53
+ ```
54
+
55
+ 注意要安装 **tarball** 而不是仓库目录:`dsh plugin add .` 会链接整个仓库,仓库自带 `node_modules` 里的 `@deepseek-ai/cordis` 会遮蔽 harness 的共享实例,导致 host 半注册不上(RPC 404)。link 方式仍适合纯 UI 迭代(浏览器 bundle 自包含,重新 build + 刷新页面即生效),但需要 host 半时请切换到 tarball 或 npm 正式版。若替换 link 安装时 pnpm 报 `EPERM ... symlink`,手动删除 profile 目录下残留的 `node_modules/dsh-provider-usage` 联结后重试即可。
56
+
57
+ 插件集合变化后需重启 `dsh web`;之后仅改动代码时重新 build + 重新 add + 刷新页面即可。
58
+
59
+ ## 升级
60
+
61
+ ```sh
62
+ dsh plugin --profile web add dsh-provider-usage@latest
63
+ ```
64
+
65
+ 然后重启 `dsh web` 并刷新页面。如果目标版本刚发布不久,profile 的供应链冷静期(`minimumReleaseAge`)可能会静默停留在旧版——这时指定精确版本号(如 `dsh plugin --profile web add dsh-provider-usage@0.1.5`),dsh 会自动豁免该版本。面板标题旁的版本徽章可以确认实际加载的版本。
66
+
67
+ ## 配置说明
68
+
69
+ 默认开箱即用:自动探测当前 profile 的所有 provider 路由。也可以在 `~/.dsh/profiles/web/cordis.patch.yml` 中调整:
70
+
71
+ ```yaml
72
+ - insert:
73
+ - id: provider-usage
74
+ name: dsh-provider-usage
75
+ config:
76
+ refreshSeconds: 60 # 面板默认刷新周期(秒)
77
+ autoDetect: true # 自动枚举 llm 注册表中的 provider
78
+ providers: [] # 手动补充/覆盖 provider(id 相同则覆盖自动探测结果)
79
+ ```
80
+
81
+ | 字段 | 类型 | 默认 | 说明 |
82
+ | --- | --- | --- | --- |
83
+ | `refreshSeconds` | number | `60` | 面板建议刷新周期(秒),5–86400 |
84
+ | `autoDetect` | boolean | `true` | 从 llm 注册表自动枚举 provider |
85
+ | `providers` | array | `[]` | 手动 provider 规格:`{id, kind, baseURL, apiKeyEnv, displayName?, enabled?}`,`kind ∈ deepseek / kimi-coding / moonshot` |
86
+
87
+ 也可以在 `~/.dsh/settings.yaml` 中通过 `provider-usage:` 命名空间热更新同样字段。
88
+
89
+ ### 手动添加一个 provider 示例
90
+
91
+ ```yaml
92
+ config:
93
+ providers:
94
+ - id: my-deepseek-gateway
95
+ kind: deepseek
96
+ baseURL: https://my-gateway.example.com
97
+ apiKeyEnv: MY_GATEWAY_KEY
98
+ displayName: 自建网关
99
+ ```
100
+
101
+ ## 架构
102
+
103
+ - **Host 半**(`src/index.ts`):`UsageService extends TypertRemoteService`,`@Remote('list')` 暴露 `usage/list`(SRC 模式,无需代码生成);`Config` 用 schemastery 声明,`installSettingsSection` 支持 settings 热更新。
104
+ - **Client 半**(`src/client/`):`window.__ModuleLoader__.load({id, factory})` 格式 bundle(tsdown 构建),注册到 `sidebar.footer.action` slot,通过 `ctx.connection.rpc.call('/api', 'usage/list', {args:{}})` 轮询。服务本身无状态——每次轮询都取实时值。
105
+
106
+ ## 许可证
107
+
108
+ [MIT](./LICENSE)
@@ -0,0 +1,17 @@
1
+ # dsh-provider-usage bundle patch: mounts the provider-usage plugin into the
2
+ # host composition of a dsh profile. The plugin registers a `usage/list` remote
3
+ # service on the host and a usage panel into the Web GUI sidebar footer, so
4
+ # every session of the profile can see live provider balances at a glance.
5
+ #
6
+ # Install: `dsh plugin --profile <name> add <this package>` (npm or a local
7
+ # path). The `dsh plugin` command pnpm-installs the package into the profile
8
+ # and reconciles it into the profile's `dsh.profile.bundles` layer list.
9
+ - insert:
10
+ - id: provider-usage
11
+ # Node-resolvable package name — must stay in sync with package.json `name`.
12
+ name: dsh-provider-usage
13
+ # All config fields are optional; defaults are shown below.
14
+ # config:
15
+ # refreshSeconds: 60 # suggested panel refresh interval (5–86400)
16
+ # autoDetect: true # enumerate provider routes from the llm registry
17
+ # providers: [] # manual specs; an id matching a detected route overrides it