dsh-ollama-usage 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -1,72 +1,102 @@
1
- # dsh-ollama-usage
1
+ <div align="center">
2
2
 
3
- DeepSeek Harness 插件:可视化 **Ollama Pro** 账号的用量余量(每 5 小时会话用量 + 周用量),
4
- 支持侧边栏双横条、设置页完整面板、API Key 与用量快照持久化、自动刷新与登录引导。
3
+ # dsh-ollama-usage
5
4
 
6
- A DeepSeek Harness plugin that visualizes your **Ollama Pro** usage / remaining quota
7
- (5-hour session bucket + weekly bucket), with a minimalist sidebar double-bar,
8
- a full settings panel, persisted API key and usage snapshots, auto-refresh,
9
- and login guidance.
5
+ **Ollama Cloud 用量余量可视化 · DeepSeek Harness 插件**
10
6
 
11
- 数据来源为 Ollama 官方接口 `GET https://ollama.com/api/usage`
12
- (数据与 [ollama.com/settings](https://ollama.com/settings) 页面一致)。
7
+ [![npm version](https://img.shields.io/npm/v/dsh-ollama-usage?color=7c66e8&label=npm)](https://www.npmjs.com/package/dsh-ollama-usage)
8
+ [![GitHub release](https://img.shields.io/github/v/release/SeverusZh/dsh-ollama-usage?color=b39df7&label=release)](https://github.com/SeverusZh/dsh-ollama-usage/releases)
9
+ [![License](https://img.shields.io/badge/license-MIT-9ece6a)](LICENSE)
10
+ [![dsh](https://img.shields.io/badge/dsh-%E2%89%A50.1.0--rc.5-7aa2f7)](https://github.com/deepseek-ai/dsh)
13
11
 
14
- ## 功能
12
+ 可视化你的 **Ollama Cloud** 用量余量 —— 每 5 小时会话用量 + 周用量,
13
+ 侧边栏极简双横条常驻显示,设置页完整面板,Key 与快照持久化,自动刷新。
15
14
 
16
- - **侧边栏底部双横条**(极简、透明背景):`会话5h` 淡紫条 + `周用量` 深紫条,
17
- 各带百分比数字;悬停显示详情;每 60 秒自动更新;窄栏(rail)自动隐藏。
18
- - **设置页「Ollama 用量」完整面板**:会话(每 5 小时)/ 周用量进度条(已用 X% · 剩余 Y%)、
19
- 周期起止时间、近 4 周费用、模型请求数排行、最近 5 条会话用量历史、清除 Key。
20
- - **持久化**:API Key 与用量快照写入 `$DSH_HOME/storages/ollama-usage/usage.json`
21
- (权限 600,保留最近 24 条历史),跨对话 / 重启自动恢复。
22
- - **自动刷新**:Host 每 10 分钟自动查询一次(浏览器页面关闭也持续);
23
- Key 失效(401)自动清除并提示重新登录。
24
- - **登录引导**:未登录时面板显示步骤指引,一键打开
25
- [ollama.com/settings](https://ollama.com/settings) 登录、到
26
- [settings/keys](https://ollama.com/settings/keys) 创建 API Key 并粘贴检测;
27
- 也兼容旧版 CLI 的 `~/.ollama/auth.json` 凭证。
15
+ *Ollama Cloud usage & remaining-quota visualization for DeepSeek Harness
16
+ 5-hour session + weekly quota, always-visible sidebar bars, a full settings
17
+ panel, persisted credentials & snapshots, auto-refresh.*
28
18
 
29
- ## 安装
19
+ </div>
20
+
21
+ ---
22
+
23
+ ## ✨ 功能特性 Features
24
+
25
+ | 能力 | 说明 |
26
+ | --- | --- |
27
+ | 🎯 **会话用量(每 5 小时)** | Ollama Cloud 的 5 小时会话配额,置顶展示「已用 X% · 剩余 Y%」 |
28
+ | 📅 **周用量(Weekly)** | 本周配额进度,与会话用量并排展示 |
29
+ | 🎨 **侧边栏双横条** | 极简透明风格:会话 5h **淡紫** + 周用量**深紫**,各带百分比数字,悬停显示详情,每 60 秒自动更新(窄栏自动隐藏) |
30
+ | 🖥️ **设置页完整面板** | 周期起止时间、近 4 周费用、模型请求数排行、最近 5 条会话用量历史 |
31
+ | 💾 **持久化** | API Key 与用量快照写入 `$DSH_HOME/storages/ollama-usage/usage.json`(权限 600,保留 24 条历史),跨对话 / 重启自动恢复 |
32
+ | 🔄 **自动刷新** | Host 每 10 分钟自动查询(页面关闭也持续);Key 失效(401)自动清除并提示 |
33
+ | 🔑 **登录引导** | 未登录时一键打开 [ollama.com/settings](https://ollama.com/settings) 登录、到 [settings/keys](https://ollama.com/settings/keys) 创建 API Key;兼容旧版 CLI 的 `~/.ollama/auth.json` |
34
+
35
+ 数据来源为 Ollama 官方接口 `GET https://ollama.com/api/usage`,与
36
+ [ollama.com/settings](https://ollama.com/settings) 页面一致。
37
+
38
+ ## 📦 安装 Install
30
39
 
31
40
  ```bash
32
41
  dsh plugin --profile web add dsh-ollama-usage
33
42
  dsh --profile web
34
43
  ```
35
44
 
36
- 或手动把包加入 profile `package.json` 的 `dsh.profile.bundles` 后重启。
45
+ > 也可手动把 `dsh-ollama-usage` 加入 profile `package.json` 的
46
+ > `dsh.profile.bundles` 后重启。
37
47
 
38
- ## 使用
48
+ ## 🚀 使用 Usage
39
49
 
40
- 1. 打开 设置**Ollama 用量**。
41
- 2. 若未登录:按面板指引打开 [ollama.com/settings](https://ollama.com/settings)
42
- 登录账号,在 [settings/keys](https://ollama.com/settings/keys) 创建 API Key
43
- (`ollama-` 开头),粘贴到输入框点 **检测**;或在终端运行 `ollama signin` 后点
44
- **重新检测本地凭证**。
45
- 3. 检测成功后 Key 与快照即持久化,之后全自动:展开侧边栏即可在底部看到双横条,
46
- 面板可随时查看详情与历史。
47
- 4. 不再需要时,在面板点 **清除已存 Key** 即可移除本地凭证(历史保留)。
50
+ 1. 打开 **设置 → Ollama 用量**;
51
+ 2. 未登录时按面板指引:登录 [ollama.com](https://ollama.com/settings)
52
+ [settings/keys](https://ollama.com/settings/keys) 创建 API Key
53
+ 粘贴并点 **检测**(或终端 `ollama signin` 后点 **重新检测本地凭证**);
54
+ 3. 检测成功后即持久化,展开侧边栏即可看到底部双横条,面板可随时查看详情与历史;
55
+ 4. 不再需要时点 **清除已存 Key** 移除本地凭证(历史保留)。
48
56
 
49
- ## 数据与隐私
57
+ ## 🔒 数据与隐私 Privacy
50
58
 
51
59
  - 仅向 `https://ollama.com/api/usage` 发送带 Bearer 的查询请求;
52
- - Key 以明文保存在本机 `$DSH_HOME/storages/ollama-usage/usage.json`(权限 600),
53
- 与 `~/.ollama/auth.json` 同等级信任;需要时可随时清除。
60
+ - Key 以明文保存在本机 `$DSH_HOME/storages/ollama-usage/usage.json`(权限 600
61
+ 与 `~/.ollama/auth.json` 同等级信任),随时可清除。
54
62
 
55
- ## 开发 / 发布
63
+ ## 🏗️ 架构 Architecture
56
64
 
57
- ```bash
58
- npm install # 安装依赖(@deepseek-ai/dsh-home-paths)
59
- npm pack # 本地打包检查
60
- npm publish # 发布到 npm(需先 npm login)
65
+ ```
66
+ ┌──────────────────────────┐ ┌─────────────────────────────┐
67
+ │ browser (client bundle) │ RPC │ host (lib/index.js) │
68
+ │ lib/client.js │◄──────►│ webServer /ollama-usage │
69
+ │ · sidebar dual bars │ 信封协议 │ · fetch api/usage (Bearer)│
70
+ │ · settings panel │ │ · $DSH_HOME 持久化(0600) │
71
+ │ · login guidance │ │ · 10min auto-refresh │
72
+ └──────────────────────────┘ └─────────────────────────────┘
61
73
  ```
62
74
 
63
- - 宿主入口:`lib/index.js`(ESM,导出 `name` + 默认插件;在 webServer 注册
64
- `/ollama-usage` 前缀路由,走 Connection RPC 信封协议)。
65
- - 客户端入口:`lib/client.js`(`window.__ModuleLoader__.load` bundle
66
- `connection.rpc.call('/ollama-usage', endpoint, payload)` 调用宿主)。
67
- - bundle 接线:`cordis.patch.yml`(Loader 行)+ `package.json` 的
75
+ - 宿主入口 `lib/index.js`:ESM,导出 `name` + 默认插件;`webServer` 前缀路由 +
76
+ Connection RPC 信封协议(`check` / `snapshot` / `forget` / `auth-state`)。
77
+ - 客户端入口 `lib/client.js`:`window.__ModuleLoader__.load` bundle,经
78
+ `connection.rpc.call('/ollama-usage', endpoint, payload)` 与宿主通信。
79
+ - 接线:`cordis.patch.yml`(Loader 行)+ `package.json` 的
68
80
  `dsh.bundle.patch` / `dsh.client` 声明。
69
81
 
70
- ## License
82
+ ## 🧪 测试 Tests
83
+
84
+ ```bash
85
+ DSH_HOME=.tmp-dsh-home HOME=.tmp-home node test/bridge-smoke.mjs
86
+ ```
87
+
88
+ 17 项冒烟测试覆盖:路由注册、no-token / 401 分支、持久化读写与清理、
89
+ snapshot / forget / auth-state、非法信封与请求方法校验。
90
+
91
+ ## 🛠️ 开发 / 发布 Develop & Publish
92
+
93
+ ```bash
94
+ npm install # 安装依赖(@deepseek-ai/dsh-home-paths)
95
+ npm test # 冒烟测试(见上)
96
+ npm pack # 本地打包检查
97
+ npm publish # 发布到 npm
98
+ ```
99
+
100
+ ## 📄 License
71
101
 
72
- MIT
102
+ [MIT](LICENSE) © 2026 dsh-ollama-usage contributors
package/lib/client.js CHANGED
@@ -139,11 +139,11 @@ window.__ModuleLoader__.load({
139
139
  React.createElement('li', null,
140
140
  '在 API Keys 页 ',
141
141
  React.createElement('a', { className: 'olusa-link', href: 'https://ollama.com/settings/keys', target: '_blank', rel: 'noreferrer' }, 'settings/keys'),
142
- ' 创建一个 API Key(以 ollama- 开头)'
142
+ ' 创建一个 API Key'
143
143
  ),
144
144
  React.createElement('li', null, '把 Key 粘贴到下方点击“检测”;或先在终端运行 ollama signin / ollama login,再点“重新检测本地凭证”')
145
145
  ),
146
- React.createElement('input', { className: 'olusa-input', placeholder: '粘贴 API Key(ollama-…)', value: props.tokenInput, onChange: (e) => props.onInput(e.target.value), spellCheck: false }),
146
+ React.createElement('input', { className: 'olusa-input', placeholder: '粘贴 API Key', value: props.tokenInput, onChange: (e) => props.onInput(e.target.value), spellCheck: false }),
147
147
  React.createElement('div', { className: 'olusa-rowbtns' },
148
148
  React.createElement('button', { className: 'olusa-btn olusa-btn-primary', disabled: props.busy || !props.tokenInput.trim(), onClick: () => props.onCheck(props.tokenInput.trim()) }, props.busy ? '检测中…' : '检测'),
149
149
  React.createElement('button', { className: 'olusa-btn', disabled: props.busy, onClick: () => props.onRetryLocal() }, '重新检测本地凭证')
@@ -269,7 +269,7 @@ window.__ModuleLoader__.load({
269
269
  React.createElement('a', { className: 'olusa-link', href: 'https://ollama.com/settings', target: '_blank', rel: 'noreferrer' }, '打开 ollama.com/settings'),
270
270
  ',或粘贴 API Key 重试。'
271
271
  ),
272
- React.createElement('input', { className: 'olusa-input', placeholder: '粘贴 API Key(ollama-…)', value: tokenInput, onChange: (e) => setTokenInput(e.target.value), spellCheck: false }),
272
+ React.createElement('input', { className: 'olusa-input', placeholder: '粘贴 API Key', value: tokenInput, onChange: (e) => setTokenInput(e.target.value), spellCheck: false }),
273
273
  React.createElement('div', { className: 'olusa-rowbtns' },
274
274
  React.createElement('button', { className: 'olusa-btn olusa-btn-primary', disabled: busy || !tokenInput.trim(), onClick: () => doCheck(tokenInput.trim()) }, busy ? '检测中…' : '检测'),
275
275
  React.createElement('button', { className: 'olusa-btn', disabled: busy, onClick: () => doCheck('') }, '重试')
package/lib/index.js CHANGED
@@ -372,14 +372,29 @@ async function handleBridgeRequest(req, res) {
372
372
  export default {
373
373
  inject: ['timer'],
374
374
  apply(ctx) {
375
+ // 1) RPC 路由优先注册:即使后续步骤失败,路由也已生效
375
376
  const webServer = ctx.get('webServer')
376
- if (webServer !== undefined) {
377
- ctx.effect(
378
- () => webServer.register({ kind: 'prefix', path: RPC_CHANNEL, handler: handleBridgeRequest }),
379
- 'ollama-usage: rpc bridge',
380
- )
377
+ if (webServer === undefined) {
378
+ console.error('[ollama-usage] webServer 服务不可用,跳过 RPC 路由注册')
379
+ } else {
380
+ try {
381
+ ctx.effect(
382
+ () => webServer.register({ kind: 'prefix', path: RPC_CHANNEL, handler: handleBridgeRequest }),
383
+ 'ollama-usage: rpc bridge',
384
+ )
385
+ console.log('[ollama-usage] RPC 路由已注册: ' + RPC_CHANNEL)
386
+ } catch (e) {
387
+ console.error('[ollama-usage] 路由注册失败: ' + String((e && e.message) || e))
388
+ }
381
389
  }
382
- ctx.effect(() => ctx.interval(autoRefresh, AUTO_REFRESH_MS), 'ollama-usage: auto refresh')
383
- autoRefresh()
390
+ // 2) 自动刷新:失败不影响插件启动
391
+ try {
392
+ ctx.effect(() => ctx.interval(autoRefresh, AUTO_REFRESH_MS), 'ollama-usage: auto refresh')
393
+ } catch (e) {
394
+ console.error('[ollama-usage] 自动刷新定时器不可用: ' + String((e && e.message) || e))
395
+ }
396
+ autoRefresh().catch((e) => {
397
+ console.error('[ollama-usage] 首次自动刷新失败: ' + String((e && e.message) || e))
398
+ })
384
399
  },
385
400
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-ollama-usage",
3
- "version": "0.1.0",
4
- "description": "DeepSeek Harness 插件:可视化 Ollama Pro 账号用量余量(每 5 小时会话用量 + 周用量),支持侧边栏双横条、设置页面板、API Key 与用量快照持久化、自动刷新与登录引导。Ollama Pro usage & remaining-quota visualization for DeepSeek Harness: 5-hour session + weekly quota bars in the sidebar footer, a full settings panel, persisted API key and usage snapshots, auto-refresh and login guidance.",
3
+ "version": "0.1.2",
4
+ "description": "DeepSeek Harness 插件:可视化 Ollama Cloud 账号用量余量(每 5 小时会话用量 + 周用量),支持侧边栏双横条、设置页面板、API Key 与用量快照持久化、自动刷新与登录引导。Ollama Pro usage & remaining-quota visualization for DeepSeek Harness: 5-hour session + weekly quota bars in the sidebar footer, a full settings panel, persisted API key and usage snapshots, auto-refresh and login guidance.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -19,15 +19,26 @@
19
19
  },
20
20
  "client": {
21
21
  "platform": "web",
22
- "inject": ["slots", "connection", "timer"]
22
+ "inject": [
23
+ "slots",
24
+ "connection",
25
+ "timer"
26
+ ]
23
27
  }
24
28
  },
25
29
  "dshhub": {
26
30
  "schemaVersion": 1,
27
31
  "displayName": "dsh-ollama-usage",
28
- "summary": "Ollama Pro 用量余量可视化:会话(5h)/周用量双横条 + 设置页完整面板,Key 与快照持久化,自动刷新,登录引导。",
29
- "categories": ["用量", "Web UI", "观测"],
30
- "surfaces": ["host", "web"],
32
+ "summary": "Ollama Cloud 用量余量可视化:会话(5h)/周用量双横条 + 设置页完整面板,Key 与快照持久化,自动刷新,登录引导。",
33
+ "categories": [
34
+ "用量",
35
+ "Web UI",
36
+ "观测"
37
+ ],
38
+ "surfaces": [
39
+ "host",
40
+ "web"
41
+ ],
31
42
  "capabilities": {
32
43
  "provides": []
33
44
  },
@@ -36,7 +47,9 @@
36
47
  "node": ">=20"
37
48
  },
38
49
  "permissions": {
39
- "network": ["https://ollama.com"]
50
+ "network": [
51
+ "https://ollama.com"
52
+ ]
40
53
  }
41
54
  },
42
55
  "files": [
@@ -60,7 +73,7 @@
60
73
  "dsh-plugin",
61
74
  "client-plugin",
62
75
  "ollama",
63
- "ollama-pro",
76
+ "ollama-cloud",
64
77
  "usage",
65
78
  "quota",
66
79
  "session",
@@ -68,5 +81,8 @@
68
81
  "zh",
69
82
  "en"
70
83
  ],
71
- "license": "MIT"
84
+ "license": "MIT",
85
+ "scripts": {
86
+ "test": "DSH_HOME=.tmp-dsh-home HOME=.tmp-home node test/bridge-smoke.mjs"
87
+ }
72
88
  }