dsh-tokenlens 1.3.1 → 1.3.3

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/CHANGELOG.md CHANGED
@@ -4,17 +4,19 @@
4
4
 
5
5
  **版本记录约定**:同一发布日只保留一个章节,标题取当日**最后一个**已发布版本号;当日多次发布的改动合并到该章节,并在标题下注明当日实际发布过的版本号(npm 上仍可安装这些独立版本)。若当日已有发布,后续小改动不再单独增加版本号,而是并入下一篇日志。这样日志按天规整、不出现同日多个小版本。
6
6
 
7
- ## 1.3.1 — 2026-11-01
7
+ ## 1.3.3 — 2026-11-01
8
8
 
9
- (当日已发布版本:v1.2.2 / v1.3.0 / v1.3.1)
9
+ (当日已发布版本:v1.2.2 / v1.3.0 / v1.3.1 / v1.3.3;v1.3.2 因仓库迁移未发布)
10
10
 
11
11
  - feat(update): 「启动时检查更新」改为**默认开启**(可在插件设置关闭);启动时向 npm registry 查询一次 latest 版本号,不携带凭据 / 账号 / 用量,失败只记录错误、不阻塞启动
12
12
  - feat(ui): 详情弹窗(统计首页)右下角的**插件版本处**显示更新状态——有新版本时显示「有新版本 vX」并可点击打开 npm;无新版本时显示「已是最新版本」;检查失败或关闭检查时不显示
13
13
  - feat(update): 供应商管理页「插件设置 → 更新检查」保留开关、隐私提示、状态行(尚未检查 / 正在检查 / 已是最新 / 发现新版本 / 检查失败可重试)与「立即检查」;并发检查单飞,仅在开关关→开时补查
14
14
  - feat(wire): `hello` / `providers` 携带 `update`(`UpdateInfo`)与 `updatePackageUrl`;`settings.updateCheck` 默认 `true`;新增 bridge action `updateCheck`(Agent 工具同步支持)
15
15
  - fix(workspaces): 修复「工作区悬浮卡片不显示 Token 明细」——Host 裁剪本地路径时把 `path` 误删成空串,默认工作区等「界面标题 ≠ 统计标签」的场景匹配失败;现只下发文件夹名 basename,客户端标题匹配大小写不敏感并兼容旧 Host
16
+ - chore(repo): 仓库迁移到 **senyingxidi/dsh-tokenlens**(原作者账号改名);同步更新 `package.json` 的 repository/homepage/bugs、README 徽章与 7 张截图、`market/index.json`、CONTRIBUTING / SECURITY / CODE_OF_CONDUCT / Issue 模板与 LICENSE 署名;旧 GitHub 地址会 301 重定向,旧市场索引 raw 地址继续可用
17
+ - fix(ui): 插件版本处自愈——页面在插件更新前加载时,`hello` 的旧版本号不再覆盖新的 Host 版本(取 hello / providers / 更新检查 `current` 中最新的版本),无需刷新页面即可显示正确版本
16
18
  - docs: README 增加「用 `link:` 安装的插件不要从插件市场重复安装/升级」的 Windows pnpm EPERM 排错说明;CHANGELOG 改为按发布日合并
17
- - 测试:278 个自动化用例(版本比较/检查/并发、设置开关、状态行、图表下钻与窗口、工作区 wire 回归)
19
+ - 测试:280 个自动化用例(版本比较/检查/并发、设置开关、状态行、图表下钻与窗口、工作区 wire 回归)
18
20
 
19
21
  ## 1.2.1 — 2026-10-31
20
22
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 daigahou
3
+ Copyright (c) 2026 senyingxidi
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/PROTOCOL.md CHANGED
@@ -327,7 +327,7 @@ needs no provider catalog of its own.
327
327
 
328
328
  The dialog 「供应商管理」 page talks to three additional actions:
329
329
 
330
- - `{action:"providers"}` → `{ok:true, providers:[{providerId,label,shortLabel,kind,enabled,hasKey,keySource,apiKeyRef,baseURL,consoleUrl,builtin,dshManaged,dshProviderId}], dshProviders:[{providerId,label,supported,usageProviderId}], settings:{labelStyle,defaultView,defaultScope,detailsExpanded,detailsWindow,updateCheck}, update:<UpdateInfo|null>, updatePackageUrl, storeFile, storeFileDisplay}`. `storeFile` is the real path (local tooling); `storeFileDisplay` replaces the user's home directory with `~` and is what the management page renders. `update` (v1.3.0) is the last optional update-check result and `updatePackageUrl` the npm page the management UI links to.
330
+ - `{action:"providers"}` → `{ok:true, version, providers:[{providerId,label,shortLabel,kind,enabled,hasKey,keySource,apiKeyRef,baseURL,consoleUrl,builtin,dshManaged,dshProviderId}], dshProviders:[{providerId,label,supported,usageProviderId}], settings:{labelStyle,defaultView,defaultScope,detailsExpanded,detailsWindow,updateCheck}, update:<UpdateInfo|null>, updatePackageUrl, storeFile, storeFileDisplay}`. `storeFile` is the real path (local tooling); `storeFileDisplay` replaces the user's home directory with `~` and is what the management page renders. `version` (v1.3.2) is the running Host version, so a page loaded before an in-place plugin update can refresh a stale `hello` label without a reload. `update` (v1.3.0) is the last update-check result and `updatePackageUrl` the npm page the management UI links to.
331
331
  - `{action:"providerUpdate", providerId, update:{enabled?,apiKey?,apiKeyRef?,baseURL?,consoleUrl?,label?,shortLabel?}}` → same list payload;
332
332
  empty strings clear a stored value (falling back to the profile/default). `label` (全名, ≤40 chars) and
333
333
  `shortLabel` (短标签, ≤12 chars) let the management page rename a provider. The shipped management page no
package/README.en.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/dsh-tokenlens.svg)](https://www.npmjs.com/package/dsh-tokenlens)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
- [![CI](https://github.com/daigahou/dsh-tokenlens/actions/workflows/ci.yml/badge.svg)](https://github.com/daigahou/dsh-tokenlens/actions/workflows/ci.yml)
7
+ [![CI](https://github.com/senyingxidi/dsh-tokenlens/actions/workflows/ci.yml/badge.svg)](https://github.com/senyingxidi/dsh-tokenlens/actions/workflows/ci.yml)
8
8
  [![Node.js](https://img.shields.io/badge/node-%3E%3D24-brightgreen)](package.json)
9
9
 
10
10
  > One glance at your usage: plan capacity for the selected provider plus local token statistics across harnesses, right below the DSH composer.
11
11
 
12
- **dsh-TokenLens** is a usage plugin for DSH (DeepSeek Harness), version v1.3.1. It keeps two kinds of numbers separate:
12
+ **dsh-TokenLens** is a usage plugin for DSH (DeepSeek Harness), version v1.3.3. It keeps two kinds of numbers separate:
13
13
 
14
14
  - **Plan capacity** — the provider's authoritative server-side values (percentage windows, used / cap, balance or remaining credit);
15
15
  - **Local token stats** — tokens consumed on this machine across every connected harness, for the selected provider or for all providers combined.
@@ -31,27 +31,27 @@ Everything is computed locally: zero runtime dependencies, no external database,
31
31
 
32
32
  **Usage chip below the composer**
33
33
 
34
- ![Usage chip below the composer](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/composer-chip.png)
34
+ ![Usage chip below the composer](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/composer-chip.png)
35
35
 
36
36
  **Workspace token badge and hover card**
37
37
 
38
- ![Workspace token badge and hover card](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/workspace-badge-hover.png)
38
+ ![Workspace token badge and hover card](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/workspace-badge-hover.png)
39
39
 
40
40
  **Usage dialog**
41
41
 
42
42
  | Chart mode | Data mode |
43
43
  |:---:|:---:|
44
- | ![Chart mode](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/stats-chart.png) | ![Data mode](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/stats-data.png) |
44
+ | ![Chart mode](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/stats-chart.png) | ![Data mode](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/stats-data.png) |
45
45
 
46
46
  **Provider management page**
47
47
 
48
48
  | Provider settings | Plugin settings |
49
49
  |:---:|:---:|
50
- | ![Provider settings](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/settings-providers.png) | ![Plugin settings](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/settings-plugin.png) |
50
+ | ![Provider settings](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/settings-providers.png) | ![Plugin settings](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/settings-plugin.png) |
51
51
 
52
52
  **Built-in provider pool**
53
53
 
54
- ![Built-in provider pool](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/settings-builtin.png)
54
+ ![Built-in provider pool](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/settings-builtin.png)
55
55
 
56
56
  ## Install
57
57
 
@@ -66,16 +66,16 @@ dsh plugin --profile <profile> add dsh-tokenlens
66
66
  Then make sure `dsh.profile.bundles` in `$DSH_HOME/profiles/<profile>/package.json` contains `"dsh-tokenlens"`:
67
67
 
68
68
  ```jsonc
69
- { "dependencies": { "dsh-tokenlens": "^1.3.1" },
69
+ { "dependencies": { "dsh-tokenlens": "^1.3.3" },
70
70
  "dsh": { "profile": { "bundles": ["…", "dsh-tokenlens"] } } }
71
71
  ```
72
72
 
73
73
  Restart DSH or wait for profile hot recomposition.
74
74
 
75
- **Option B — from GitHub.** In DSH, open **Plugins → Add plugin**, enter `https://github.com/daigahou/dsh-tokenlens` (or `github:daigahou/dsh-tokenlens`) and install. DSH selects the bundle in `dsh.profile.bundles` and enables it by default. CLI equivalent (installs the dependency only; add `"dsh-tokenlens"` to `dsh.profile.bundles` yourself):
75
+ **Option B — from GitHub.** In DSH, open **Plugins → Add plugin**, enter `https://github.com/senyingxidi/dsh-tokenlens` (or `github:senyingxidi/dsh-tokenlens`) and install. DSH selects the bundle in `dsh.profile.bundles` and enables it by default. CLI equivalent (installs the dependency only; add `"dsh-tokenlens"` to `dsh.profile.bundles` yourself):
76
76
 
77
77
  ```powershell
78
- dsh plugin --profile <profile> add "github:daigahou/dsh-tokenlens"
78
+ dsh plugin --profile <profile> add "github:senyingxidi/dsh-tokenlens"
79
79
  ```
80
80
 
81
81
  GitHub installs track the latest commit on the default branch (not a tag); updates require uninstall + reinstall, and GitHub access can be unreliable from some networks.
@@ -89,7 +89,7 @@ GitHub installs track the latest commit on the default branch (not a tag); updat
89
89
  1. DSH → **Plugins** → **More** next to *Experimental plugins* → enable **Custom plugin market**;
90
90
  2. Open **Discover** → **Add index source** → paste:
91
91
  ```
92
- https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/market/index.json
92
+ https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/market/index.json
93
93
  ```
94
94
  3. Search for `TokenLens` in **Discover** and install.
95
95
 
@@ -137,10 +137,10 @@ Host bridge route: `/api/tokenlens`; agent tool: `tokenlens_usage`.
137
137
 
138
138
  ## Development
139
139
 
140
- Node.js ≥ 24, zero runtime dependencies: `node --test` runs the 278 tests.
140
+ Node.js ≥ 24, zero runtime dependencies: `node --test` runs the 280 tests.
141
141
 
142
142
  Release: `node scripts/bump-version.mjs <version> "<note>"` updates `package.json`, `PLUGIN_VERSION` and `CHANGELOG.md`; see [CONTRIBUTING.md](CONTRIBUTING.md) and [SECURITY.md](SECURITY.md).
143
143
 
144
144
  ## License
145
145
 
146
- [MIT](LICENSE) © daigahou
146
+ [MIT](LICENSE) © senyingxidi
package/README.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/dsh-tokenlens.svg)](https://www.npmjs.com/package/dsh-tokenlens)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
- [![CI](https://github.com/daigahou/dsh-tokenlens/actions/workflows/ci.yml/badge.svg)](https://github.com/daigahou/dsh-tokenlens/actions/workflows/ci.yml)
7
+ [![CI](https://github.com/senyingxidi/dsh-tokenlens/actions/workflows/ci.yml/badge.svg)](https://github.com/senyingxidi/dsh-tokenlens/actions/workflows/ci.yml)
8
8
  [![Node.js](https://img.shields.io/badge/node-%3E%3D24-brightgreen)](package.json)
9
9
 
10
10
  > **一眼看清你的用量**:在 DSH 输入框下方显示当前供应商的套餐容量,并汇总本机跨 Harness 的 Token 消耗。
11
11
 
12
- **dsh-TokenLens(词元透镜)** 是 DSH(DeepSeek Harness)的用量插件(v1.3.1,公开版本)。它把两类数字**按不同口径**分开呈现:
12
+ **dsh-TokenLens(词元透镜)** 是 DSH(DeepSeek Harness)的用量插件(v1.3.3,公开版本)。它把两类数字**按不同口径**分开呈现:
13
13
 
14
14
  - **套餐容量**(供应商服务端权威值):百分比窗口、`已用 / 上限`、账户余额或剩余额度;
15
15
  - **本机 Token 统计**(本机记录):当前供应商在本机所有已接入 Harness 上的合计用量,也可切到「全部 Harness」看总账。
@@ -53,27 +53,27 @@
53
53
 
54
54
  ### 输入框下方的用量 chip
55
55
 
56
- ![输入框下方的用量 chip](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/composer-chip.png)
56
+ ![输入框下方的用量 chip](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/composer-chip.png)
57
57
 
58
58
  ### 工作区 Token 徽标与悬浮统计
59
59
 
60
- ![工作区 Token 徽标与悬浮统计](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/workspace-badge-hover.png)
60
+ ![工作区 Token 徽标与悬浮统计](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/workspace-badge-hover.png)
61
61
 
62
62
  ### 用量详情弹窗
63
63
 
64
64
  | 图表模式 | 数据模式 |
65
65
  |:---:|:---:|
66
- | ![统计弹窗 · 图表模式](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/stats-chart.png) | ![统计弹窗 · 数据模式](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/stats-data.png) |
66
+ | ![统计弹窗 · 图表模式](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/stats-chart.png) | ![统计弹窗 · 数据模式](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/stats-data.png) |
67
67
 
68
68
  ### 供应商管理页
69
69
 
70
70
  | 供应商配置 | 插件设置 |
71
71
  |:---:|:---:|
72
- | ![供应商配置](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/settings-providers.png) | ![插件设置](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/settings-plugin.png) |
72
+ | ![供应商配置](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/settings-providers.png) | ![插件设置](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/settings-plugin.png) |
73
73
 
74
74
  ### 内置供应商池
75
75
 
76
- ![内置供应商池](https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/docs/images/settings-builtin.png)
76
+ ![内置供应商池](https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/docs/images/settings-builtin.png)
77
77
 
78
78
  ## 安装
79
79
 
@@ -106,7 +106,7 @@ dsh plugin --profile <profile> add dsh-tokenlens
106
106
  ```jsonc
107
107
  {
108
108
  "dependencies": {
109
- "dsh-tokenlens": "^1.3.1"
109
+ "dsh-tokenlens": "^1.3.3"
110
110
  },
111
111
  "dsh": {
112
112
  "profile": {
@@ -128,13 +128,13 @@ dsh plugin --profile <profile> add dsh-tokenlens
128
128
  无法访问 npm(或想直接跟踪仓库最新代码)时,可以用仓库地址安装(需要能访问 GitHub):
129
129
 
130
130
  1. DSH → 侧边栏「插件」→「添加插件」;
131
- 2. 输入 `https://github.com/daigahou/dsh-tokenlens`(或 `github:daigahou/dsh-tokenlens`),选择安装源后点「安装」;
131
+ 2. 输入 `https://github.com/senyingxidi/dsh-tokenlens`(或 `github:senyingxidi/dsh-tokenlens`),选择安装源后点「安装」;
132
132
  3. 安装完成后 DSH 会把它选入 profile 的 `dsh.profile.bundles` 并默认启用;若界面没有变化,重启 DSH。
133
133
 
134
134
  等价的 CLI 写法(只安装依赖,仍需手动把 `dsh-tokenlens` 加入 `dsh.profile.bundles`):
135
135
 
136
136
  ```powershell
137
- dsh plugin --profile <profile> add "github:daigahou/dsh-tokenlens"
137
+ dsh plugin --profile <profile> add "github:senyingxidi/dsh-tokenlens"
138
138
  ```
139
139
 
140
140
  > 注意:GitHub 源安装的是**默认分支最新提交**(不是 tag),DSH 不支持原地升级,升级时先卸载再安装。国内网络访问 GitHub 可能不稳定;插件发布到 npm 后建议改用方式 A。
@@ -165,7 +165,7 @@ dsh plugin --profile <profile> add "link:<path-to-dsh-tokenlens>"
165
165
  1. 打开 DSH → 侧边栏「插件」→「实验性插件」旁的「更多」→ 打开 **自定义插件市场**;
166
166
  2. 「已安装」旁出现 **发现** 标签 → 点 **添加索引源**,粘贴:
167
167
  ```
168
- https://raw.githubusercontent.com/daigahou/dsh-tokenlens/main/market/index.json
168
+ https://raw.githubusercontent.com/senyingxidi/dsh-tokenlens/main/market/index.json
169
169
  ```
170
170
  3. 在「发现」里搜索 `TokenLens`(或浏览 `dsh-TokenLens` 卡片)→ 安装。
171
171
 
@@ -392,7 +392,7 @@ Host 半注册 `tokenlens_usage`,参数 `action`(默认 `snapshot`)与可
392
392
 
393
393
  ## 验证
394
394
 
395
- - `node --test`:**278 个自动化用例**,覆盖 Host 数据层、供应商适配器、统计折叠、各 harness 读取、插件集成与浏览器端渲染 / 交互。
395
+ - `node --test`:**280 个自动化用例**,覆盖 Host 数据层、供应商适配器、统计折叠、各 harness 读取、插件集成与浏览器端渲染 / 交互。
396
396
  - 在真实环境中验证过 **5 个 harness** 的数据源;本机统计与独立的 SQLite 查询、独立的日志解析逐项对账(差额为 0),跨 harness 合并与供应商映射算术自洽。
397
397
  - 供应商接口按各官方文档与参考客户端行为验证;未配置凭据时 chip 静默隐藏,接口异常时按可重试错误降级。
398
398
 
@@ -401,9 +401,9 @@ Host 半注册 `tokenlens_usage`,参数 `action`(默认 `snapshot`)与可
401
401
  要求 **Node.js ≥ 24**(DSH Desktop 自带;用到 `node:sqlite` 与 zstd 解压),无运行时 npm 依赖:
402
402
 
403
403
  ```powershell
404
- git clone https://github.com/daigahou/dsh-tokenlens.git
404
+ git clone https://github.com/senyingxidi/dsh-tokenlens.git
405
405
  cd dsh-tokenlens
406
- node --test # 278 个用例
406
+ node --test # 280 个用例
407
407
  ```
408
408
 
409
409
  本地联调安装方式见[方式 C](#方式-c本地开发从源码-link)。
@@ -437,4 +437,4 @@ node scripts/bump-version.mjs <version> "<说明>"
437
437
 
438
438
  ## 许可
439
439
 
440
- [MIT](LICENSE) © daigahou
440
+ [MIT](LICENSE) © senyingxidi
package/client.js CHANGED
@@ -1292,6 +1292,9 @@ window.__ModuleLoader__.load({
1292
1292
  settings: normalizePluginSettings(settings),
1293
1293
  update: hasUpdate ? normalizeUpdate(raw.update) : null,
1294
1294
  hasUpdate,
1295
+ // v1.3.2: the running Host version. A page whose one-time `hello` was
1296
+ // answered before a plugin update can adopt the new value from here.
1297
+ version: stringOrEmpty(raw.version).trim(),
1295
1298
  // Optional: the Host may advertise the npm page its links should open.
1296
1299
  updatePackageUrl: stringOrEmpty(raw.updatePackageUrl).trim(),
1297
1300
  labelCatalog,
@@ -2186,6 +2189,12 @@ window.__ModuleLoader__.load({
2186
2189
  if (parsed.updatePackageUrl !== '' && current.updatePackageUrl !== parsed.updatePackageUrl) {
2187
2190
  patch.updatePackageUrl = parsed.updatePackageUrl
2188
2191
  }
2192
+ // v1.3.2: the answered Host version refreshes a stale hello version (the
2193
+ // page may have loaded before a plugin update/recomposition). Never
2194
+ // downgrade: hello and this answer race, and the newest version wins.
2195
+ if (parsed.version !== '' && newerVersionOf(current.pluginVersion, parsed.version) === parsed.version) {
2196
+ if (current.pluginVersion !== parsed.version) patch.pluginVersion = parsed.version
2197
+ }
2189
2198
  if (parsed.labelCatalog !== null && typeof parsed.labelCatalog === 'object') {
2190
2199
  const catalog = { ...current.labelCatalog, ...parsed.labelCatalog }
2191
2200
  if (Object.keys(catalog).length > 0) patch.labelCatalog = catalog
@@ -2891,7 +2900,13 @@ window.__ModuleLoader__.load({
2891
2900
  if (data === null || typeof data !== 'object') return
2892
2901
  const patch = {}
2893
2902
  if (typeof data.version === 'string' && data.version !== '') {
2894
- if (store.get().pluginVersion !== data.version) patch.pluginVersion = data.version
2903
+ // v1.3.2: hello and the startup providers bootstrap race; only the
2904
+ // newest known Host version wins (a stale hello must not downgrade the
2905
+ // label after an in-place plugin update).
2906
+ const known = store.get().pluginVersion
2907
+ if (newerVersionOf(known, data.version) === data.version && known !== data.version) {
2908
+ patch.pluginVersion = data.version
2909
+ }
2895
2910
  }
2896
2911
  // `update` is optional on the wire: only an explicit field (null included)
2897
2912
  // replaces what the store already knows.
@@ -6801,6 +6816,44 @@ window.__ModuleLoader__.load({
6801
6816
  })
6802
6817
  }
6803
6818
 
6819
+ /**
6820
+ * Numeric parts of a plain `x.y.z` version, or null (v1.3.2).
6821
+ */
6822
+ function versionPartsOf(value) {
6823
+ if (typeof value !== 'string') return null
6824
+ const match = /^v?(\d{1,9})\.(\d{1,9})\.(\d{1,9})$/.exec(value.trim())
6825
+ return match === null ? null : [Number(match[1]), Number(match[2]), Number(match[3])]
6826
+ }
6827
+
6828
+ /**
6829
+ * The newer of two version strings (v1.3.2). Invalid or empty sides fall
6830
+ * back to the other one, so the dialog label never goes blank.
6831
+ */
6832
+ function newerVersionOf(left, right) {
6833
+ const a = versionPartsOf(left)
6834
+ const b = versionPartsOf(right)
6835
+ if (a === null) return b === null ? '' : right.trim()
6836
+ if (b === null) return left.trim()
6837
+ for (let index = 0; index < 3; index += 1) {
6838
+ if (a[index] !== b[index]) return a[index] > b[index] ? left.trim() : right.trim()
6839
+ }
6840
+ return left.trim()
6841
+ }
6842
+
6843
+ /**
6844
+ * The best-known running Host version for the dialog label (v1.3.2).
6845
+ *
6846
+ * `state.pluginVersion` is captured from the one-time `hello` announcement,
6847
+ * while `state.update.current` arrives with the startup update check and the
6848
+ * providers payload carries the same Host version. Picking the newest of the
6849
+ * two makes the label self-heal after a plugin update without a page reload.
6850
+ */
6851
+ function currentPluginVersionOf(state) {
6852
+ const fromHello = typeof state.pluginVersion === 'string' ? state.pluginVersion : ''
6853
+ const fromCheck = state.update !== null && typeof state.update.current === 'string' ? state.update.current : ''
6854
+ return newerVersionOf(fromHello, fromCheck).trim()
6855
+ }
6856
+
6804
6857
  /**
6805
6858
  * The update status appended to the plugin-version line of the usage dialog
6806
6859
  * body, or null when it must stay silent.
@@ -6889,12 +6942,13 @@ window.__ModuleLoader__.load({
6889
6942
  ),
6890
6943
  )
6891
6944
  const body = [buildManageButton(state, t), statsArea]
6892
- if (typeof state.pluginVersion === 'string' && state.pluginVersion !== '') {
6945
+ const displayVersion = currentPluginVersionOf(state)
6946
+ if (displayVersion !== '') {
6893
6947
  body.push(
6894
6948
  h(
6895
6949
  'div',
6896
6950
  { key: 'version', className: 'dsh-tokenlens-version' },
6897
- t('pluginVersion', { version: state.pluginVersion }),
6951
+ t('pluginVersion', { version: displayVersion }),
6898
6952
  // Update status sits right next to the plugin version: 有新版本 vX
6899
6953
  // (link to the npm page) or 已是最新版本, only for a successful check.
6900
6954
  buildVersionUpdateStatus(state, t),
package/index.js CHANGED
@@ -74,7 +74,7 @@ export const inject = []
74
74
  export const PLUGIN_NAME = 'dsh-tokenlens'
75
75
 
76
76
  /** Plugin version; mirrors package.json (kept here so diagnostics need no fs read). */
77
- export const PLUGIN_VERSION = '1.3.1'
77
+ export const PLUGIN_VERSION = '1.3.3'
78
78
 
79
79
  /** Documented defaults; every field of the raw row config is optional. */
80
80
  const DEFAULTS = {
@@ -733,12 +733,13 @@ export function apply(ctx, rawConfig) {
733
733
 
734
734
  return {
735
735
  ok: true,
736
+ // The running Host version: a page whose `hello` was answered before a
737
+ // plugin update can adopt the new version from this payload (v1.3.2).
738
+ version: PLUGIN_VERSION,
736
739
  providers,
737
740
  dshProviders,
738
741
  settings: sanitizeSettings(providerStore.settings),
739
- // Optional startup update check (settings.updateCheck): null until the
740
- // first check; never fetched unless the setting is enabled or the user
741
- // presses "check now".
742
+ // Update check result (settings.updateCheck): null until the first check.
742
743
  update: state.update,
743
744
  updatePackageUrl: UPDATE_PACKAGE_URL,
744
745
  storeFile: redactPaths(providerStoreFile),
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "dsh-tokenlens",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "type": "module",
5
5
  "description": "dsh-TokenLens (词元透镜) — provider-aware plan capacity plus local token statistics (today/7d/30d/all-time, by harness/provider/model/workspace) for DSH.",
6
6
  "license": "MIT",
7
- "author": "daigahou",
7
+ "author": "senyingxidi",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/daigahou/dsh-tokenlens.git"
10
+ "url": "git+https://github.com/senyingxidi/dsh-tokenlens.git"
11
11
  },
12
12
  "bugs": {
13
- "url": "https://github.com/daigahou/dsh-tokenlens/issues"
13
+ "url": "https://github.com/senyingxidi/dsh-tokenlens/issues"
14
14
  },
15
- "homepage": "https://github.com/daigahou/dsh-tokenlens#readme",
15
+ "homepage": "https://github.com/senyingxidi/dsh-tokenlens#readme",
16
16
  "keywords": [
17
17
  "dsh",
18
18
  "dsh-plugin",