dsh-deepseek-balance-widget 2.4.2 → 2.4.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/README.md CHANGED
@@ -33,21 +33,27 @@
33
33
  - 更新失败时显示错误详情面板(可复制错误信息),并引导前往 GitHub 自行安装
34
34
  - 界面语言随 dsh 设置自动切换中 / EN
35
35
 
36
+ **皮肤与第三方插件兼容(v2.4.3 起)**
37
+ - 与 maid-atelier 等会重建侧栏 DOM 的皮肤插件共存时,余额入口依然稳定显示
38
+ - 插入采用「安全插入」策略:锚点被皮肤 / React 搬走时自动退化为追加,绝不抛异常、绝不中断重试
39
+ - 放置成功后下一帧自动复查,被搬走会在下一轮变化时自动归位
40
+ - 识别常见皮肤标记(如 `[data-maid-sidebar-footer]`)作为侧栏兜底锚点
41
+
36
42
  ## 安装
37
43
 
38
44
  需要:已安装 dsh(可用 `dsh web`)。
39
45
 
40
46
  ```bash
41
- dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.2
47
+ dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.3
42
48
  ```
43
49
 
44
50
  从 npm 拉取安装,dsh 自动注册到 `dsh.profile.bundles`,完成后**重启 `dsh web`** 即可。
45
51
 
46
- > **务必写死版本号 `@2.4.2`**(当前最新稳定版)。不要用 `@latest`——它会被本地 pnpm/npm 缓存或镜像源解析成旧版本,导致装到老版。如果未来发布了更高版本,把这里的版本号换成最新的即可。
52
+ > **务必写死版本号 `@2.4.3`**(当前最新稳定版)。不要用 `@latest`——它会被本地 pnpm/npm 缓存或镜像源解析成旧版本,导致装到老版。如果未来发布了更高版本,把这里的版本号换成最新的即可。
47
53
 
48
54
  也可以直接对 AI 说:
49
55
 
50
- > 帮我用 npm 安装 dsh-deepseek-balance-widget 插件,执行 `dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.2`。
56
+ > 帮我用 npm 安装 dsh-deepseek-balance-widget 插件,执行 `dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.3`。
51
57
 
52
58
  ## 配置
53
59
 
@@ -82,24 +88,38 @@ AI 会接管全部:问 API Key / 引导获取平台 Cookie → 读取本机教
82
88
  ### 方式二:命令行强制更新(最稳妥,适合卡住或装不上的情况)
83
89
 
84
90
  ```bash
85
- dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.2
91
+ dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.3
86
92
  ```
87
93
 
88
- **写死版本号 `@2.4.2`** 可绕过本地缓存 / 镜像源不同步 / `latest` 解析成旧版的问题,一步到位。装完**彻底重启 `dsh web`**。
94
+ **写死版本号 `@2.4.3`** 可绕过本地缓存 / 镜像源不同步 / `latest` 解析成旧版的问题,一步到位。装完**彻底重启 `dsh web`**。
89
95
 
90
96
  ### 方式三:手动更新(命令行更新失败时兜底)
91
97
 
92
98
  ```bash
93
99
  cd ~/.dsh/profiles/web
94
- npm install dsh-deepseek-balance-widget@2.4.2 # 若目录内有 pnpm-lock.yaml 则用 pnpm add
100
+ npm install dsh-deepseek-balance-widget@2.4.3 # 若目录内有 pnpm-lock.yaml 则用 pnpm add
95
101
  # 验证磁盘上确实变了
96
102
  cat node_modules/dsh-deepseek-balance-widget/package.json | grep '"version"'
97
103
  ```
98
104
 
99
- 确认输出 `2.4.2` 后,**彻底重启 `dsh web`** 即可。
105
+ 确认输出 `2.4.3` 后,**彻底重启 `dsh web`** 即可。
100
106
 
101
107
  > 如果你的环境里弹窗/命令行的更新一直失败(提示版本没变),通常是 Agent 主机(如 WorkBuddy)通过 `NODE_OPTIONS` 注入了文件删除拦截导致 pnpm/npm 更新中断。此时在**普通终端**(不通过 Agent 运行)里执行上面的命令即可成功;或先执行 `set NODE_OPTIONS=`(PowerShell)再重试。
102
108
 
109
+ ## 更新日志
110
+
111
+ ### v2.4.3
112
+
113
+ - **修复**:与 maid-atelier 等皮肤插件共存时,余额卡片完全不显示、控制台持续抛 `Uncaught NotFoundError: insertBefore` 的问题
114
+ - 侧栏 / 底栏插入统一改用安全插入 helper:插入前校验锚点是否仍为目标容器的已连接子节点,否则退化为 `appendChild`,永不抛异常
115
+ - `tryPlace()` 整体容错,单次失败不再中断后续重试;放置成功后在下一帧复查,自动纠正被皮肤 / React 同帧搬走的入口
116
+ - `sidebarRoot()` 增加 `[data-maid-sidebar-footer]` 皮肤标记兜底
117
+ - 感谢用户「朱鹭咲泽」提交的详细根因分析与修复补丁
118
+
119
+ ### v2.4.2 及更早
120
+
121
+ 见 [GitHub Releases](https://github.com/crazy-L118/dsh-deepseek-balance-widget/releases)。
122
+
103
123
  ## 卸载
104
124
 
105
125
  ```bash
package/README_EN.md CHANGED
@@ -9,11 +9,11 @@ A multi-provider AI balance widget for the dsh web sidebar. **DeepSeek** is buil
9
9
  ![AI balance sidebar](assets/screenshot-en.png)
10
10
 
11
11
  **Sidebar entry**
12
- - Live Balance / Today spend / Today tokens for the current provider, auto-refresh every 30 s
12
+ - Live Balance / Today Spend / Today Tokens for the current provider, auto-refresh every 30 s
13
13
  - Values follow the provider selected in the popover
14
14
 
15
15
  **Detail popover**
16
- - Header shows the current provider: a "**Switch**" menu changes to another added provider, "**×**" removes it (with confirmation)
16
+ - Header shows the current provider: a "**Switch**" menu lets you change to another added provider, and "**×**" removes it (with confirmation)
17
17
  - "**+ Add**" button (top right): add MiMo or DeepSeek
18
18
  - DeepSeek details: balance, cumulative spend, today spend, today tokens, monthly usage (monthly spend / tokens)
19
19
  - MiMo details: balance, cumulative spend, today spend / today tokens, monthly usage, and a **daily usage table** (date / tokens / requests / spend)
@@ -29,31 +29,37 @@ A multi-provider AI balance widget for the dsh web sidebar. **DeepSeek** is buil
29
29
  - Everything stays on your machine; nothing is uploaded
30
30
 
31
31
  **Version & updates**
32
- - The footer shows the current version; when a newer one exists it reads `vX → vY 更新` with one-click auto-update
32
+ - The footer shows the current version; when a newer one exists it reads `vX → vY Update` with one-click auto-update
33
33
  - On update failure an error panel shows the details (copyable) and points you to GitHub for a manual install
34
34
  - UI follows dsh's language setting (中文 / EN)
35
35
 
36
+ **Skin & third-party plugin compatibility (since v2.4.3)**
37
+ - Coexists safely with skins like maid-atelier that rebuild the sidebar DOM — the balance entry stays visible
38
+ - Inserts use a "safe insert" strategy: when the anchor is moved by the skin / React, it falls back to appending; it never throws and never breaks the retry loop
39
+ - After placement, a next-frame check re-places the entry if it was moved away
40
+ - Recognizes common skin markers (e.g. `[data-maid-sidebar-footer]`) as fallback sidebar anchors
41
+
36
42
  ## Install
37
43
 
38
44
  Requires: dsh installed (with `dsh web` working).
39
45
 
40
46
  ```bash
41
- dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.2
47
+ dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.3
42
48
  ```
43
49
 
44
50
  Installed from npm and auto-registered by dsh. **Restart `dsh web`** and the balance button appears in the sidebar.
45
51
 
46
- > **Always pin the version `@2.4.2`** (the current latest stable). Do not use `@latest` — local pnpm/npm cache or a mirror registry can resolve it to an outdated release. When a newer version is released, bump the number here.
52
+ > **Always pin the version `@2.4.3`** (the current latest stable). Do not use `@latest` — local pnpm/npm cache or a mirror registry can resolve it to an outdated release. When a newer version is released, bump the number here.
47
53
 
48
54
  Or just tell your AI:
49
55
 
50
- > Install the dsh-deepseek-balance-widget plugin for me via npm: run `dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.2`.
56
+ > Install the dsh-deepseek-balance-widget plugin for me via npm: run `dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.3`.
51
57
 
52
58
  ## Configuration
53
59
 
54
60
  On first use the plugin creates a DeepSeek entry and reads your local `DEEPSEEK_API_KEY`.
55
61
 
56
- To add MiMo, open the popover, click "+ Add", then "AI 帮我配置", and send the copied prompt to your AI. Or just tell your AI:
62
+ To add MiMo, open the popover, click "+ Add", then "AI Configure", and send the copied prompt to your AI. Or just tell your AI:
57
63
 
58
64
  > Configure dsh-deepseek-balance-widget for me.
59
65
 
@@ -73,8 +79,8 @@ Upgrade to the latest stable release on npm regardless of which older version yo
73
79
 
74
80
  ### Method 1: One-click from the popover (recommended for installed users)
75
81
 
76
- 1. Open the balance popover; the footer shows the version. When a newer one exists it reads `vX → vY 更新` (where `vY` is the highest semver version on npm).
77
- 2. Click "**更新**" (Update). The plugin pulls and installs the highest semver version from npm automatically.
82
+ 1. Open the balance popover; the footer shows the version. When a newer one exists it reads `vX → vY Update` (where `vY` is the highest semver version on npm).
83
+ 2. Click "**Update**". The plugin pulls and installs the highest semver version from npm automatically.
78
84
  3. After install you **must fully restart `dsh web`** (stop the `dsh web` process / quit the desktop app and reopen — **refreshing the browser tab is not enough**) for the new version to load.
79
85
 
80
86
  > The popover's "Update" skips the `latest` tag and installs the highest semver version on npm, so it still reaches latest even if someone lowers the `latest` tag.
@@ -82,24 +88,38 @@ Upgrade to the latest stable release on npm regardless of which older version yo
82
88
  ### Method 2: Force update from the command line (most reliable if stuck)
83
89
 
84
90
  ```bash
85
- dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.2
91
+ dsh plugin --profile web add dsh-deepseek-balance-widget@2.4.3
86
92
  ```
87
93
 
88
- **Pinning `@2.4.2`** bypasses local cache / mirror desync / a stale `latest` resolution in one step. Then **fully restart `dsh web`**.
94
+ **Pinning `@2.4.3`** bypasses local cache / mirror desync / a stale `latest` resolution in one step. Then **fully restart `dsh web`**.
89
95
 
90
96
  ### Method 3: Manual update (fallback when the command-line update fails)
91
97
 
92
98
  ```bash
93
99
  cd ~/.dsh/profiles/web
94
- npm install dsh-deepseek-balance-widget@2.4.2 # use `pnpm add` if a pnpm-lock.yaml exists in this dir
100
+ npm install dsh-deepseek-balance-widget@2.4.3 # use `pnpm add` if a pnpm-lock.yaml exists in this dir
95
101
  # verify the on-disk version actually changed
96
102
  cat node_modules/dsh-deepseek-balance-widget/package.json | grep '"version"'
97
103
  ```
98
104
 
99
- Once it prints `2.4.2`, **fully restart `dsh web`**.
105
+ Once it prints `2.4.3`, **fully restart `dsh web`**.
100
106
 
101
107
  > If the popover / command-line update keeps failing (version never changes), an agent host (e.g. WorkBuddy) is likely injecting a file-deletion guard via `NODE_OPTIONS`, which makes pnpm/npm abort during updates. Run the command in a **plain terminal** (not through the agent), or unset `NODE_OPTIONS` first (PowerShell: `set NODE_OPTIONS=`) and retry.
102
108
 
109
+ ## Changelog
110
+
111
+ ### v2.4.3
112
+
113
+ - **Fixed**: the balance card not showing at all (with constant `Uncaught NotFoundError: insertBefore` in the console) when running alongside skins such as maid-atelier
114
+ - Sidebar / toolbar insertion now goes through a safe-insert helper: it verifies the anchor is still a connected child of the target and falls back to `appendChild` otherwise — it never throws
115
+ - `tryPlace()` is fully guarded, so a single failure no longer kills retries; a next-frame check re-places the entry if the skin / React moved it in the same tick
116
+ - `sidebarRoot()` gained a `[data-maid-sidebar-footer]` skin-marker fallback
117
+ - Thanks to user「朱鹭咲泽」for the detailed root-cause analysis and fix patch
118
+
119
+ ### v2.4.2 and earlier
120
+
121
+ See [GitHub Releases](https://github.com/crazy-L118/dsh-deepseek-balance-widget/releases).
122
+
103
123
  ## Uninstall
104
124
 
105
125
  ```bash
package/lib/client.js CHANGED
@@ -447,7 +447,7 @@ window.__ModuleLoader__.load({
447
447
  function sidebarRoot() {
448
448
  const column = document.querySelector('[data-pane="sidebar"], [class*="sidebarCol"]');
449
449
  if (column === null) return void 0;
450
- return column.querySelector('[class*="logoRow"]')?.parentElement ?? column.firstElementChild;
450
+ return column.querySelector("[data-maid-sidebar-footer]") ?? column.querySelector('[class*="logoRow"]')?.parentElement ?? column.firstElementChild;
451
451
  }
452
452
 
453
453
  /** Try to locate the bottom toolbar that holds Settings/Download/Call icons. */
@@ -506,6 +506,19 @@ window.__ModuleLoader__.load({
506
506
  return entry;
507
507
  }
508
508
 
509
+ /** Insert before `before` when it is a connected child of `parent`; otherwise append.
510
+ * Never throws: React and skins move these nodes during reconciliation. */
511
+ function safeInsertTo(parent, node, before) {
512
+ if (parent === void 0 || parent === null) return false;
513
+ try {
514
+ if (before !== void 0 && before !== null && before.parentNode === parent && before.isConnected) parent.insertBefore(node, before);
515
+ else parent.appendChild(node);
516
+ return true;
517
+ } catch (e) {
518
+ try { parent.appendChild(node); return true; } catch (e2) { return false; }
519
+ }
520
+ }
521
+
509
522
  /** Re-insert the entry after the New Session row (sidebar mode). */
510
523
  function placeSidebar(root, entry) {
511
524
  const button = newSessionButton(root);
@@ -514,7 +527,7 @@ window.__ModuleLoader__.load({
514
527
  const row = button.closest('[class*="logoRow"]');
515
528
  const base = row !== null && row.parentElement === root ? row : button;
516
529
  const anchor = base.nextElementSibling ?? null;
517
- root.insertBefore(entry, anchor);
530
+ return safeInsertTo(root, entry, anchor);
518
531
  }
519
532
  return true;
520
533
  }
@@ -524,17 +537,10 @@ window.__ModuleLoader__.load({
524
537
  if (toolbar === void 0 || toolbar === null) return false;
525
538
  if (entry.parentElement === toolbar) return true;
526
539
  const settingsSlot = toolbar.querySelector("[data-slot='sidebar.settings']");
527
- if (settingsSlot !== null) {
528
- toolbar.insertBefore(entry, settingsSlot);
529
- return true;
530
- }
540
+ if (settingsSlot !== null) return safeInsertTo(toolbar, entry, settingsSlot);
531
541
  const settingsBtn = toolbar.querySelector('button[aria-label="设置"], button[aria-label="Settings"], button[title="设置"], button[title="Settings"]');
532
- if (settingsBtn !== null && settingsBtn.parentElement === toolbar) {
533
- toolbar.insertBefore(entry, settingsBtn);
534
- } else {
535
- toolbar.appendChild(entry);
536
- }
537
- return true;
542
+ if (settingsBtn !== null && settingsBtn.parentElement === toolbar) return safeInsertTo(toolbar, entry, settingsBtn);
543
+ return safeInsertTo(toolbar, entry, null);
538
544
  }
539
545
 
540
546
  /** Map a currency code to a display symbol. */
@@ -1584,7 +1590,7 @@ window.__ModuleLoader__.load({
1584
1590
  let mode = "toolbar";
1585
1591
  let placed = false;
1586
1592
 
1587
- const tryPlace = () => {
1593
+ const tryPlaceInner = () => {
1588
1594
  if (root !== void 0 && !root.isConnected) { rootObserver.disconnect(); root = void 0; placed = false; }
1589
1595
  if (placed) {
1590
1596
  if (document.body.contains(entry)) return;
@@ -1606,9 +1612,16 @@ window.__ModuleLoader__.load({
1606
1612
  placed = placeSidebar(root, entry);
1607
1613
  }
1608
1614
  }
1609
- if (placed) rootObserver.observe(root, { childList: true, subtree: true });
1615
+ if (placed) {
1616
+ rootObserver.observe(root, { childList: true, subtree: true });
1617
+ // Retry once off-frame: skins/React may move the anchor in the same tick.
1618
+ requestAnimationFrame(() => { if (!document.body.contains(entry)) tryPlace(); });
1619
+ }
1610
1620
  };
1611
1621
 
1622
+ // Never let a single failed insertion kill the retry loop.
1623
+ const tryPlace = () => { try { tryPlaceInner(); } catch { /* retry on next mutation */ } };
1624
+
1612
1625
  const waitObserver = new MutationObserver(() => tryPlace());
1613
1626
  waitObserver.observe(document.body, { childList: true, subtree: true });
1614
1627
  const rootObserver = new MutationObserver(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-deepseek-balance-widget",
3
- "version": "2.4.2",
3
+ "version": "2.4.3",
4
4
  "type": "module",
5
5
  "description": "Multi-provider AI balance widget for the dsh web sidebar: a live, auto-refreshing balance pill plus a detail popover listing DeepSeek and any added providers (MiMo etc.). Keys are stored per-machine in ~/.dsh/ai-balances.json and resolved from the local credential seam, never hardcoded.",
6
6
  "keywords": [