dsh-workbuddy-bridge 0.1.0 → 0.2.0

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
@@ -7,8 +7,9 @@
7
7
  <p><em>WorkBuddy desktop models in DeepSeek Harness</em></p>
8
8
 
9
9
  <p>
10
- <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-Plugin-4176E6?style=flat" alt="DeepSeek Harness Plugin"></a>
10
+ <a href="https://www.npmjs.com/package/dsh-workbuddy-bridge"><img src="https://img.shields.io/npm/v/dsh-workbuddy-bridge?style=flat" alt="npm"></a>
11
11
  <a href="https://github.com/zlZayn/dsh-workbuddy-bridge/actions/workflows/ci.yml"><img src="https://github.com/zlZayn/dsh-workbuddy-bridge/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
12
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-Plugin-4176E6?style=flat" alt="DeepSeek Harness Plugin"></a>
12
13
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT 许可证"></a>
13
14
  </p>
14
15
 
@@ -23,184 +24,109 @@
23
24
  > **凭据不出本机**:登录状态取自 WorkBuddy 桌面 App 自己的凭据文件,插件只在本机留一份加密副本;
24
25
  > 浏览器半边拿不到令牌,界面里也永远不出现凭据原文。
25
26
 
26
- 国内版 **WorkBuddy** 与国际版 **WorkBuddy AI** 并存:装哪个就出现哪个模型分组,两个都装就两组并排,
27
+ 国内版 **WorkBuddy** 与国际版 **WorkBuddy AI** 并存:装哪个 App 就出现哪个模型分组,两个都装就两组并排,
27
28
  各自用自己的账号与积分。模型直接出现在 DSH 的模型选择器里,不必为它单独配一个 provider。
28
29
 
29
30
  <p align="center">
30
- <img src="assets/1.png" alt="WorkBuddy 模型出现在 DSH 模型选择器中" width="330">
31
+ <img src="assets/1.png" alt="WorkBuddy 模型出现在 DSH 模型选择器中" width="300">
31
32
  <br>
32
- <em>国内版在模型选择器中自成一组(含积分倍率与促销徽章),与 DSH 自带分组并排;装国际版则出现「WorkBuddy AI」组。</em>
33
+ <em>国内版在模型选择器中自成一组,模型名后直接跟积分倍率与促销徽章;装国际版则出现「WorkBuddy AI」组。</em>
33
34
  </p>
34
35
 
35
- ## 能力
36
-
37
- - **开箱即用**:装完启用,模型分组自己出现,没有必填项。
38
- - **两版互不串号**:国内版是「WorkBuddy」分组、国际版是「WorkBuddy AI」分组,模型、账号与积分互不混用;
39
- **各自只跟随自己那版 App 的登录状态** —— 退出其中一版,对应分组消失,另一版不受影响。
40
- - **图片输入**:多数模型可直接粘贴或拖入图片(GLM-5.3-Flash、GLM-5.2、DeepSeek-V4 系列等);
41
- 少数纯文字模型(如 GLM-5.1)会明确说明不支持。
42
- - **推理档位**:上游声明了档位的模型直接可选(如 GLM-5.3 / GLM-5.3-Flash 的 low / high / max);
43
- 没声明的模型可在 Web 与 Desktop 上**手动检测**(见[为什么是手动检测](#为什么是手动检测))。
44
- 未检测或没有可用档位的模型继续用 WorkBuddy 的默认档位。
45
- - **模型显隐**:卡片的「模型」标签里勾选哪些模型出现在选择器里;**按登录账号分别保存**,
46
- 切换账号自动切换各自的配置。隐藏只影响可选择性,**已在用该模型的会话照常继续**。
47
- - **账号与积分**:插件页里看账号、令牌有效期(自动续期)、剩余积分与模型优惠,可手动刷新模型列表,
48
- 并看到当前列表来自上游还是内置兜底。
49
- - **费率与促销**:模型名后直接跟积分倍率(如 `GLM-5.2 · x0.79`)与促销徽章(限时免费 / 夜间折扣),
50
- `/model` 弹窗与输入框下拉都能看到。倍率只是显示,不影响请求。
51
- - **企业账号**:国内版企业账号走企业专用计费接口读周期额度,卡片显示「企业额度」与周期重置时间。
52
- - **三种界面**:Web / Desktop / TUI 都能跑;只有 TUI 不提供手动检测。
53
- - **插件页里以显示名出现**:`DSH WorkBuddy Bridge`(中英界面同名),标题下面另有一行代码体写着包名
54
- `dsh-workbuddy-bridge` —— 两处都要能对上,才不会在插件列表里认错。
36
+ ## 它能做什么
55
37
 
56
- ## 安装
38
+ - **开箱即用** —— 装完启用,模型分组自己出现,没有必填项。
39
+ - **两版互不串号** —— 国内版是「WorkBuddy」分组、国际版是「WorkBuddy AI」分组;模型、账号与积分互不混用,
40
+ 各自只跟随自己那版 App 的登录状态。退出其中一版,对应分组消失,另一版不受影响。
41
+ - **推理档位** —— 上游声明了档位的模型直接可选;没声明的模型可以在插件页里**手动检测**
42
+ (见[为什么是手动检测](#为什么是手动检测))。未检测或没有可用档位的模型继续用 WorkBuddy 的默认档位。
43
+ - **模型显隐** —— 卡片的「模型」标签里勾选哪些模型出现在选择器里,按登录账号分别保存;
44
+ 隐藏只影响可选择性,已在用该模型的会话照常继续。
45
+ - **积分与账户** —— 插件页里看登录账号、剩余积分、各套餐余量,并可手动刷新模型列表。
46
+ - **图片输入** —— 多数模型可直接粘贴或拖入图片;少数纯文字模型会明确说明不支持。
47
+ - **三种界面** —— Web / Desktop / TUI 都能跑;只有 TUI 不提供手动检测。
57
48
 
58
- ### 前置
49
+ <p align="center">
50
+ <img src="assets/2.png" alt="插件详情页:配置表单与两张状态卡片" width="560">
51
+ <br>
52
+ <em>插件页里的样子:上面是配置表单,下面两张卡片各跟随自己 App 的登录状态。</em>
53
+ </p>
59
54
 
60
- - 已安装并登录 **WorkBuddy 桌面 App**(国际版为 WorkBuddy AI App)。插件复用 App 的登录状态,
61
- 账号切换自动跟随;两版互不影响。
62
- - DSH 的版本范围以 [package.json](package.json) 的 `engines` 与 `peerDependencies` 为准 —— 本仓只跟 **DSH `0.1.7` 线**。
63
- - Node 22+(同上,真源是 `engines.node`)。
55
+ ## 安装
64
56
 
65
- ### 从 npm 安装
57
+ 前置只有一条:已安装并登录 **WorkBuddy 桌面 App**(国际版为 WorkBuddy AI App)—— 插件复用 App 的登录状态,
58
+ 账号切换自动跟随。
66
59
 
67
60
  ```sh
68
61
  dsh plugin --profile web add dsh-workbuddy-bridge
69
62
  dsh web
70
63
  ```
71
64
 
72
- ### 从源码安装
65
+ Desktop 与 TUI 把 `--profile web` 换成 `desktop` / `dsh-tui` 即可(TUI 需终端插件
66
+ `@deepseek-harness-tui/dsh-tui` ≥ `0.10.0-beta.5`,且用 pnpm 11 安装,详见其文档)。
67
+
68
+ 也可以从源码安装:
73
69
 
74
70
  ```sh
75
71
  git clone https://github.com/zlZayn/dsh-workbuddy-bridge.git
76
72
  cd dsh-workbuddy-bridge
77
73
  pnpm install && pnpm build
78
-
79
74
  dsh plugin --profile web add "$PWD"
80
- dsh web
81
75
  ```
82
76
 
83
- ### 三种界面
84
-
85
- ```sh
86
- # Desktop(DSH Desktop 桌面版)
87
- dsh plugin --profile desktop add dsh-workbuddy-bridge
88
- dsh --profile desktop
89
- ```
90
-
91
- ```sh
92
- # TUI(终端界面)
93
- dsh plugin --profile dsh-tui add dsh-workbuddy-bridge
94
- dsh --profile dsh-tui
95
- ```
96
-
97
- > **TUI 的版本搭配**:终端界面插件 `@deepseek-harness-tui/dsh-tui` 需 **`0.10.0-beta.5` 及以上** ——
98
- > 更早的版本装了本插件会启动失败,报 `events is not iterable`。先用 TUI 自带的方式把壳升上去,再装本插件。
99
-
100
- > **TUI 的 pnpm**:`dsh-tui` profile 需用 pnpm 11 安装(PATH 里是其他版本会报 `ERR_PNPM_UNEXPECTED_STORE`,
101
- > 用 `npx pnpm@11` 即可)。
102
-
103
- ### 发现与安装
77
+ ## 插件页
104
78
 
105
- - **GitHub**:[`zlZayn/dsh-workbuddy-bridge`](https://github.com/zlZayn/dsh-workbuddy-bridge)
106
- - 仓库带 GitHub topic `dsh-plugin`,插件市场据此自动发现。
79
+ 侧边栏 **插件(Plugins)** → 已安装 → 点 **DSH WorkBuddy Bridge** 进详情页。配置区就在描述下面,直接可改,保存即生效:
107
80
 
108
- ## 版本兼容
81
+ - **登录文件路径**(国内版 / 国际版)—— 留空即用 App 自己的位置,一般不用填。
82
+ - **允许推理档位检测**、**使用上游声明的最大上下文窗口** —— 两个开关,默认够用。
109
83
 
110
- - 本仓只支持 **DSH `0.1.7` 线**(实测在 `0.1.7-rc.2` 上通过);下限见 [package.json](package.json) 的 `engines.dsh`,本文不重抄。
111
- - **不提供跨代兼容**:宿主换线时本仓跟着抬下限,不在一份代码里同时伺候两条线。
112
- - 本仓**不查宿主版本号**:它按宿主声明的契约注册(槽、服务、配置接缝),没有防御性包装;
113
- 接缝缺席时对应功能静默不出现,不会拖垮界面。
114
-
115
- ## 配置
116
-
117
- 侧边栏 **插件(Plugins)** →「已安装(Installed)」→ 点插件名进详情页 ——
118
- **配置区就在描述下面,直接可改**,那一行上没有第二个 Configure 步骤:
119
-
120
- - **配置表单**:`authFile`(国内版登录文件路径)、`authFileAI`(国际版)、**允许推理档位检测**、
121
- **使用上游声明的最大上下文窗口**。前两项留空即用 App 自己的位置。
122
- - **两张卡片**:国内版与国际版各一张,各显示自己账号的信息。账号、令牌有效期与模型列表来源常驻展开区顶部,
123
- 下面三个标签按「读者要做什么」划分:
124
- - **积分**:合计、周期重置与各套餐余量,一处读完。
125
- - **模型**:完整目录一张表 —— **模型显隐**勾选、上下文窗口、积分倍率与促销徽章。
126
- - **检测**:推理档位检测,一模型一行;没有可检测的模型时这一页为空。
84
+ 配置改动立即生效,不需要重启;卡片上的实时状态(账号、积分、模型列表)则来自下面的两张卡。
127
85
 
128
86
  <p align="center">
129
- <img src="assets/2.png" alt="插件详情页:配置表单与两张状态卡片" width="480">
87
+ <img src="assets/6.png" alt="模型标签:显隐、窗口、倍率" width="300">
88
+ <img src="assets/7.png" alt="检测标签:推理档位检测" width="300">
130
89
  <br>
131
- <em>配置表单与两张卡片上下排列;国内版与国际版各一张,各自跟随自己 App 的登录状态。</em>
90
+ <em>展开「WorkBuddy(国内版)」卡片:左「模型」标签管理显隐、看窗口与倍率;右「检测」标签一模型一行,点「开始检测」确认它接受哪些推理档位,结果也回写到模型选择器里。</em>
132
91
  </p>
133
92
 
134
93
  <p align="center">
135
- <img src="assets/3.png" alt="积分标签:合计与套餐余量" width="420">
136
- <img src="assets/6.png" alt="模型标签:显隐、窗口、倍率" width="420">
137
- <img src="assets/7.png" alt="检测标签:推理档位检测" width="420">
94
+ <img src="assets/3.png" alt="积分标签:合计与套餐余量" width="640">
138
95
  <br>
139
- <em>卡片展开分三个标签:积分(合计与套餐余量)、模型(显隐、窗口、倍率)、检测(推理档位)。</em>
96
+ <em>「积分」标签:合计一行,下面是各套餐余量条。</em>
140
97
  </p>
141
98
 
142
- 保存即生效。**配置改动不需要重启宿主**(配置是 volatile 引用);**改了插件代码才需要**。
143
-
144
- > 设置弹窗里的「内置插件」页是**只读清单**(名称与运行状态),没有配置入口 —— 别在那里找配置。
145
-
146
99
  ## 为什么是手动检测
147
100
 
148
- WorkBuddy 的推理档位信息分散在上游接口与客户端私有 UI 逻辑里,且模型目录变化很快。
149
- 若插件按经验给所有未声明模型补齐一套统一档位,就得持续追赶没有稳定契约的未公开逻辑。
150
-
151
- 实测还发现:有些模型**接受** `reasoning_effort` 却忽略未知值、回退到默认行为 ——
152
- 一次请求成功并不能证明某个档位真的可用。
153
-
154
- <p align="center">
155
- <img src="assets/4.png" alt="输入框模型选择器旁的「推理等级」检测控件" width="620">
156
- <br>
157
- <em>检测控件就在模型选择器旁;结果显示在模型下拉里,也回写到卡片上。</em>
158
- </p>
159
-
160
- 所以对没有声明档位的模型,Web 与 Desktop 改为**先授权、再按需检测**:先确认上游会校验这个参数,
161
- 再逐项确认哪些规范档位被接受。检测会发送少量请求、可能消耗积分;结果只表示**上游当前接受该档位**,
162
- 不承诺它改变推理效果、速度或积分消耗。
101
+ WorkBuddy 的推理档位信息分散在上游接口与客户端私有 UI 逻辑里,且模型目录变化很快;而实测有些模型
102
+ **接受** `reasoning_effort` 却忽略未知值、回退到默认行为 —— 一次请求成功并不能证明某个档位真的可用。
103
+ 所以插件不猜:先由你在配置里授权,再按需对单个模型发少量真实请求确认。检测可能消耗少量积分;
104
+ 结果只表示**上游当前接受该档位**,不承诺它改变推理效果、速度或积分消耗。
163
105
 
164
106
  ## 命令行
165
107
 
166
- ```sh
167
- dsh plugin --profile <web|desktop|dsh-tui> exec dsh-workbuddy-bridge status
168
- ```
169
-
170
- 登录状态与剩余积分;`--json` 输出机器可读格式,另有 `doctor`(诊断)与 `logout`(清理凭据)。
171
-
172
- 默认操作国内版,加 `--provider workbuddy-ai` 操作国际版:
108
+ 不改界面也能查状态:
173
109
 
174
110
  ```sh
175
- dsh plugin --profile web exec dsh-workbuddy-bridge status --provider workbuddy-ai
176
- dsh plugin --profile web exec dsh-workbuddy-bridge doctor --provider workbuddy-ai
111
+ dsh plugin --profile web exec dsh-workbuddy-bridge status # 登录状态与剩余积分
112
+ dsh plugin --profile web exec dsh-workbuddy-bridge status --json # 机器可读
113
+ dsh plugin --profile web exec dsh-workbuddy-bridge doctor # 诊断 App 发现与凭据
114
+ dsh plugin --profile web exec dsh-workbuddy-bridge logout # 清理插件自留的凭据副本
177
115
  ```
178
116
 
179
- `logout` 只删除该版插件自留的凭据副本,不动桌面 App 自己的登录,也不承诺模型分组一定消失
180
- (App 的凭据文件仍在时依然生效)。
117
+ 默认操作国内版,加 `--provider workbuddy-ai` 操作国际版。`logout` 不动桌面 App 自己的登录。
181
118
 
182
- ## 安全与边界
119
+ ## 兼容与已知限制
183
120
 
184
- - **凭据只在本机**:从 App 的凭据文件读出后,插件自留一份**静态加密**的副本;
185
- 浏览器半边永远拿不到令牌、文件路径或平台事实。
186
- - **界面里不出现凭据原文**:卡片只报账号与状态。
187
- - **只访问 WorkBuddy 自己的接口**,不代理、不转发其他流量。
188
- - 依赖的是 **WorkBuddy 客户端接口(非公开 API)**,上游改动可能使其失效;届时按
189
- 「本账号上次成功目录 → 内置目录」降级,并在卡片上标明来源与失败原因。
121
+ - 只支持 **DSH `0.1.7` 线**;下限以 [package.json](package.json) 的 `engines.dsh` 为准,不做跨代兼容。
122
+ - **凭据发现按平台**:macOS 直接支持;Windows 依次探测 Local 与 Roaming AppData(实测可用);
123
+ WSL 优先读挂载的 Windows 用户目录。找不到时用 `WORKBUDDY_AUTH_FILE`(国际版 `WORKBUDDY_AI_AUTH_FILE`)指定。
124
+ - **国际版目录来自 App 界面接口**(私有实现,上游改动可能失效);国内版走官方 CLI 同款接口。
125
+ - 无凭据时该版模型分组不再显示 —— 插件不会展示一份选了必然报错的兜底列表。
126
+ - 企业账号积分目前仅覆盖国内版。
190
127
 
191
- ## 已知限制
192
-
193
- - 在 macOS 的 DSH Web / Desktop / TUI 下验证通过。Windows 依次探测 Local 与 Roaming AppData;
194
- WSL 优先从挂载的 Windows 用户目录读取登录凭据。Windows 与 Linux 用户名不同、且 Windows 环境变量
195
- 未传入 WSL 时,用 `WORKBUDDY_AUTH_FILE`(国际版 `WORKBUDDY_AI_AUTH_FILE`)指定实际位置。
196
- - **国际版的模型目录来自 App 界面接口**:服务端按 User-Agent 分流,属私有实现,改动可能使其失效;
197
- 国内版走官方 CLI 同款接口,不受此影响。
198
- - **国际版仍未覆盖的环境**:Windows / WSL / Linux 下国际版 App 的版本读取尚未找到可靠来源,
199
- 会退回最近保存的版本或内置值。
200
- - **无凭据时的行为**:某版 App 从未登录、也没留下插件自留副本时,该版模型分组不再显示
201
- (此前国内版会显示一份内置兜底列表,但那些模型选了必然报错)。
202
- - **企业账号积分目前仅覆盖国内版**:国际版企业计费接口尚未验证,仍按个人版接口读取。
203
- - 手动检测只在 Web 与 Desktop 提供,TUI 没有。
128
+ 设计取舍 → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md);发版流程 → [docs/PUBLISHING.md](docs/PUBLISHING.md);
129
+ 维护者文档地图 → [AGENTS.md](AGENTS.md)。
204
130
 
205
131
  ## 免责声明
206
132
 
@@ -216,11 +142,4 @@ dsh plugin --profile web exec dsh-workbuddy-bridge doctor --provider workbuddy-a
216
142
 
217
143
  ## 许可
218
144
 
219
- [MIT](LICENSE)。
220
-
221
- ## 贡献
222
-
223
- 报缺陷请附 DSH 版本、插件版本与复现步骤;提功能前先翻 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) 看设计取舍。
224
-
225
- 设计取向 → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md);发布流程与版本号判定 → [docs/PUBLISHING.md](docs/PUBLISHING.md);
226
- 维护者文档地图 → [AGENTS.md](AGENTS.md)。
145
+ [MIT](LICENSE)。
package/README_en.md CHANGED
@@ -3,247 +3,161 @@
3
3
  </p>
4
4
 
5
5
  <div align="center">
6
- <p><strong>WorkBuddy desktop models in your DSH chat</strong></p>
7
- <p><em>把 WorkBuddy 桌面 App 的模型接进 DSH 对话窗口</em></p>
6
+ <p><strong>WorkBuddy desktop models in DeepSeek Harness</strong></p>
8
7
 
9
8
  <p>
10
- <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-Plugin-4176E6?style=flat" alt="DeepSeek Harness Plugin"></a>
9
+ <a href="https://www.npmjs.com/package/dsh-workbuddy-bridge"><img src="https://img.shields.io/npm/v/dsh-workbuddy-bridge?style=flat" alt="npm"></a>
11
10
  <a href="https://github.com/zlZayn/dsh-workbuddy-bridge/actions/workflows/ci.yml"><img src="https://github.com/zlZayn/dsh-workbuddy-bridge/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
11
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/DeepSeek%20Harness-Plugin-4176E6?style=flat" alt="DeepSeek Harness Plugin"></a>
12
12
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License"></a>
13
13
  </p>
14
14
 
15
15
  <p>
16
- <a href="README.md">简体中文</a> · <strong><a href="README_en.md">English</a></strong>
16
+ <strong><a href="README.md">简体中文</a></strong> · <a href="README_en.md">English</a>
17
17
  </p>
18
18
  </div>
19
19
 
20
20
  ---
21
21
 
22
22
  > [!NOTE]
23
- > **Credentials never leave your machine**: the sign-in state is read from the WorkBuddy desktop
24
- > app's own credential file and kept as one encrypted local copy. The browser half never receives
25
- > the token, and no credential text ever reaches the UI.
23
+ > **Credentials never leave this machine**: sign-in state is read from the WorkBuddy desktop app's own
24
+ > credential file and kept as one encrypted local copy; the browser half never sees a token, and none
25
+ > ever appears in the UI.
26
26
 
27
- The CN **WorkBuddy** and the international **WorkBuddy AI** apps live side by side: whichever you
28
- have installed shows up as its own model group, and both installed shows both groups, each with its
29
- own account and credit. The models appear directly in the DSH model picker — no separate provider to configure.
27
+ The CN **WorkBuddy** and the international **WorkBuddy AI** coexist: install one app and its model group
28
+ appears; install both and the two groups sit side by side, each with its own account and credit. The
29
+ models appear directly in the DSH model picker — no separate provider to configure.
30
30
 
31
31
  <p align="center">
32
- <img src="assets/1.png" alt="WorkBuddy models in the DSH model picker" width="330">
32
+ <img src="assets/1.png" alt="WorkBuddy models in the DSH model picker" width="300">
33
33
  <br>
34
- <em>The CN version forms its own group in the model picker (with credit rates and promo badges), beside DSH's
35
- own groups; installing the international version adds a "WorkBuddy AI" group the same way.</em>
34
+ <em>The CN version forms its own group in the model picker, each model carrying its credit rate and promo
35
+ badge; installing the international version adds a "WorkBuddy AI" group the same way.</em>
36
36
  </p>
37
37
 
38
- ## Capabilities
39
-
40
- - **Works out of the box**: install and enable — the model groups appear on their own, with nothing required to fill in.
41
- - **The two versions never mix**: the CN app is the "WorkBuddy" group and the international one is "WorkBuddy AI";
42
- models, accounts, and credit stay separate. **Each group follows only its own app's sign-in** — sign out of one
43
- and that group disappears, leaving the other untouched.
44
- - **Image input**: most models accept pasted or dropped images (GLM-5.3-Flash, GLM-5.2, the DeepSeek-V4 series, and more);
45
- the few text-only models (e.g. GLM-5.1) say so explicitly.
46
- - **Reasoning levels**: models that declare levels expose them directly (low / high / max on GLM-5.3 and GLM-5.3-Flash);
47
- models that do not can be **checked manually** on Web and Desktop (see [Why detection is manual](#why-detection-is-manual)).
48
- Models without a check result or usable levels keep WorkBuddy's default.
49
- - **Model visibility**: the card's "Models" tab selects which models appear in the picker; the choice is
50
- **saved per signed-in account** and follows account switches. Hiding only affects pickability — **chats already
51
- using that model keep working**.
52
- - **Account and credit**: the plugin page shows the account, token validity (auto-renewed), remaining credit, and model
53
- offers; it can refresh the model list and shows whether the list came from the upstream or the built-in fallback.
54
- - **Rates and promos**: each model name carries its credit multiplier (e.g. `GLM-5.2 · x0.79`) and promo badges
55
- (limited-time free / night discount) in both the `/model` popup and the composer dropdown. The rate is display-only.
56
- - **Enterprise accounts**: CN enterprise accounts read their cycle quota from the enterprise billing endpoint, and the
57
- card shows an "enterprise quota" row with the reset time.
58
- - **The plugin page shows a display name**: `DSH WorkBuddy Bridge` (the same in both UI languages), with the
59
- package name `dsh-workbuddy-bridge` on the code-style line beneath it.
38
+ ## What it does
39
+
40
+ - **Zero configuration** — install, enable, and the model group appears by itself.
41
+ - **The two versions never cross** — "WorkBuddy" for the CN app, "WorkBuddy AI" for the international one;
42
+ models, accounts and credit stay separate, and each group follows its own app's sign-in. Sign out of one
43
+ and its group disappears while the other is unaffected.
44
+ - **Reasoning levels** — models that declare levels expose them directly; the rest can be **checked manually**
45
+ on the plugin page (see [Why detection is manual](#why-detection-is-manual)). Unchecked models keep
46
+ WorkBuddy's default level.
47
+ - **Model visibility** — tick which models appear in the picker on the card's "Models" tab; saved per
48
+ signed-in account. Hiding only affects pickability — chats already using a hidden model keep working.
49
+ - **Credit and account** — the plugin page shows the signed-in account, remaining credit and per-package
50
+ allowances, with a manual model-list refresh.
51
+ - **Image input** — most models accept pasted or dropped images; the few text-only models say so explicitly.
52
+ - **Three surfaces** — Web, Desktop and TUI all work; only the TUI lacks manual detection.
60
53
 
61
- ## Install
62
-
63
- ### Prerequisites
54
+ <p align="center">
55
+ <img src="assets/2.png" alt="Plugin detail page: the configuration form and the two status cards" width="560">
56
+ <br>
57
+ <em>The plugin page: the configuration form on top, two cards below, each following its own app's sign-in.</em>
58
+ </p>
64
59
 
65
- - The **WorkBuddy desktop app** is installed and signed in (WorkBuddy AI for the international version). The plugin
66
- reuses the app's sign-in state and follows account switches; the two versions do not affect each other.
67
- - The DSH version range is whatever [package.json](package.json) declares in `engines` and `peerDependencies` —
68
- this repository tracks the **DSH `0.1.7` line** only.
69
- - Node 22+ (same source: `engines.node`).
60
+ ## Install
70
61
 
71
- ### From npm
62
+ One prerequisite: the **WorkBuddy desktop app** is installed and signed in (WorkBuddy AI for the
63
+ international version) — the plugin reuses the app's sign-in state and follows account switches.
72
64
 
73
65
  ```sh
74
66
  dsh plugin --profile web add dsh-workbuddy-bridge
75
67
  dsh web
76
68
  ```
77
69
 
78
- ### From source
70
+ For Desktop and TUI swap `--profile web` for `desktop` / `dsh-tui` (the TUI needs the terminal plugin
71
+ `@deepseek-harness-tui/dsh-tui` ≥ `0.10.0-beta.5`, installed with pnpm 11 — see its docs).
72
+
73
+ Or from source:
79
74
 
80
75
  ```sh
81
76
  git clone https://github.com/zlZayn/dsh-workbuddy-bridge.git
82
77
  cd dsh-workbuddy-bridge
83
78
  pnpm install && pnpm build
84
-
85
79
  dsh plugin --profile web add "$PWD"
86
- dsh web
87
- ```
88
-
89
- ### Other interfaces
90
-
91
- ```sh
92
- # Desktop (the DSH Desktop app)
93
- dsh plugin --profile desktop add dsh-workbuddy-bridge
94
- dsh --profile desktop
95
- ```
96
-
97
- ```sh
98
- # TUI (terminal UI)
99
- dsh plugin --profile dsh-tui add dsh-workbuddy-bridge
100
- dsh --profile dsh-tui
101
80
  ```
102
81
 
103
- > **TUI version pairing**: the terminal UI package `@deepseek-harness-tui/dsh-tui` must be **`0.10.0-beta.5` or newer** —
104
- > older versions fail at startup with `events is not iterable` once this plugin is installed. Update the shell first.
82
+ ## The plugin page
105
83
 
106
- > **TUI and pnpm**: the `dsh-tui` profile needs pnpm 11 (a different pnpm on PATH fails with
107
- > `ERR_PNPM_UNEXPECTED_STORE` — use `npx pnpm@11`).
84
+ Sidebar **Plugins** → installed → click **DSH WorkBuddy Bridge**. The configuration area sits right under the
85
+ description, editable in place, saved immediately:
108
86
 
109
- ### Discovery
87
+ - **Sign-in file paths** (CN / international) — leave blank to use the app's own location; usually unnecessary.
88
+ - **Allow reasoning-level detection** and **use the largest declared context window** — two switches, defaults are fine.
110
89
 
111
- - **GitHub**: [`zlZayn/dsh-workbuddy-bridge`](https://github.com/zlZayn/dsh-workbuddy-bridge)
112
- - The repository carries the GitHub topic `dsh-plugin`, which the plugin market uses for discovery.
113
-
114
- ## Version compatibility
115
-
116
- - This repository supports the **DSH `0.1.7` line** only, verified on `0.1.7-rc.2`; the floor lives in
117
- [package.json](package.json) (`engines.dsh`) and is not copied here.
118
- - **No cross-generation compatibility**: when the host moves lines, this repository moves its floor with it rather
119
- than serving two lines from one codebase.
120
- - The plugin **never probes the host version**: it registers against the contracts the host declares (slots, services,
121
- the configuration seam) with no defensive wrappers. Where a seam is absent the corresponding feature quietly does not
122
- appear, and nothing else is dragged down with it.
123
-
124
- ## Configuration
125
-
126
- Sidebar **Plugins** → "Installed" → click the plugin name to open its detail page — **the configuration area sits right
127
- under the description and is editable in place**, with no second Configure step on that row:
128
-
129
- - **Configuration form**: `authFile` (CN sign-in file), `authFileAI` (international), **allow reasoning-level detection**,
130
- and **use the largest context window the upstream declares**. Leave the first two blank to use the app's own location.
131
- - **Two cards**: one per version, each reporting its own account. The account, token validity and catalog source
132
- sit above the tabs; the three tabs below split by what a reader came to do:
133
- - **Credits**: total, cycle reset, and per-package allowances in one place.
134
- - **Models**: the full catalog in one table — **visibility** checkboxes, context windows, credit rates and badges.
135
- - **Detection**: reasoning-level detection, one row per model; empty when nothing needs detecting.
90
+ Configuration takes effect immediately — no restart needed. The live state on the cards (account, credit,
91
+ model list) comes from the two cards below.
136
92
 
137
93
  <p align="center">
138
- <img src="assets/2.png" alt="Plugin detail page: the configuration form and the two status cards" width="480">
94
+ <img src="assets/6.png" alt="Models tab: visibility, windows, rates" width="300">
95
+ <img src="assets/7.png" alt="Detection tab: reasoning-level detection" width="300">
139
96
  <br>
140
- <em>The configuration form sits above the two cards — one per version, each following its own app's sign-in.</em>
97
+ <em>Expanding the "WorkBuddy (CN)" card: the Models tab (left) manages visibility and shows windows and
98
+ rates; the Detection tab (right) is one row per model — press Detect to confirm which reasoning levels
99
+ it accepts, and the results also land in the model picker.</em>
141
100
  </p>
142
101
 
143
102
  <p align="center">
144
- <img src="assets/3.png" alt="Credits tab: total and per-package allowances" width="420">
145
- <img src="assets/6.png" alt="Models tab: visibility, windows, rates" width="420">
146
- <img src="assets/7.png" alt="Detection tab: reasoning-level detection" width="420">
103
+ <img src="assets/3.png" alt="Credits tab: total and per-package allowances" width="640">
147
104
  <br>
148
- <em>Expanding a card shows three tabs: Credits (total and per-package), Models (visibility, windows, rates), and Detection (reasoning levels).</em>
105
+ <em>The Credits tab: the total on one line, each package's allowance as a bar below.</em>
149
106
  </p>
150
107
 
151
- Saving takes effect immediately. **Configuration changes do not need a host restart** (configuration is a volatile
152
- reference); **changing the plugin's code does**.
153
-
154
- > The "Built-in Plugins" page in the settings dialog is a **read-only inventory** (name and runtime status) with no
155
- > configuration entry — do not look for configuration there.
156
-
157
108
  ## Why detection is manual
158
109
 
159
- WorkBuddy's reasoning-level information is split between upstream API responses and private UI logic in the client,
160
- while the model catalog changes quickly. Filling in one uniform set of levels for every undeclared model would mean
161
- chasing unpublished product logic with no stable contract.
110
+ WorkBuddy's reasoning-level information is scattered across upstream endpoints and private client UI logic,
111
+ and the model catalog changes fast. Worse, testing showed some models **accept** `reasoning_effort` but
112
+ silently ignore unknown values — one successful request does not prove a level actually works. So the plugin
113
+ does not guess: you authorize detection in the configuration first, then each model is confirmed with a few
114
+ real requests on demand. Detection may consume a small amount of credit; a result only means **the upstream
115
+ currently accepts that level** — it does not promise any change in quality, speed, or cost.
162
116
 
163
- Testing also found that some models **accept** `reasoning_effort` while ignoring unknown values and falling back to
164
- their default — so one successful request does not prove that a level is actually usable.
117
+ ## Command line
165
118
 
166
- <p align="center">
167
- <img src="assets/4.png" alt="The reasoning-level control beside the composer's model picker" width="620">
168
- <br>
169
- <em>The control sits next to the model picker; results land in the model dropdown and are written back to the card.</em>
170
- </p>
171
-
172
- For models without declared levels, Web and Desktop therefore use **authorize first, then detect on demand**: confirm
173
- that the upstream validates the parameter, then check which standard levels it accepts. Detection sends a few requests
174
- and may consume credit; the result means only that **the upstream currently accepts that level** — it does not promise
175
- a change in reasoning quality, speed, or credit use.
176
-
177
- ## CLI
119
+ Check status without the UI:
178
120
 
179
121
  ```sh
180
- dsh plugin --profile <web|desktop|dsh-tui> exec dsh-workbuddy-bridge status
122
+ dsh plugin --profile web exec dsh-workbuddy-bridge status # sign-in state and credit
123
+ dsh plugin --profile web exec dsh-workbuddy-bridge status --json # machine-readable
124
+ dsh plugin --profile web exec dsh-workbuddy-bridge doctor # diagnose app discovery and credentials
125
+ dsh plugin --profile web exec dsh-workbuddy-bridge logout # remove the plugin's local credential copy
181
126
  ```
182
127
 
183
- Sign-in state and remaining credit; `--json` for machine-readable output, plus `doctor` (diagnostics) and `logout`
184
- (credential cleanup).
128
+ Targets the CN version by default; add `--provider workbuddy-ai` for the international one. `logout` does not
129
+ touch the desktop app's own sign-in.
185
130
 
186
- Both target the CN version by default; add `--provider workbuddy-ai` for the international one:
131
+ ## Compatibility and known limits
187
132
 
188
- ```sh
189
- dsh plugin --profile web exec dsh-workbuddy-bridge status --provider workbuddy-ai
190
- dsh plugin --profile web exec dsh-workbuddy-bridge doctor --provider workbuddy-ai
191
- ```
133
+ - Supports the **DSH `0.1.7` line** only; the floor lives in [package.json](package.json) `engines.dsh` — no
134
+ cross-generation compatibility.
135
+ - **Credential discovery is per platform**: macOS supported directly; Windows probes Local then Roaming
136
+ AppData (tested working); WSL reads the mounted Windows user profile first. When nothing is found, point
137
+ `WORKBUDDY_AUTH_FILE` (international: `WORKBUDDY_AI_AUTH_FILE`) at the actual file.
138
+ - **The international catalog comes from the app's UI endpoint** (private, may break upstream); the CN version
139
+ uses the same official CLI endpoint.
140
+ - With no credentials the group does not appear — the plugin never shows a fallback list that would only error.
141
+ - Enterprise credit covers the CN version only.
192
142
 
193
- `logout` removes only that version's plugin-owned credential copy. It leaves the desktop app's own sign-in alone and
194
- does not promise the model group will disappear (the app's credential file still supplies one).
195
-
196
- ## Security and boundaries
197
-
198
- - **Credentials stay local**: read from the app's credential file, then kept as one **encrypted** plugin-owned copy.
199
- The browser half never receives the token, file paths, or platform facts.
200
- - **No credential text in the UI**: the cards report the account and status only.
201
- - **Only WorkBuddy's own endpoints are contacted** — no proxying or forwarding of other traffic.
202
- - The plugin depends on **WorkBuddy client interfaces (not a public API)**; upstream changes can break it. When that
203
- happens it degrades to "this account's last successful catalog → built-in roster" and labels the source and failure
204
- reason on the card.
205
-
206
- ## Known limitations
207
-
208
- - Verified on macOS with the DSH Web / Desktop / TUI profiles. Windows probes Local and Roaming AppData in order; WSL
209
- first reads credentials from the mounted Windows user profile. If the Windows and Linux user names differ and Windows
210
- environment variables are not forwarded into WSL, point `WORKBUDDY_AUTH_FILE` (or `WORKBUDDY_AI_AUTH_FILE`) at the
211
- actual file.
212
- - **The international version's catalog comes from the app's own interface**: the service splits it by User-Agent, a
213
- private implementation detail a server-side change can break. The CN version uses the same interface as the official
214
- CLI and is unaffected.
215
- - **International-version environments not yet covered**: on Windows / WSL / Linux no reliable source for the
216
- international app's version has been located, so the saved value or the built-in default is used.
217
- - **Behaviour with no credentials**: a version whose app was never signed in — and that left no plugin-owned copy —
218
- no longer shows a model group. (The CN version used to display a built-in fallback list, but every model on it failed
219
- when selected.)
220
- - **The enterprise credit path currently covers the CN product only**: the international enterprise billing interface is
221
- unverified, so those accounts still read through the personal endpoint.
222
- - Manual detection is available on Web and Desktop only; TUI has none.
143
+ Design notes → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md); release process → [docs/PUBLISHING.md](docs/PUBLISHING.md);
144
+ maintainer map → [AGENTS.md](AGENTS.md).
223
145
 
224
146
  ## Disclaimer
225
147
 
226
- - This project is for **personal learning and research only**, driving your own WorkBuddy account on your own machine.
227
- Do not use it commercially or beyond reasonable personal use.
228
- - Users must comply with the WorkBuddy terms of service. Any consequence of using this project (including but not limited
229
- to account restrictions, depleted credit, or service interruption) is borne by the user.
230
- - The author is not liable for any direct or indirect loss arising from the use or misuse of this project.
231
- - This project is not affiliated with, endorsed by, or sponsored by Tencent, WorkBuddy, or DeepSeek. Product names are
232
- used for compatibility description only; trademarks belong to their respective owners.
148
+ - This project is **for personal study and research only**; it drives your own WorkBuddy account on your own
149
+ machine. Do not use it commercially or beyond reasonable personal use.
150
+ - You must comply with WorkBuddy's terms of service; any consequences (account restriction, credit forfeiture,
151
+ service interruption) are your own responsibility.
152
+ - The authors accept no liability for direct or indirect loss caused by use or misuse of this project.
153
+ - Not affiliated with, nor endorsed by, Tencent, WorkBuddy, or DeepSeek; names appear only to describe
154
+ compatibility, and trademarks belong to their owners.
233
155
 
234
156
  ## Acknowledgements
235
157
 
236
- - [Sliverkiss/workbuddy2api](https://github.com/Sliverkiss/workbuddy2api) (MIT) — reference implementation of the WorkBuddy upstream protocol.
237
- - [franksong2702/dsh-codex-connect](https://github.com/franksong2702/dsh-codex-connect) (Apache-2.0) — reference for the DSH plugin structure and provider registration.
158
+ - [Sliverkiss/workbuddy2api](https://github.com/Sliverkiss/workbuddy2api) (MIT) — reference for the WorkBuddy upstream protocol.
159
+ - [franksong2702/dsh-codex-connect](https://github.com/franksong2702/dsh-codex-connect) (Apache-2.0) — reference for DSH plugin structure and provider registration.
238
160
 
239
161
  ## License
240
162
 
241
- [MIT](LICENSE).
242
-
243
- ## Contributing
244
-
245
- Bug reports should include the DSH version, the plugin version, and reproduction steps. Before proposing a feature, read
246
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design trade-offs.
247
-
248
- Design → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md); release process and version semantics → [docs/PUBLISHING.md](docs/PUBLISHING.md);
249
- maintainer doc map → [AGENTS.md](AGENTS.md).
163
+ [MIT](LICENSE).
package/icon.svg CHANGED
@@ -1,31 +1,51 @@
1
1
  <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
2
2
  <!--
3
- dsh-workbuddy-bridge 的插件页图标:与输入区那个「推理档位检测」控件**同一个字形**
4
- (src/client/probe-control.tsx 用宿主自己的 IconThinkOutlineRegular),放大到官方 36 格。
3
+ dsh-workbuddy-bridge 的插件页图标。
5
4
 
6
- **边距是关键,不是把墨迹拉满格**。量了宿主三个官方图标的内容范围:
7
- auto-review 上下 6 / 左右 8.5 voice-input 约 7.7 / 7.6 agent-team 上下 8.5–9.4 / 左右 9
8
- 即内容落在离边 6–9 之间。本文件取 7:16 格的墨迹(外接框 0.6233–15.3767)落到 7–29。
9
- scale = 22 / (15.3767 − 0.6233) = 1.4912
10
- translate = 7 − 0.6233 × 1.4912 = 6.0706
11
- 原先写的是 translate(2 2) scale(2)(内容 2–34,四周只留 2)—— 看起来就是「太大、太挤」。
5
+ 源图是维护者给的一枚 280 格徽章(圆角方块 + 青绿渐变底 + 两团柔光 + 白色标记),
6
+ 这里整组搬进官方 36 格:transform(7 7) scale(22/280) ——
7
+ 墨迹外接框 7..29,四周各留 7,落在官方三个图标的 6–9 边距窗口里。
12
8
 
13
- 线宽:组内给 1.5,落到画布约 2.24,与宿主「16 格里 1px」的视觉重量一致(1/16 × 36 = 2.25)。
9
+ 颜色是烘死的:宿主按图片渲染,currentColor 与主题变量都不起作用
10
+ (理由与取色判据同 dsh-ds-balance/icon.svg)。这里保留源图自带的品牌青绿渐变。
14
11
 
15
- 选色:图标是宿主直读的静态资源,**不跟随主题**,所以颜色只能烘死。
16
- 墨迹 #7F8287(亮暗两块主题下都落在宿主中性色附近);圆心那一点 #F59E0B
17
- (宿主 warn 档语义色,亮暗同值)—— 语义是「正在检测的那一档」。
18
- 取色判据与 dsh-ds-balance 的 icon.svg 同一套。
19
-
20
- 形状真源是宿主:组件直接渲染 IconThinkOutlineRegular,本文件是它按官方边距放大后的副本。
21
- 宿主换字形时这里要同批跟(红线 test/redlines.spec.ts 对着三处路径逐字核)。
12
+ 注意:XML 注释里不许出现连续两个连字符(浏览器会当图片解析失败,插件页静默回落成默认图形)。
22
13
  -->
23
- <g transform="translate(6.0706 6.0706) scale(1.4912)">
24
- <g stroke="#7F8287" stroke-width="1.5" fill="none">
25
- <path d="M10.7554 5.24466C13.9891 8.4783 15.3769 12.3333 13.8552 13.8551C12.3335 15.3768 8.4785 13.989 5.24478 10.7553C2.01111 7.52165 0.623307 3.66664 2.14504 2.14491C3.66676 0.623189 7.52178 2.01099 10.7554 5.24466Z" />
26
- <path d="M10.7554 10.7553C7.52178 13.989 3.66676 15.3768 2.14504 13.8551C0.623307 12.3333 2.01111 8.4783 5.24478 5.24466C8.4785 2.01099 12.3335 0.623189 13.8552 2.14491C15.3769 3.66664 13.9891 7.52165 10.7554 10.7553Z" />
14
+ <g transform="translate(7 7) scale(0.07857142857142857)">
15
+ <g clip-path="url(#clip0)">
16
+ <rect width="280" height="280" rx="60.4211" fill="url(#paint0_linear)"/>
17
+ <g filter="url(#filter0_f)">
18
+ <circle cx="88.2504" cy="244.86" r="98.5668" fill="#32E6B9" fill-opacity="0.4"/>
19
+ </g>
20
+ <g filter="url(#filter1_f)">
21
+ <circle cx="223.384" cy="290.328" r="90.0931" fill="#FFE355" fill-opacity="0.49"/>
22
+ </g>
23
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M204.15 6.89352C206.896 4.43111 207.061 4.33611 209.074 4.21524C212.336 3.97692 215.324 5.54248 220.41 10.1729C232.291 20.9692 248.834 43.1654 259.119 62.1205L263.093 69.4768L268.707 72.2672C274.126 75.0055 283.015 80.6198 286.728 83.6308C288.407 85.0191 288.642 85.0483 290.388 84.3692C298.267 81.3008 309.553 85.3675 319.508 94.9178C328.47 103.507 337.052 118.181 340.34 130.429C340.82 132.4 341.458 136.638 341.69 139.794C342.44 150.876 338.886 159.726 332.042 163.733C330.644 164.54 330.551 164.759 330.59 168.245C330.905 184.841 326.432 201.406 317.445 217.561C307.301 235.7 289.238 254.464 264.791 272.142C251.663 281.695 220.604 299.792 206.561 306.145C172.92 321.29 145.952 327.1 122.527 324.23C108.554 322.537 92.7397 317.083 83.3819 310.752C80.9182 309.049 80.5286 308.944 78.6462 309.483C68.6285 312.36 55.5086 306.447 44.3628 294.075C39.9174 289.129 32.743 276.986 30.417 270.488C25.0365 255.281 26.1061 241.558 33.273 233.363C35.1245 231.252 35.1835 231.163 34.7791 227.614C34.1112 221.804 33.808 213.206 34.1131 207.656L34.3541 202.472L26.5713 188.706C14.5194 167.262 6.8648 149.255 3.91152 135.497C2.35249 127.954 2.44923 124.607 4.36401 122.131C5.52945 120.635 9.35191 119.087 13.9599 118.236C25.5602 116.199 50.8596 118.043 79.0059 123.012L81.9295 123.517L88.3537 117.834C99.0194 108.386 106.105 103.089 119.168 94.9439C132.783 86.4254 148.148 79.4181 165.452 73.8693L171.004 72.09L174.054 64.0775C184.981 35.233 196.172 13.9675 204.15 6.89352ZM112.625 154.702C100.275 161.832 94.0999 165.397 89.5627 169.393C71.1894 185.572 64.3228 211.198 72.145 234.396C74.0767 240.125 77.642 246.3 84.7719 258.65C91.9018 270.999 95.4667 277.173 99.4619 281.711C115.641 300.084 141.267 306.95 164.466 299.128C170.194 297.197 176.369 293.631 188.719 286.501L259.76 245.486C272.109 238.356 278.284 234.791 282.821 230.796C301.194 214.617 308.061 188.99 300.239 165.792C298.307 160.063 294.742 153.889 287.612 141.54C280.482 129.19 276.917 123.015 272.922 118.478C256.743 100.104 231.116 93.2378 207.918 101.06C202.19 102.992 196.015 106.557 183.666 113.687L112.625 154.702Z" fill="url(#paint1_linear)"/>
24
+ <rect x="119.473" y="204.341" width="28.0633" height="58.2852" rx="14.0316" transform="rotate(-30 119.473 204.341)" fill="white"/>
25
+ <rect x="195.186" y="160.627" width="28.0633" height="58.2852" rx="14.0316" transform="rotate(-30 195.186 160.627)" fill="white"/>
27
26
  </g>
28
- <!-- 圆心那一点:宿主原字形的第三条路径,填色而非描边,所以跟着同一组一起缩放。 -->
29
- <path d="M8.9587 8.00025C8.9587 8.52835 8.5306 8.95655 8.0024 8.95655C7.47429 8.95655 7.04614 8.52835 7.04614 8.00025C7.04614 7.47209 7.47429 7.04395 8.0024 7.04395C8.5306 7.04395 8.9587 7.47209 8.9587 8.00025Z" fill="#F59E0B" />
30
27
  </g>
28
+ <defs>
29
+ <filter id="filter0_f" x="-104.414" y="52.1958" width="385.327" height="385.328" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
30
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
31
+ <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
32
+ <feGaussianBlur stdDeviation="47.0486" result="effect1_foregroundBlur"/>
33
+ </filter>
34
+ <filter id="filter1_f" x="56.2884" y="123.233" width="334.191" height="334.192" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
35
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
36
+ <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
37
+ <feGaussianBlur stdDeviation="38.5013" result="effect1_foregroundBlur"/>
38
+ </filter>
39
+ <linearGradient id="paint0_linear" x1="140" y1="0" x2="140" y2="280" gradientUnits="userSpaceOnUse">
40
+ <stop stop-color="#0EC8A9"/>
41
+ <stop offset="1" stop-color="#01C886"/>
42
+ </linearGradient>
43
+ <linearGradient id="paint1_linear" x1="106.647" y1="62.5482" x2="237.632" y2="289.42" gradientUnits="userSpaceOnUse">
44
+ <stop stop-color="white" stop-opacity="0.8"/>
45
+ <stop offset="0.437689" stop-color="white"/>
46
+ </linearGradient>
47
+ <clipPath id="clip0">
48
+ <rect width="280" height="280" rx="60.4211" fill="white"/>
49
+ </clipPath>
50
+ </defs>
31
51
  </svg>
package/lib/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { D as cnAppDiscovery, E as WorkBuddyAtRestKeyProvider, O as WorkBuddyUpstreamClient, X as resolveAppVersion, b as WorkBuddyCredentialStore, f as WORKBUDDY_BRIDGE_VERSION, g as FALLBACK_WORKBUDDY_MODELS, h as FALLBACK_WORKBUDDY_AI_MODELS, i as variantFor, l as readHostHeartbeat, n as CN_VARIANT, r as WORKBUDDY_VARIANTS, s as isHeartbeatProcessAlive, u as workbuddyHostHeartbeatPath } from "./variants-CFO_LIBm.js";
2
+ import { D as cnAppDiscovery, E as WorkBuddyAtRestKeyProvider, O as WorkBuddyUpstreamClient, X as resolveAppVersion, b as WorkBuddyCredentialStore, f as WORKBUDDY_BRIDGE_VERSION, g as FALLBACK_WORKBUDDY_MODELS, h as FALLBACK_WORKBUDDY_AI_MODELS, i as variantFor, l as readHostHeartbeat, n as CN_VARIANT, r as WORKBUDDY_VARIANTS, s as isHeartbeatProcessAlive, u as workbuddyHostHeartbeatPath } from "./variants-DP0Ho0Tc.js";
3
3
  import { realpathSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region src/cli/bin.ts
package/lib/client.js CHANGED
@@ -46,8 +46,8 @@ window.__ModuleLoader__.load({
46
46
  return new Intl.NumberFormat(void 0, { maximumFractionDigits: 1 }).format(percent);
47
47
  }
48
48
  //#endregion
49
- //#region \0workbuddy-css:D:\ProjectSomething\dsh-plugins\dsh-workbuddy-bridge\src\client\workbuddy.module.css.js
50
- const css$1 = "._1kHyqG_page,._1kHyqG_cards{flex-direction:column;gap:12px;display:flex}._1kHyqG_toggleRow{border-top:.5px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:flex-start;gap:16px;padding:12px 0;font-size:13px;line-height:1.5;display:flex}._1kHyqG_toggleLabel{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}._1kHyqG_toggleHint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}._1kHyqG_body{flex-direction:column;padding:4px 0 12px;display:flex}._1kHyqG_section{flex-direction:column;gap:6px;margin:12px 0;display:flex}._1kHyqG_title{color:var(--dsw-alias-label-primary);margin:0;font-size:13px;font-weight:500;line-height:1.5}._1kHyqG_row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;padding:12px 0;display:flex}._1kHyqG_summaryRow{flex-wrap:wrap;gap:4px;height:auto;min-height:28px}._1kHyqG_summaryTitle{flex:1;min-width:0}._1kHyqG_statusLine{color:var(--dsw-alias-label-tertiary);align-items:center;gap:6px;font-size:12px;line-height:1.5;display:inline-flex}._1kHyqG_text{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:1.5}._1kHyqG_dim{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}._1kHyqG_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:1.5}._1kHyqG_package{flex-direction:column;gap:8px;display:flex}._1kHyqG_packageLabel{color:var(--dsw-alias-label-secondary);justify-content:space-between;gap:8px;font-size:13px;line-height:1.5;display:flex}._1kHyqG_track{corner-shape:round;background:var(--dsw-alias-border-l3);border-radius:999px;height:8px;overflow:hidden}._1kHyqG_fill{border-radius:inherit;background:var(--dsw-alias-brand-primary);height:100%}._1kHyqG_list{border:.5px solid var(--dsw-alias-border-l1);border-radius:10px;gap:6px;min-width:0;max-height:280px;margin:0;padding:14px;display:grid;overflow:auto}._1kHyqG_modelRow{justify-content:space-between;align-items:flex-start;gap:8px;display:flex}._1kHyqG_modelMain{align-items:center;gap:8px;min-width:0;display:flex}._1kHyqG_modelStack{flex-direction:column;gap:2px;min-width:0;display:flex}._1kHyqG_name{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}._1kHyqG_modelEnd{text-align:right;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-direction:column;gap:2px;font-size:12px;line-height:1.5;display:flex}._1kHyqG_meta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}._1kHyqG_badges{flex-wrap:wrap;align-items:center;gap:6px;display:flex}._1kHyqG_sectionActions{justify-content:flex-end;display:flex}._1kHyqG_probeRow{justify-content:space-between;align-items:center;gap:8px;display:flex}._1kHyqG_probeEnd{flex:none;align-items:center;gap:8px;display:inline-flex}._1kHyqG_assist{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:8px;padding:12px;display:flex}._1kHyqG_prompt{min-width:0;color:var(--dsw-alias-label-secondary);white-space:pre-wrap;overflow-wrap:anywhere;user-select:text;flex:220px;margin:0;font-size:12px;line-height:1.6}._1kHyqG_promptRow{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-3);flex-wrap:wrap;align-items:flex-start;gap:8px;padding:8px 9px 8px 11px;display:flex}";
49
+ //#region \0workbuddy-css:/home/runner/work/dsh-workbuddy-bridge/dsh-workbuddy-bridge/src/client/workbuddy.module.css.js
50
+ const css$1 = "._8BbhmW_page,._8BbhmW_cards{flex-direction:column;gap:12px;display:flex}._8BbhmW_toggleRow{border-top:.5px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:flex-start;gap:16px;padding:12px 0;font-size:13px;line-height:1.5;display:flex}._8BbhmW_toggleLabel{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}._8BbhmW_toggleHint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}._8BbhmW_body{flex-direction:column;padding:4px 0 12px;display:flex}._8BbhmW_section{flex-direction:column;gap:6px;margin:12px 0;display:flex}._8BbhmW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:13px;font-weight:500;line-height:1.5}._8BbhmW_row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;padding:12px 0;display:flex}._8BbhmW_summaryRow{flex-wrap:wrap;gap:4px;height:auto;min-height:28px}._8BbhmW_summaryTitle{flex:1;min-width:0}._8BbhmW_statusLine{color:var(--dsw-alias-label-tertiary);align-items:center;gap:6px;font-size:12px;line-height:1.5;display:inline-flex}._8BbhmW_text{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:1.5}._8BbhmW_dim{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}._8BbhmW_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:1.5}._8BbhmW_package{flex-direction:column;gap:8px;display:flex}._8BbhmW_packageLabel{color:var(--dsw-alias-label-secondary);justify-content:space-between;gap:8px;font-size:13px;line-height:1.5;display:flex}._8BbhmW_track{corner-shape:round;background:var(--dsw-alias-border-l3);border-radius:999px;height:8px;overflow:hidden}._8BbhmW_fill{border-radius:inherit;background:var(--dsw-alias-brand-primary);height:100%}._8BbhmW_list{border:.5px solid var(--dsw-alias-border-l1);border-radius:10px;gap:6px;min-width:0;max-height:280px;margin:0;padding:14px;display:grid;overflow:auto}._8BbhmW_modelRow{justify-content:space-between;align-items:flex-start;gap:8px;display:flex}._8BbhmW_modelMain{align-items:center;gap:8px;min-width:0;display:flex}._8BbhmW_modelStack{flex-direction:column;gap:2px;min-width:0;display:flex}._8BbhmW_name{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}._8BbhmW_modelEnd{text-align:right;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-direction:column;gap:2px;font-size:12px;line-height:1.5;display:flex}._8BbhmW_meta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}._8BbhmW_badges{flex-wrap:wrap;align-items:center;gap:6px;display:flex}._8BbhmW_sectionActions{justify-content:flex-end;display:flex}._8BbhmW_probeRow{justify-content:space-between;align-items:center;gap:8px;display:flex}._8BbhmW_probeEnd{flex:none;align-items:center;gap:8px;display:inline-flex}._8BbhmW_assist{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:8px;padding:12px;display:flex}._8BbhmW_prompt{min-width:0;color:var(--dsw-alias-label-secondary);white-space:pre-wrap;overflow-wrap:anywhere;user-select:text;flex:220px;margin:0;font-size:12px;line-height:1.6}._8BbhmW_promptRow{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-3);flex-wrap:wrap;align-items:flex-start;gap:8px;padding:8px 9px 8px 11px;display:flex}";
51
51
  const tagId$1 = "dsh-workbuddy-bridge/workbuddy.module.css";
52
52
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
53
53
  const tag = document.createElement("style");
@@ -57,39 +57,39 @@ window.__ModuleLoader__.load({
57
57
  document.head.appendChild(tag);
58
58
  }
59
59
  var workbuddy_module_css_default = {
60
- "assist": "_1kHyqG_assist",
61
- "badges": "_1kHyqG_badges",
62
- "body": "_1kHyqG_body",
63
- "cards": "_1kHyqG_cards",
64
- "dim": "_1kHyqG_dim",
65
- "error": "_1kHyqG_error",
66
- "fill": "_1kHyqG_fill",
67
- "list": "_1kHyqG_list",
68
- "meta": "_1kHyqG_meta",
69
- "modelEnd": "_1kHyqG_modelEnd",
70
- "modelMain": "_1kHyqG_modelMain",
71
- "modelRow": "_1kHyqG_modelRow",
72
- "modelStack": "_1kHyqG_modelStack",
73
- "name": "_1kHyqG_name",
74
- "package": "_1kHyqG_package",
75
- "packageLabel": "_1kHyqG_packageLabel",
76
- "page": "_1kHyqG_page",
77
- "probeEnd": "_1kHyqG_probeEnd",
78
- "probeRow": "_1kHyqG_probeRow",
79
- "prompt": "_1kHyqG_prompt",
80
- "promptRow": "_1kHyqG_promptRow",
81
- "row": "_1kHyqG_row",
82
- "section": "_1kHyqG_section",
83
- "sectionActions": "_1kHyqG_sectionActions",
84
- "statusLine": "_1kHyqG_statusLine",
85
- "summaryRow": "_1kHyqG_summaryRow",
86
- "summaryTitle": "_1kHyqG_summaryTitle",
87
- "text": "_1kHyqG_text",
88
- "title": "_1kHyqG_title",
89
- "toggleHint": "_1kHyqG_toggleHint",
90
- "toggleLabel": "_1kHyqG_toggleLabel",
91
- "toggleRow": "_1kHyqG_toggleRow",
92
- "track": "_1kHyqG_track"
60
+ "assist": "_8BbhmW_assist",
61
+ "badges": "_8BbhmW_badges",
62
+ "body": "_8BbhmW_body",
63
+ "cards": "_8BbhmW_cards",
64
+ "dim": "_8BbhmW_dim",
65
+ "error": "_8BbhmW_error",
66
+ "fill": "_8BbhmW_fill",
67
+ "list": "_8BbhmW_list",
68
+ "meta": "_8BbhmW_meta",
69
+ "modelEnd": "_8BbhmW_modelEnd",
70
+ "modelMain": "_8BbhmW_modelMain",
71
+ "modelRow": "_8BbhmW_modelRow",
72
+ "modelStack": "_8BbhmW_modelStack",
73
+ "name": "_8BbhmW_name",
74
+ "package": "_8BbhmW_package",
75
+ "packageLabel": "_8BbhmW_packageLabel",
76
+ "page": "_8BbhmW_page",
77
+ "probeEnd": "_8BbhmW_probeEnd",
78
+ "probeRow": "_8BbhmW_probeRow",
79
+ "prompt": "_8BbhmW_prompt",
80
+ "promptRow": "_8BbhmW_promptRow",
81
+ "row": "_8BbhmW_row",
82
+ "section": "_8BbhmW_section",
83
+ "sectionActions": "_8BbhmW_sectionActions",
84
+ "statusLine": "_8BbhmW_statusLine",
85
+ "summaryRow": "_8BbhmW_summaryRow",
86
+ "summaryTitle": "_8BbhmW_summaryTitle",
87
+ "text": "_8BbhmW_text",
88
+ "title": "_8BbhmW_title",
89
+ "toggleHint": "_8BbhmW_toggleHint",
90
+ "toggleLabel": "_8BbhmW_toggleLabel",
91
+ "toggleRow": "_8BbhmW_toggleRow",
92
+ "track": "_8BbhmW_track"
93
93
  };
94
94
  //#endregion
95
95
  //#region src/client/panels.tsx
@@ -1278,8 +1278,8 @@ window.__ModuleLoader__.load({
1278
1278
  });
1279
1279
  }
1280
1280
  //#endregion
1281
- //#region \0workbuddy-css:D:\ProjectSomething\dsh-plugins\dsh-workbuddy-bridge\src\client\probe-control.module.css.js
1282
- const css = ".Ivd5xG_wrapper{align-items:center;display:inline-flex;position:relative}.Ivd5xG_trigger{corner-shape:round;cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:999px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex;position:relative}.Ivd5xG_trigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Ivd5xG_trigger:disabled{cursor:default;color:var(--dsw-alias-label-dimmed)}.Ivd5xG_trigger:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}.Ivd5xG_trigger[aria-busy=true] svg{transform-origin:50%;animation:1.2s linear infinite Ivd5xG_wb-probe-spin}@keyframes Ivd5xG_wb-probe-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.Ivd5xG_trigger[aria-busy=true] svg{animation:none}}.Ivd5xG_panel{isolation:isolate;z-index:1100;box-sizing:border-box;border-radius:var(--dsw-radius-lg);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:max-content;min-width:min(280px,100vw - 24px);max-width:min(360px,100vw - 24px);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-secondary);cursor:default;border:0;padding:12px;font-size:12px;line-height:1.5;position:fixed}.Ivd5xG_panel:before{z-index:-1;border-radius:inherit;background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);content:\"\";pointer-events:none;position:absolute;inset:0}.Ivd5xG_panelTitle{color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:13px;font-weight:500;line-height:1.5;display:flex}.Ivd5xG_panelTitleIcon{color:var(--dsw-alias-label-secondary);flex:none;align-items:center;display:inline-flex}.Ivd5xG_panelTitleText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.Ivd5xG_titleRule{border-top:.5px solid var(--dsw-alias-border-l2);margin:8px 0 10px}.Ivd5xG_levelsLabel{color:var(--dsw-alias-label-tertiary);margin:0 0 2px;font-size:12px;line-height:1.5}.Ivd5xG_levels{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;font-size:13px;font-weight:500;line-height:1.5}.Ivd5xG_note,.Ivd5xG_dim{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.6}.Ivd5xG_dim{margin-top:2px}.Ivd5xG_panelActions{justify-content:flex-end;gap:8px;margin-top:12px;display:flex}";
1281
+ //#region \0workbuddy-css:/home/runner/work/dsh-workbuddy-bridge/dsh-workbuddy-bridge/src/client/probe-control.module.css.js
1282
+ const css = ".EVr7sG_wrapper{align-items:center;display:inline-flex;position:relative}.EVr7sG_trigger{corner-shape:round;cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:999px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex;position:relative}.EVr7sG_trigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.EVr7sG_trigger:disabled{cursor:default;color:var(--dsw-alias-label-dimmed)}.EVr7sG_trigger:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}.EVr7sG_panel{isolation:isolate;z-index:1100;box-sizing:border-box;border-radius:var(--dsw-radius-lg);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:max-content;min-width:min(280px,100vw - 24px);max-width:min(360px,100vw - 24px);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-secondary);cursor:default;border:0;padding:12px;font-size:12px;line-height:1.5;position:fixed}.EVr7sG_panel:before{z-index:-1;border-radius:inherit;background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);content:\"\";pointer-events:none;position:absolute;inset:0}.EVr7sG_panelTitle{color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:13px;font-weight:500;line-height:1.5;display:flex}.EVr7sG_panelTitleIcon{color:var(--dsw-alias-label-secondary);flex:none;align-items:center;display:inline-flex}.EVr7sG_panelTitleText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.EVr7sG_titleRule{border-top:.5px solid var(--dsw-alias-border-l2);margin:8px 0 10px}.EVr7sG_levelsLabel{color:var(--dsw-alias-label-tertiary);margin:0 0 2px;font-size:12px;line-height:1.5}.EVr7sG_levels{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;font-size:13px;font-weight:500;line-height:1.5}.EVr7sG_note,.EVr7sG_dim{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.6}.EVr7sG_dim{margin-top:2px}.EVr7sG_panelActions{justify-content:flex-end;gap:8px;margin-top:12px;display:flex}";
1283
1283
  const tagId = "dsh-workbuddy-bridge/probe-control.module.css";
1284
1284
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1285
1285
  const tag = document.createElement("style");
@@ -1289,19 +1289,18 @@ window.__ModuleLoader__.load({
1289
1289
  document.head.appendChild(tag);
1290
1290
  }
1291
1291
  var probe_control_module_css_default = {
1292
- "dim": "Ivd5xG_dim",
1293
- "levels": "Ivd5xG_levels",
1294
- "levelsLabel": "Ivd5xG_levelsLabel",
1295
- "note": "Ivd5xG_note",
1296
- "panel": "Ivd5xG_panel",
1297
- "panelActions": "Ivd5xG_panelActions",
1298
- "panelTitle": "Ivd5xG_panelTitle",
1299
- "panelTitleIcon": "Ivd5xG_panelTitleIcon",
1300
- "panelTitleText": "Ivd5xG_panelTitleText",
1301
- "titleRule": "Ivd5xG_titleRule",
1302
- "trigger": "Ivd5xG_trigger",
1303
- "wb-probe-spin": "Ivd5xG_wb-probe-spin",
1304
- "wrapper": "Ivd5xG_wrapper"
1292
+ "dim": "EVr7sG_dim",
1293
+ "levels": "EVr7sG_levels",
1294
+ "levelsLabel": "EVr7sG_levelsLabel",
1295
+ "note": "EVr7sG_note",
1296
+ "panel": "EVr7sG_panel",
1297
+ "panelActions": "EVr7sG_panelActions",
1298
+ "panelTitle": "EVr7sG_panelTitle",
1299
+ "panelTitleIcon": "EVr7sG_panelTitleIcon",
1300
+ "panelTitleText": "EVr7sG_panelTitleText",
1301
+ "titleRule": "EVr7sG_titleRule",
1302
+ "trigger": "EVr7sG_trigger",
1303
+ "wrapper": "EVr7sG_wrapper"
1305
1304
  };
1306
1305
  //#endregion
1307
1306
  //#region src/client/probe-control.tsx
@@ -1533,6 +1532,7 @@ window.__ModuleLoader__.load({
1533
1532
  const shown = fresh ?? result;
1534
1533
  const levels = levelsLine(shown);
1535
1534
  const notValidating = shown?.validation === "non-validating";
1535
+ const lit = shown !== void 0;
1536
1536
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1537
1537
  className: probe_control_module_css_default.wrapper,
1538
1538
  ref: rootRef,
@@ -1551,7 +1551,7 @@ window.__ModuleLoader__.load({
1551
1551
  onClick: () => {
1552
1552
  setOpen(!open);
1553
1553
  },
1554
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProbeIcon, {})
1554
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProbeIcon, { lit })
1555
1555
  })
1556
1556
  }), open ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1557
1557
  ref: panelRef,
@@ -1564,7 +1564,7 @@ window.__ModuleLoader__.load({
1564
1564
  className: probe_control_module_css_default.panelTitle,
1565
1565
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1566
1566
  className: probe_control_module_css_default.panelTitleIcon,
1567
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProbeIcon, {})
1567
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProbeIcon, { lit })
1568
1568
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1569
1569
  className: probe_control_module_css_default.panelTitleText,
1570
1570
  children: model
@@ -1612,21 +1612,49 @@ window.__ModuleLoader__.load({
1612
1612
  }), document.body) : null]
1613
1613
  });
1614
1614
  }
1615
+ /** The bulb's body — the maintainer's artwork, one filled path with the base cut out. */
1616
+ const BULB_BODY = "M496 64C681.6 64 832 208.896 832 387.648c0 124.544-73.152 232.704-180.352 286.784v24.256c0 6.912-0.64 13.76-1.856 20.288a56.32 56.32 0 0 1 20.672 20.416 54.848 54.848 0 0 1 7.552 27.712v37.312c0 29.312-23.04 53.312-52.288 55.808l-2.816 0.192h-23.04c0 54.976-46.336 99.584-103.424 99.584-57.024 0-103.296-44.544-103.296-99.584h-19.776l-2.24-0.128h-3.84a58.24 58.24 0 0 1-36.48-18.432 55.808 55.808 0 0 1-14.72-37.44v-37.312c0-20.16 11.008-37.888 27.328-47.744a104.064 104.064 0 0 1-1.984-20.672v-23.744C233.6 621.056 160 512.576 160 387.584 160.064 208.96 310.4 64 496 64z m-45.632 796.288c0 24.064 20.48 43.712 46.08 43.712 25.728 0 46.144-19.712 46.208-43.52v-0.192H450.368z m-76.992-56h247.296l0.064-37.056-0.512-0.32H373.632l-0.256 37.376zM496 120.064c-154.112 0-278.656 120-278.656 267.52 0 100.8 58.624 191.68 150.208 237.44l31.104 15.68 0.064 50.56c0 3.968 0.384 7.552 0.896 10.816l0.576 1.984H467.84V704h70.4v-0.128l55.488-0.32 0.512-1.472c0.64-3.776 0.96-7.552 0.96-11.328l-0.96-50.56 31.04-15.616c91.2-45.952 149.312-136.576 149.312-236.992 0-147.584-124.544-267.648-278.656-267.648v0.128z";
1617
+ /** The bolt drawn inside the bulb once a detection has landed. */
1618
+ const BULB_BOLT = "M465.536 443.264H396.8c-8.96 0-15.168-8.192-11.968-15.872l68.288-163.84a11.904 11.904 0 0 1 4.672-5.504A13.632 13.632 0 0 1 465.024 256h115.2c9.088 0 15.36 8.448 11.904 16.128L552.32 361.344H627.2c11.008 0 16.832 11.84 9.6 19.456L453.376 571.968c-8.96 9.28-25.472 1.28-22.016-10.752l34.176-117.952z";
1615
1619
  /**
1616
- * The control's icon — the host's own reasoning glyph.
1620
+ * The control's icon: a light bulb, and the same bulb lit once a detection landed.
1617
1621
  *
1618
- * Deliberately **not** a hand-drawn shape. Every icon in this chrome is one of
1619
- * the host's, drawn on the same grid (16-unit viewBox, 1px stroke) with the same
1620
- * `currentColor` convention, so borrowing the host's artwork is the only way to
1621
- * land in the same visual language — anything original reads as foreign beside
1622
- * the model picker it sits next to.
1622
+ * Two states carry the whole story without a word:
1623
+ * - **bulb** — nothing verified yet; this is the model whose levels are still unknown.
1624
+ * - **bulb with the bolt** — a recorded result says which levels this model accepts.
1623
1625
  *
1624
- * `IconThinkOutlineRegular` is the host's semantic icon for reasoning, which is
1625
- * exactly what this control acts on. It is exported from a package this plugin
1626
- * already depends on, so it costs no new dependency edge.
1626
+ * That is why the bolt is a second path rather than decoration: the trigger has to answer
1627
+ * "is this model checked?" at a glance, in 28px, next to the host's model picker — and the
1628
+ * panel that opens from it repeats the same glyph, so trigger, panel and result read as one
1629
+ * object. The artwork is the maintainer's bulb, redrawn on the host's 16-unit grid: ink spans
1630
+ * 2..14 vertically and 3.5..12.5 horizontally (the host's own icons keep a 6–9 inset), filled
1631
+ * with `currentColor` so both themes come from the button's colour alone — no literal colour,
1632
+ * no `[data-ds-dark-theme]` selector.
1633
+ *
1634
+ * The bolt appears only for a **successful** detection (`lit`), never while a run is in
1635
+ * flight and never for a failure: a spinner-shaped claim would be answered by the tooltip,
1636
+ * which already says exactly what happened.
1627
1637
  */
1628
- function ProbeIcon() {
1629
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconThinkOutlineRegular, { size: 16 });
1638
+ function ProbeIcon({ lit }) {
1639
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1640
+ width: "16",
1641
+ height: "16",
1642
+ viewBox: "0 0 16 16",
1643
+ xmlns: "http://www.w3.org/2000/svg",
1644
+ "aria-hidden": "true",
1645
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
1646
+ transform: "translate(1.35714 1.14286) scale(0.01339286)",
1647
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1648
+ d: BULB_BODY,
1649
+ fill: "currentColor",
1650
+ fillRule: "evenodd"
1651
+ }), lit ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1652
+ d: BULB_BOLT,
1653
+ fill: "currentColor",
1654
+ fillRule: "evenodd"
1655
+ }) : null]
1656
+ })
1657
+ });
1630
1658
  }
1631
1659
  //#endregion
1632
1660
  //#region src/client/config-controller.ts
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as normalizeCredits, B as FALLBACK_CN_APP_VERSION, C as desktopAuthCandidatesFor, D as cnAppDiscovery, E as WorkBuddyAtRestKeyProvider, F as PROBE_EFFORT_CANDIDATES, G as validCliVersion, H as fallbackChatIdentity, I as probeModel, J as installedAppVersion, K as WORKBUDDY_APP_VERSION_FILENAME, L as randomSentinel, M as prepareChatBody, N as prepareInternationalChatBody, O as WorkBuddyUpstreamClient, P as regionOf, R as classifyUpstreamError, S as defaultDesktopAuthPath, T as workbuddyOwnAuthPath, U as readCliVersion, V as chatUserAgent, W as resolveChatIdentity, X as resolveAppVersion, Y as readBundleVersion, Z as validAppVersion, _ as WorkBuddyCatalog, a as WORKBUDDY_HOST_HEARTBEAT_FILENAME, b as WorkBuddyCredentialStore, c as processStartTimeMs, d as writeHostHeartbeat, f as WORKBUDDY_BRIDGE_VERSION, g as FALLBACK_WORKBUDDY_MODELS, h as FALLBACK_WORKBUDDY_AI_MODELS, i as variantFor, j as parseModelCatalog, k as modelWithCurrentPromotion, l as readHostHeartbeat, n as CN_VARIANT, o as clearHostHeartbeat, q as appUserAgent, r as WORKBUDDY_VARIANTS, s as isHeartbeatProcessAlive, t as AI_VARIANT, u as workbuddyHostHeartbeatPath, v as WORKBUDDY_AUTH_FILENAME, w as parseWorkBuddyAuth, x as defaultDesktopAuthCandidates, y as WORKBUDDY_AUTH_FILE_ENV, z as CN_APP_VERSION_FILENAME } from "./variants-CFO_LIBm.js";
1
+ import { A as normalizeCredits, B as FALLBACK_CN_APP_VERSION, C as desktopAuthCandidatesFor, D as cnAppDiscovery, E as WorkBuddyAtRestKeyProvider, F as PROBE_EFFORT_CANDIDATES, G as validCliVersion, H as fallbackChatIdentity, I as probeModel, J as installedAppVersion, K as WORKBUDDY_APP_VERSION_FILENAME, L as randomSentinel, M as prepareChatBody, N as prepareInternationalChatBody, O as WorkBuddyUpstreamClient, P as regionOf, R as classifyUpstreamError, S as defaultDesktopAuthPath, T as workbuddyOwnAuthPath, U as readCliVersion, V as chatUserAgent, W as resolveChatIdentity, X as resolveAppVersion, Y as readBundleVersion, Z as validAppVersion, _ as WorkBuddyCatalog, a as WORKBUDDY_HOST_HEARTBEAT_FILENAME, b as WorkBuddyCredentialStore, c as processStartTimeMs, d as writeHostHeartbeat, f as WORKBUDDY_BRIDGE_VERSION, g as FALLBACK_WORKBUDDY_MODELS, h as FALLBACK_WORKBUDDY_AI_MODELS, i as variantFor, j as parseModelCatalog, k as modelWithCurrentPromotion, l as readHostHeartbeat, n as CN_VARIANT, o as clearHostHeartbeat, q as appUserAgent, r as WORKBUDDY_VARIANTS, s as isHeartbeatProcessAlive, t as AI_VARIANT, u as workbuddyHostHeartbeatPath, v as WORKBUDDY_AUTH_FILENAME, w as parseWorkBuddyAuth, x as defaultDesktopAuthCandidates, y as WORKBUDDY_AUTH_FILE_ENV, z as CN_APP_VERSION_FILENAME } from "./variants-DP0Ho0Tc.js";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
@@ -3579,7 +3579,7 @@ const WORKBUDDY_AI_STATUS_PATH = "/plugins/dsh-workbuddy-bridge/ai/status";
3579
3579
  const WORKBUDDY_AI_PROBE_PATH = "/plugins/dsh-workbuddy-bridge/ai/probe";
3580
3580
  //#endregion
3581
3581
  //#region src/version.ts
3582
- const WORKBUDDY_BRIDGE_VERSION = "0.1.0";
3582
+ const WORKBUDDY_BRIDGE_VERSION = "0.2.0";
3583
3583
  //#endregion
3584
3584
  //#region src/web/heartbeat.ts
3585
3585
  /**
package/package.json CHANGED
@@ -2,9 +2,17 @@
2
2
  "name": "dsh-workbuddy-bridge",
3
3
  "displayName": "DSH WorkBuddy Bridge",
4
4
  "description": "将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness — bring WorkBuddy desktop app models into DeepSeek Harness with zero configuration.",
5
- "version": "0.1.0",
5
+ "version": "0.2.0",
6
6
  "author": "zlZayn",
7
- "keywords": ["dsh","deepseek-harness","dsh-plugin","workbuddy","models","llm","bridge"],
7
+ "keywords": [
8
+ "dsh",
9
+ "deepseek-harness",
10
+ "dsh-plugin",
11
+ "workbuddy",
12
+ "models",
13
+ "llm",
14
+ "bridge"
15
+ ],
8
16
  "type": "module",
9
17
  "engines": {
10
18
  "node": "^22.19.0 || >=24.0.0",
@@ -16,14 +24,6 @@
16
24
  "bin": {
17
25
  "dsh-workbuddy-bridge": "lib/bin.js"
18
26
  },
19
- "scripts": {
20
- "prepack": "node node_modules/tsdown/dist/run.mjs",
21
- "build": "tsdown",
22
- "test": "vitest run",
23
- "typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.client.json",
24
- "check:release": "node scripts/check-release.mjs",
25
- "check": "pnpm run typecheck && pnpm run test && pnpm run build"
26
- },
27
27
  "exports": {
28
28
  ".": {
29
29
  "types": "./lib/types/index.d.ts",
@@ -151,5 +151,12 @@
151
151
  "unrun": "^0.3.1",
152
152
  "vitest": "^4.1.8",
153
153
  "zustand": "^5.0.15"
154
+ },
155
+ "scripts": {
156
+ "build": "tsdown",
157
+ "test": "vitest run",
158
+ "typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.client.json",
159
+ "check:release": "node scripts/check-release.mjs",
160
+ "check": "pnpm run typecheck && pnpm run test && pnpm run build"
154
161
  }
155
- }
162
+ }