dsh-workbuddy-connect 0.7.4 → 0.7.6
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.en.md +18 -9
- package/README.md +18 -9
- package/lib/bin.js +1 -1
- package/lib/client.js +5 -5
- package/lib/{host-heartbeat-DVlbwIIo.js → host-heartbeat-vU86u9aU.js} +164 -15
- package/lib/index.d.ts +15 -0
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -13,7 +13,7 @@ Brings the models available in your signed-in WorkBuddy / WorkBuddy AI desktop a
|
|
|
13
13
|
```text
|
|
14
14
|
Please install and verify the DSH (DeepSeek Harness) plugin dsh-workbuddy-connect for me (project: https://github.com/corrinehu/dsh-workbuddy-connect).
|
|
15
15
|
Start by reading the project README and confirming which interface I actually use (Web / Desktop / TUI) and its DSH core version — for the Desktop app, the bundled core, never the standalone CLI's version.
|
|
16
|
-
Then install from the official npm package per the version mapping (0.2.0-rc.2 -> 0.7.
|
|
16
|
+
Then install from the official npm package per the version mapping (0.2.0-rc.2 -> 0.7.6, rc.1 -> 0.7.0, 0.1.5-0.1.7 -> 0.6.5), preferring a locally supported non-market channel; on some Desktop distributions (the official Electron app in particular) the profile is app-managed and rules vary by distribution — check mine first, then explore its compliant install route, but never bypass its validation.
|
|
17
17
|
Ask for my consent and make backups before changing any local files or configuration.
|
|
18
18
|
After installing, verify the WorkBuddy group appears in the model picker and walk me through one short conversation.
|
|
19
19
|
If the Desktop install still fails generation validation (e.g. the @types/retry false positive), report it honestly, reference upstream dataelement/dsh-desktop#688, and suggest switching to the standalone Web / TUI — do not modify dependency packages or bypass the check.
|
|
@@ -23,7 +23,7 @@ Core-to-plugin quick reference (full table in "Compatibility and release history
|
|
|
23
23
|
|
|
24
24
|
| DSH core | Recommended plugin |
|
|
25
25
|
|---|---|
|
|
26
|
-
| 0.2.0-rc.2 | 0.7.
|
|
26
|
+
| 0.2.0-rc.2 | 0.7.6 (npm latest) |
|
|
27
27
|
| 0.2.0-rc.1 | 0.7.0 |
|
|
28
28
|
| 0.1.5 – 0.1.7 | 0.6.5 |
|
|
29
29
|
|
|
@@ -31,8 +31,8 @@ Core-to-plugin quick reference (full table in "Compatibility and release history
|
|
|
31
31
|
<summary>Manual install (command line, Web / TUI only)</summary>
|
|
32
32
|
|
|
33
33
|
```sh
|
|
34
|
-
# Web (pin per your actual core — example: 0.2.0-rc.2 -> 0.7.
|
|
35
|
-
dsh plugin --profile web add dsh-workbuddy-connect@0.7.
|
|
34
|
+
# Web (pin per your actual core — example: 0.2.0-rc.2 -> 0.7.6; or install from source via github:corrinehu/dsh-workbuddy-connect)
|
|
35
|
+
dsh plugin --profile web add dsh-workbuddy-connect@0.7.6
|
|
36
36
|
dsh web
|
|
37
37
|
|
|
38
38
|
# TUI (example for a 0.1.x core; that profile needs pnpm 11, e.g. npx pnpm@11)
|
|
@@ -62,7 +62,7 @@ dsh --profile dsh-tui
|
|
|
62
62
|
|
|
63
63
|
- **Reasoning levels**: levels explicitly declared by WorkBuddy appear directly — for example, GLM-5.3 and GLM-5.3-Flash offer low / high / max. For models without declared levels, Web and Desktop offer a manual check in the model picker (it sends a few requests and may consume credit); models without a check result or selectable levels keep using WorkBuddy's default.
|
|
64
64
|
|
|
65
|
-
- **Balance at a glance**: with a WorkBuddy / WorkBuddy AI model selected, the composer shows the account's remaining credit next to the model selector (e.g. `WB.3,401 credits`, `WB AI.3,401 credits` on the international app). Credit is not polled automatically (every status read is a real billing query): one read on mount, then refresh on demand with the ↻ beside it.
|
|
65
|
+
- **Balance at a glance**: with a WorkBuddy / WorkBuddy AI model selected, the composer shows the account's remaining credit next to the model selector (e.g. `WB.3,401 credits`, `WB AI.3,401 credits` on the international app). Credit is not polled automatically (every status read is a real billing query): one read on mount, then refresh on demand with the ↻ beside it. During session switching, the controls may briefly hide until the model selection is ready, then return automatically. The refresh button remains available even when the model has no reasoning-level detection entry or the balance cannot be read.
|
|
66
66
|
|
|
67
67
|
- **Status and detection**: Settings → Plugins → the matching card shows the account, token validity, remaining credit, and model offers; it also refreshes the model list manually, shows whether the current list came from the upstream or the built-in fallback, and runs manual reasoning-level detection for eligible models. On DSH 0.1.5 the entry lives under Settings → Plugins; on 0.1.6+ it moved to the left-sidebar Plugins panel (workbuddy-connect → View) — and the Settings → Models page shows no WorkBuddy entries on either generation, by design.
|
|
68
68
|
|
|
@@ -112,7 +112,7 @@ dsh plugin --profile web exec dsh-workbuddy-connect doctor --provider workbuddy-
|
|
|
112
112
|
## Known limitations
|
|
113
113
|
|
|
114
114
|
- Verified on macOS with the DSH Web / Desktop / TUI profiles (as of 0.3.2 this requires `0.1.5-rc.1`+ and Node 22+; TUI requires the terminal UI package `0.10.0-beta.5` or newer — see the Install section). Windows probes Local and Roaming AppData in order; WSL first reads credentials from the mounted Windows user profile. If the Windows and Linux user names differ and Windows environment variables are not forwarded into WSL, point `WORKBUDDY_AUTH_FILE` (or `WORKBUDDY_AI_AUTH_FILE` for the international version) at the actual file.
|
|
115
|
-
- **Encrypted desktop credential helper discovery**: the helper is auto-detected on macOS and Windows; on Windows the CN app checks the default path `%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe` first and then the uninstall registry records, while the international app has no verified default path and checks the registry only. If auto-detection fails, set `WORKBUDDY_ELECTRON_BIN` (CN) or `WORKBUDDY_AI_ELECTRON_BIN` (international) to the executable explicitly, then fully quit and restart DSH for the change to take effect. Linux has no auto-discovery; an explicit environment variable is required.
|
|
115
|
+
- **Encrypted desktop credential helper discovery**: the helper is auto-detected on macOS and Windows; on Windows the CN app checks the default path `%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe` first and then the uninstall registry records, while the international app has no verified default path and checks the registry only. If auto-detection fails, set `WORKBUDDY_ELECTRON_BIN` (CN) or `WORKBUDDY_AI_ELECTRON_BIN` (international) to the executable explicitly, then fully quit and restart DSH for the change to take effect. Linux has no auto-discovery; an explicit environment variable is required. When WSL invokes the Windows-side helper, the plugin automatically normalizes the `ELECTRON_RUN_AS_NODE` entry in the child's `WSLENV` to a single safe flag set (carrying `/w` for forwarding, with no path translation; all other entries are preserved) — no manual `WSLENV` setup is needed. This change has passed offline regression tests; real WSL2 / Windows verification remains outstanding.
|
|
116
116
|
- **The international version's model catalog comes from the app's own interface**: the service splits it by User-Agent, which is a private implementation detail that a server-side change can break. When that happens the plugin degrades to this account's last successful catalog and then to its built-in roster, showing the source (live / saved / built-in), the fetch time, and the failure reason on the card — but long-term compatibility is not guaranteed. The CN version's catalog uses the same interface as the official CLI and is unaffected.
|
|
117
117
|
- **International-version environments not yet covered**: on Windows / WSL / Linux no reliable source for the international app's version has been located yet, so the saved value or the built-in default is used. On macOS, real-shim checks covered complete GPT-family replies, tool calls, and continued turns.
|
|
118
118
|
- **Behaviour change with no credentials**: a version whose app was never signed in — and that left no plugin-owned copy — no longer shows a model group. The CN version used to display a built-in fallback list, but every model on it failed when selected.
|
|
@@ -126,7 +126,7 @@ The plugin version must match the DSH core — a mismatched combination fails to
|
|
|
126
126
|
|
|
127
127
|
| DSH core | Recommended plugin | Notes |
|
|
128
128
|
|---|---|---|
|
|
129
|
-
| `0.2.0-rc.2` | `0.7.
|
|
129
|
+
| `0.2.0-rc.2` | `0.7.6` (npm latest) | Current line; fixes enterprise catalog gaps and international chat requests blocked by the upstream channel check. Avoid 0.7.2 with its registry regression. |
|
|
130
130
|
| `0.2.0-rc.1` | `0.7.0` | 0.7.1 drops rc.1 support; stay on this version. |
|
|
131
131
|
| `0.1.5` – `0.1.7` | `0.6.5` | Final release for the old cores; 0.7.0 targets 0.2.0 only. |
|
|
132
132
|
| `0.1.2-rc.1` | `0.3.1` | Older line, historical maintenance only. |
|
|
@@ -134,14 +134,16 @@ The plugin version must match the DSH core — a mismatched combination fails to
|
|
|
134
134
|
|
|
135
135
|
Release history (full records at [releases](https://github.com/corrinehu/dsh-workbuddy-connect/releases)):
|
|
136
136
|
|
|
137
|
+
- **0.7.6**: fixes enterprise accounts missing `glm-5.3-flashx` from the model catalog ([#123](https://github.com/corrinehu/dsh-workbuddy-connect/issues/123)), and fixes international chat requests being blocked by the upstream channel check ([#139](https://github.com/corrinehu/dsh-workbuddy-connect/issues/139) / [#142](https://github.com/corrinehu/dsh-workbuddy-connect/issues/142)).
|
|
138
|
+
- **0.7.5**: restores composer controls after session switching ([#125](https://github.com/corrinehu/dsh-workbuddy-connect/issues/125) / [#132](https://github.com/corrinehu/dsh-workbuddy-connect/issues/132)), fixes WSL helper environment forwarding ([#133](https://github.com/corrinehu/dsh-workbuddy-connect/issues/133)), and adds community projects to both READMEs.
|
|
137
139
|
- **0.7.4**: Windows diagnostics and stability improvements: accurate classification of oversized registry-subprocess output, cross-platform test-assumption fixes ([#62](https://github.com/corrinehu/dsh-workbuddy-connect/issues/62)), and a reworked install section.
|
|
138
140
|
- **0.7.3**: fixes Windows registry auto-discovery failing on non-default install paths ([#105](https://github.com/corrinehu/dsh-workbuddy-connect/issues/105)).
|
|
139
|
-
- **0.7.2**: pi-ai becomes a plugin-bundled dependency and rejected inference-field requests are fixed ([#92](https://github.com/corrinehu/dsh-workbuddy-connect/issues/92)); this release carries a Windows registry regression — use 0.7.4
|
|
141
|
+
- **0.7.2**: pi-ai becomes a plugin-bundled dependency and rejected inference-field requests are fixed ([#92](https://github.com/corrinehu/dsh-workbuddy-connect/issues/92)); this release carries a Windows registry regression — use 0.7.4 or a newer stable release.
|
|
140
142
|
- **0.7.1**: narrows the pi-ai dependency range.
|
|
141
143
|
- **0.7.0**: adapts to DSH 0.2.0's settings-service rework and drops 0.1.x support.
|
|
142
144
|
- **0.6.5**: final release of the 0.1.x line.
|
|
143
145
|
|
|
144
|
-
Pinned-version install example: `dsh plugin --profile web add dsh-workbuddy-connect@0.7.
|
|
146
|
+
Pinned-version install example: `dsh plugin --profile web add dsh-workbuddy-connect@0.7.6`.
|
|
145
147
|
|
|
146
148
|
**Do not upgrade the profile-level `@earendil-works/pi-ai` to 1.x**: this plugin and the `0.2.0-rc.2` generation of the DSH core both require `^0.87.1` (bundled by the plugin since 0.7.2), and third-party plugin managers' "updatable" prompts do not check peer constraints — do not act on them ([#86](https://github.com/corrinehu/dsh-workbuddy-connect/issues/86)); likewise, do not blindly remove a leftover `overrides: {'@earendil-works/pi-ai': '0.87.1'}` until you have confirmed nothing else depends on it.
|
|
147
149
|
|
|
@@ -152,6 +154,13 @@ Pinned-version install example: `dsh plugin --profile web add dsh-workbuddy-conn
|
|
|
152
154
|
- The author is not liable for any direct or indirect loss arising from the use or misuse of this project.
|
|
153
155
|
- This project is not affiliated with, endorsed by, or sponsored by Tencent, WorkBuddy, or DeepSeek. Product names are used for compatibility description only; trademarks belong to their respective owners.
|
|
154
156
|
|
|
157
|
+
## Related Projects / Community Ecosystem
|
|
158
|
+
|
|
159
|
+
- **[HanaAgent](https://github.com/liliMozi/openhanako)**: an independent personal AI Agent project.
|
|
160
|
+
- **[hana-workbuddy-connect](https://github.com/miaoyongxu/hana-workbuddy-connect)**: a community-maintained unofficial adapter project that reuses parts of the `dsh-workbuddy-connect` implementation to bring WorkBuddy / WorkBuddy AI models to HanaAgent.
|
|
161
|
+
|
|
162
|
+
Both projects are maintained independently by third parties. The compatibility, security, and usage support of `hana-workbuddy-connect` are the responsibility of its maintainer. Listing them here is not an official endorsement, nor does it imply any stability or compatibility commitment on this plugin's internal interfaces.
|
|
163
|
+
|
|
155
164
|
## Acknowledgements
|
|
156
165
|
|
|
157
166
|
- [Sliverkiss/workbuddy2api](https://github.com/Sliverkiss/workbuddy2api) (MIT) — reference implementation of the WorkBuddy upstream protocol.
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
```text
|
|
14
14
|
请帮我安装并验证 DSH(DeepSeek Harness)插件 dsh-workbuddy-connect(项目地址:https://github.com/corrinehu/dsh-workbuddy-connect):
|
|
15
15
|
先阅读项目 README,确认我实际使用的界面(Web / Desktop / TUI)与 DSH 内核版本,桌面版以 App 内置核心为准,不要用独立 CLI 的版本代替;
|
|
16
|
-
再按版本对应关系从 npm 正式包安装(0.2.0-rc.2→0.7.
|
|
16
|
+
再按版本对应关系从 npm 正式包安装(0.2.0-rc.2→0.7.6、rc.1→0.7.0、0.1.5–0.1.7→0.6.5),优先走本机受支持的非插件市场渠道;部分 Desktop 发行版(尤其官方 Electron 版)的 profile 由 App 管理,各发行版规则未必相同,先确认我所用的发行版,再探查其合规的安装方式,但不得绕过其校验;
|
|
17
17
|
任何本地文件或配置改动,先征得我同意并做好备份;
|
|
18
18
|
装完后验证模型选择器里出现 WorkBuddy 分组,并陪我完成一次简短对话;
|
|
19
19
|
若 Desktop 安装仍因 generation 校验失败(如 @types/retry 误报),请如实报告、参照上游 dataelement/dsh-desktop#688,并建议我改用独立的 Web / TUI,不要修改依赖包或绕过校验。
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
| DSH 内核 | 推荐插件版 |
|
|
25
25
|
|---|---|
|
|
26
|
-
| 0.2.0-rc.2 | 0.7.
|
|
26
|
+
| 0.2.0-rc.2 | 0.7.6(npm latest) |
|
|
27
27
|
| 0.2.0-rc.1 | 0.7.0 |
|
|
28
28
|
| 0.1.5 – 0.1.7 | 0.6.5 |
|
|
29
29
|
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
<summary>手动安装(命令行,仅 Web / TUI)</summary>
|
|
32
32
|
|
|
33
33
|
```sh
|
|
34
|
-
# Web(按实际内核固定版本,示例为 0.2.0-rc.2 → 0.7.
|
|
35
|
-
dsh plugin --profile web add dsh-workbuddy-connect@0.7.
|
|
34
|
+
# Web(按实际内核固定版本,示例为 0.2.0-rc.2 → 0.7.6;也可用 github:corrinehu/dsh-workbuddy-connect 从源码安装)
|
|
35
|
+
dsh plugin --profile web add dsh-workbuddy-connect@0.7.6
|
|
36
36
|
dsh web
|
|
37
37
|
|
|
38
38
|
# TUI(示例为 0.1.x 内核;该 profile 需用 pnpm 11 安装,如 npx pnpm@11)
|
|
@@ -62,7 +62,7 @@ dsh --profile dsh-tui
|
|
|
62
62
|
|
|
63
63
|
- **推理档位**:WorkBuddy 明确声明的档位会直接显示,例如 GLM-5.3 和 GLM-5.3-Flash 可选 low / high / max。未声明档位的模型可在 Web 和 Desktop 的模型选择器中手动检测(发送少量请求,可能消耗积分);未检测或没有可用档位的模型使用 WorkBuddy 默认档位。
|
|
64
64
|
|
|
65
|
-
- **余额速览**:选中 WorkBuddy / WorkBuddy AI 模型时,输入框底部在模型选择器旁显示当前账号的剩余积分(如 `WB.3,401(积分)`、国际版 `WB AI.3,401(积分)`)。积分不自动轮询(每次读取都是真实计费查询),挂载时读取一次后可点旁边的 ↻
|
|
65
|
+
- **余额速览**:选中 WorkBuddy / WorkBuddy AI 模型时,输入框底部在模型选择器旁显示当前账号的剩余积分(如 `WB.3,401(积分)`、国际版 `WB AI.3,401(积分)`)。积分不自动轮询(每次读取都是真实计费查询),挂载时读取一次后可点旁边的 ↻ 手动刷新。切换会话时组件可能短暂隐藏,模型选择就绪后自动恢复;即使模型没有推理档位检测入口或余额读取失败,刷新按钮仍保留。
|
|
66
66
|
|
|
67
67
|
- **信息查看与检测**:设置 → 插件 → 对应卡片可查看账号、令牌有效期、剩余积分和模型优惠,也可手动刷新模型列表并查看当前列表来自上游还是内置兜底,或对可检测模型手动检测推理档位。DSH 0.1.5 的入口在「设置 → 插件」,0.1.6+ 移到主界面左侧栏「插件」面板(workbuddy-connect → 查看);「设置 → 模型」页两代都不显示 WorkBuddy 条目,属有意设计。
|
|
68
68
|
|
|
@@ -113,7 +113,7 @@ dsh plugin --profile web exec dsh-workbuddy-connect doctor --provider workbuddy-
|
|
|
113
113
|
## 已知限制
|
|
114
114
|
|
|
115
115
|
- 在 macOS 的 DSH Web / Desktop / TUI 下验证通过(0.3.2 起要求 `0.1.5-rc.1`+、Node 22+;TUI 需终端界面插件 `0.10.0-beta.5` 及以上,见安装章节说明)。Windows 会依次探测 Local 与 Roaming AppData;WSL 会优先从挂载的 Windows 用户目录读取登录凭据。若 Windows 与 Linux 用户名不同且 Windows 环境变量未传入 WSL,请通过 `WORKBUDDY_AUTH_FILE`(国际版为 `WORKBUDDY_AI_AUTH_FILE`)指定实际位置。
|
|
116
|
-
- **加密桌面凭据的解密程序定位**:解密程序在 macOS 与 Windows 上会自动探测;Windows 上国内版先查默认路径 `%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe`,再查卸载注册表记录,国际版没有已验证的默认路径、仅查注册表。自动探测失败时,可用 `WORKBUDDY_ELECTRON_BIN`(国内版)或 `WORKBUDDY_AI_ELECTRON_BIN`(国际版)显式指定可执行文件,设置后需完全退出并重启 DSH 才生效。Linux 无法自动发现,需显式指定。
|
|
116
|
+
- **加密桌面凭据的解密程序定位**:解密程序在 macOS 与 Windows 上会自动探测;Windows 上国内版先查默认路径 `%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe`,再查卸载注册表记录,国际版没有已验证的默认路径、仅查注册表。自动探测失败时,可用 `WORKBUDDY_ELECTRON_BIN`(国内版)或 `WORKBUDDY_AI_ELECTRON_BIN`(国际版)显式指定可执行文件,设置后需完全退出并重启 DSH 才生效。Linux 无法自动发现,需显式指定。WSL 下调用 Windows 侧解密程序时,插件会自动把子进程 `WSLENV` 中的 `ELECTRON_RUN_AS_NODE` 条目规范化为单一安全旗标(含 `/w` 转发、不做路径转换,其余条目原样保留),无需手动设置。此改动已通过离线回归测试,尚未完成 WSL2 / Windows 真机验证。
|
|
117
117
|
- **国际版的模型目录来自 App 界面接口**:服务端按 User-Agent 分流下发,属私有实现,上游改动可能使其失效。届时插件按「本账号上次成功目录 → 内置目录」降级,并在卡片上标明来源(实时 / 已保存 / 内置)、更新时间与失败原因,但不能保证长期兼容。国内版目录走官方 CLI 同款接口,不受此影响。
|
|
118
118
|
- **国际版仍未覆盖的环境**:Windows / WSL / Linux 下国际版 App 的版本读取尚未找到可靠来源,会退回最近保存的版本或内置值。macOS 上已通过真实 shim 验证 GPT 系完整回复、工具调用与续轮。
|
|
119
119
|
- **无凭据时的行为变化**:某版 App 从未登录、也没留下插件自留副本时,该版模型分组不再显示。此前国内版会显示一份内置兜底列表,但那些模型选了必然报错。
|
|
@@ -127,7 +127,7 @@ dsh plugin --profile web exec dsh-workbuddy-connect doctor --provider workbuddy-
|
|
|
127
127
|
|
|
128
128
|
| DSH 内核 | 推荐插件版 | 注意事项 |
|
|
129
129
|
|---|---|---|
|
|
130
|
-
| `0.2.0-rc.2` | `0.7.
|
|
130
|
+
| `0.2.0-rc.2` | `0.7.6`(npm latest) | 当前最新线;修复企业账号模型目录缺项与国际版对话被渠道校验拦截,勿停留在有注册表回归的 0.7.2。 |
|
|
131
131
|
| `0.2.0-rc.1` | `0.7.0` | 0.7.1 起不再支持 rc.1,请停留本版。 |
|
|
132
132
|
| `0.1.5` – `0.1.7` | `0.6.5` | 旧内核最终版;0.7.0 起仅面向 0.2.0。 |
|
|
133
133
|
| `0.1.2-rc.1` | `0.3.1` | 更早旧线,仅历史维护。 |
|
|
@@ -135,14 +135,16 @@ dsh plugin --profile web exec dsh-workbuddy-connect doctor --provider workbuddy-
|
|
|
135
135
|
|
|
136
136
|
历次更新(完整记录见 [releases](https://github.com/corrinehu/dsh-workbuddy-connect/releases)):
|
|
137
137
|
|
|
138
|
+
- **0.7.6**:修复企业账号模型目录缺少 `glm-5.3-flashx`([#123](https://github.com/corrinehu/dsh-workbuddy-connect/issues/123)),修复国际版对话请求被上游渠道校验拦截([#139](https://github.com/corrinehu/dsh-workbuddy-connect/issues/139) / [#142](https://github.com/corrinehu/dsh-workbuddy-connect/issues/142))。
|
|
139
|
+
- **0.7.5**:修复切换会话后输入框余额与刷新按钮消失([#125](https://github.com/corrinehu/dsh-workbuddy-connect/issues/125) / [#132](https://github.com/corrinehu/dsh-workbuddy-connect/issues/132)),修复 WSL 调用 Windows 凭据解密程序的环境转发([#133](https://github.com/corrinehu/dsh-workbuddy-connect/issues/133)),README 收录社区项目([#130](https://github.com/corrinehu/dsh-workbuddy-connect/issues/130))。
|
|
138
140
|
- **0.7.4**:Windows 诊断与稳定性改进:注册表子进程输出超限准确分类、跨平台测试假设修正([#62](https://github.com/corrinehu/dsh-workbuddy-connect/issues/62)),安装说明重排。
|
|
139
141
|
- **0.7.3**:修复 Windows 非默认安装路径下注册表自动发现失败([#105](https://github.com/corrinehu/dsh-workbuddy-connect/issues/105))。
|
|
140
|
-
- **0.7.2**:pi-ai 改为插件自带依赖,并修复推理字段请求被拒([#92](https://github.com/corrinehu/dsh-workbuddy-connect/issues/92));该版存在 Windows
|
|
142
|
+
- **0.7.2**:pi-ai 改为插件自带依赖,并修复推理字段请求被拒([#92](https://github.com/corrinehu/dsh-workbuddy-connect/issues/92));该版存在 Windows 注册表回归,请使用 0.7.4 或更新的正式版本。
|
|
141
143
|
- **0.7.1**:收窄 pi-ai 依赖范围。
|
|
142
144
|
- **0.7.0**:适配 DSH 0.2.0 的设置服务改造,不再支持 0.1.x。
|
|
143
145
|
- **0.6.5**:0.1.x 线最终版本。
|
|
144
146
|
|
|
145
|
-
固定版本安装示例:`dsh plugin --profile web add dsh-workbuddy-connect@0.7.
|
|
147
|
+
固定版本安装示例:`dsh plugin --profile web add dsh-workbuddy-connect@0.7.6`。
|
|
146
148
|
|
|
147
149
|
**不要把 profile 级的 `@earendil-works/pi-ai` 升到 1.x**:本插件与 `0.2.0-rc.2` 这一代内核都要求 `^0.87.1`(0.7.2 起由插件自带),第三方插件管理器的「可更新」提示不校验 peer 约束、不能照做([#86](https://github.com/corrinehu/dsh-workbuddy-connect/issues/86));为此历史遗留的 `overrides: {'@earendil-works/pi-ai': '0.87.1'}` 在确认其他插件不依赖前也不要盲目移除。
|
|
148
150
|
|
|
@@ -153,6 +155,13 @@ dsh plugin --profile web exec dsh-workbuddy-connect doctor --provider workbuddy-
|
|
|
153
155
|
- 本项目作者不对任何因使用或滥用本项目产生的直接或间接损失负责。
|
|
154
156
|
- 本项目与腾讯、WorkBuddy、DeepSeek 均无关联,未获其授权或认可;文中出现的名称仅用于描述兼容关系,其商标权利归各自所有。
|
|
155
157
|
|
|
158
|
+
## 相关项目 / 社区生态
|
|
159
|
+
|
|
160
|
+
- **[HanaAgent](https://github.com/liliMozi/openhanako)**:独立的个人 AI Agent 项目。
|
|
161
|
+
- **[hana-workbuddy-connect](https://github.com/miaoyongxu/hana-workbuddy-connect)**:社区维护的非官方适配项目,复用 `dsh-workbuddy-connect` 的部分实现,为 HanaAgent 接入 WorkBuddy / WorkBuddy AI 模型。
|
|
162
|
+
|
|
163
|
+
以上项目均由第三方独立维护。其中,`hana-workbuddy-connect` 的兼容性、安全性及使用支持由其维护者负责。收录不代表官方背书,也不意味着本插件对内部接口提供稳定性或兼容性承诺。
|
|
164
|
+
|
|
156
165
|
## 致谢
|
|
157
166
|
|
|
158
167
|
- [Sliverkiss/workbuddy2api](https://github.com/Sliverkiss/workbuddy2api)(MIT)— WorkBuddy 上游协议的参照实现。
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as WORKBUDDY_VARIANTS, O as WorkBuddyUpstreamClient, Q as resolveAppVersion, S as CN_VARIANT, a as readHostHeartbeat, b as atRestKeyProviderFor, c as WORKBUDDY_CONNECT_VERSION, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, w as variantFor } from "./host-heartbeat-
|
|
2
|
+
import { C as WORKBUDDY_VARIANTS, O as WorkBuddyUpstreamClient, Q as resolveAppVersion, S as CN_VARIANT, a as readHostHeartbeat, b as atRestKeyProviderFor, c as WORKBUDDY_CONNECT_VERSION, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, w as variantFor } from "./host-heartbeat-vU86u9aU.js";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/bin.ts
|
package/lib/client.js
CHANGED
|
@@ -1746,14 +1746,14 @@ window.__ModuleLoader__.load({
|
|
|
1746
1746
|
const subscribe = (0, react.useCallback)((listener) => directory.subscribe(listener), [directory]);
|
|
1747
1747
|
const snapshot = (0, react.useCallback)(() => directory.getSnapshot(), [directory]);
|
|
1748
1748
|
const selection = (0, react.useSyncExternalStore)(subscribe, snapshot, snapshot).current;
|
|
1749
|
-
|
|
1750
|
-
const
|
|
1751
|
-
return card === void 0
|
|
1749
|
+
if (selection == null) return null;
|
|
1750
|
+
const card = cardVariantFor(selection.provider);
|
|
1751
|
+
return card === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelProbe, {
|
|
1752
1752
|
model: selection.model,
|
|
1753
1753
|
card,
|
|
1754
1754
|
label: useLabel(t),
|
|
1755
1755
|
t
|
|
1756
|
-
},
|
|
1756
|
+
}, `${card.id}:${selection.model}`);
|
|
1757
1757
|
}
|
|
1758
1758
|
function ModelProbe({ model, card, label, t }) {
|
|
1759
1759
|
const [status, setStatus] = (0, react.useState)();
|
|
@@ -2772,7 +2772,7 @@ window.__ModuleLoader__.load({
|
|
|
2772
2772
|
};
|
|
2773
2773
|
//#endregion
|
|
2774
2774
|
//#region src/version.ts
|
|
2775
|
-
const WORKBUDDY_CONNECT_VERSION = "0.7.
|
|
2775
|
+
const WORKBUDDY_CONNECT_VERSION = "0.7.6";
|
|
2776
2776
|
//#endregion
|
|
2777
2777
|
//#region src/client/WorkBuddyConfigPage.tsx
|
|
2778
2778
|
/**
|
|
@@ -3,7 +3,7 @@ import { homedir, release } from "node:os";
|
|
|
3
3
|
import { basename, dirname, join } from "node:path";
|
|
4
4
|
import { withFileLock, writeFileAtomic } from "@deepseek-ai/dsh-atomic-write";
|
|
5
5
|
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
6
|
-
import { createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
6
|
+
import { createDecipheriv, createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { execFile, execFileSync } from "node:child_process";
|
|
8
8
|
import { accessSync, constants, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
9
9
|
//#region src/app-version.ts
|
|
@@ -709,11 +709,39 @@ function commonHeaders(credential) {
|
|
|
709
709
|
};
|
|
710
710
|
}
|
|
711
711
|
/**
|
|
712
|
+
* The conversation-channel trio the chat endpoints require.
|
|
713
|
+
*
|
|
714
|
+
* Since 2026-10-16 `www.workbuddy.ai` answers any `/v2/chat/completions`
|
|
715
|
+
* request that omits all three `X-Conversation-*` headers with `400` /
|
|
716
|
+
* `code 11128` / `msg: "conversation id missing"`, whose `displayMsg.zh` is
|
|
717
|
+
* 「请求被拦截,请重新发送」 (issue #139). The official desktop client sends
|
|
718
|
+
* the trio on chat and speech alike — read out of `resources/app.asar`, where
|
|
719
|
+
* the names are `X-Conversation-ID`, `X-Conversation-Request-ID` and
|
|
720
|
+
* `X-Conversation-Message-ID`.
|
|
721
|
+
*
|
|
722
|
+
* A fresh UUID per request is enough, and is what the wire measurement
|
|
723
|
+
* supports: the upstream keeps no history keyed by the id (two calls sharing
|
|
724
|
+
* one id, the second carrying only `system` + `user`, still answered "I don't
|
|
725
|
+
* know"), so the trio marks the channel rather than carrying conversation
|
|
726
|
+
* state. Fresh ids also keep concurrent sub-agents off one shared
|
|
727
|
+
* conversation. The CN gateway was measured accepting the same trio (200 with
|
|
728
|
+
* and without), so both regions carry it and the two paths cannot drift.
|
|
729
|
+
*/
|
|
730
|
+
function conversationHeaders() {
|
|
731
|
+
return {
|
|
732
|
+
"X-Conversation-ID": randomUUID(),
|
|
733
|
+
"X-Conversation-Request-ID": randomUUID(),
|
|
734
|
+
"X-Conversation-Message-ID": randomUUID()
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
712
738
|
* Chat request headers, including the X-No-* conventions the official CLI uses.
|
|
713
739
|
*
|
|
714
740
|
* `userAgent` and `clientVersion` carry the same resolved desktop identity for
|
|
715
741
|
* chat and probe requests. Refresh shares `commonHeaders` but never this
|
|
716
|
-
* override, so the two paths cannot drift into each other.
|
|
742
|
+
* override, so the two paths cannot drift into each other. The
|
|
743
|
+
* `X-Conversation-*` trio rides along too — see {@link conversationHeaders} —
|
|
744
|
+
* because the international gateway rejects a chat that omits it.
|
|
717
745
|
*/
|
|
718
746
|
function chatHeaders(credential, userAgent, clientVersion) {
|
|
719
747
|
return {
|
|
@@ -726,7 +754,8 @@ function chatHeaders(credential, userAgent, clientVersion) {
|
|
|
726
754
|
"X-IDE-Type": "WorkBuddy",
|
|
727
755
|
"X-IDE-Name": "WorkBuddy",
|
|
728
756
|
"X-IDE-Version": clientVersion,
|
|
729
|
-
"X-Product": "SaaS"
|
|
757
|
+
"X-Product": "SaaS",
|
|
758
|
+
...conversationHeaders()
|
|
730
759
|
};
|
|
731
760
|
}
|
|
732
761
|
/** Refresh-endpoint headers; X-Refresh-Token appears here and nowhere else. */
|
|
@@ -755,6 +784,28 @@ function billingHeaders(credential) {
|
|
|
755
784
|
return headers;
|
|
756
785
|
}
|
|
757
786
|
/**
|
|
787
|
+
* Account-identity headers for the CN catalog requests (`/v3/config` and the
|
|
788
|
+
* console badge read). The gateway also splits `/v3/config` by account
|
|
789
|
+
* identity: an enterprise account without this pair is silently answered with
|
|
790
|
+
* the personal roster (issue #123 — 18 vs 19 models, FlashX missing), and the
|
|
791
|
+
* pair is all-or-nothing there: `X-Enterprise-Id` alone is rejected outright
|
|
792
|
+
* while `X-User-Id` alone selects nothing. So the block is emitted only when
|
|
793
|
+
* both parts exist, and personal accounts keep the bare headers their roster
|
|
794
|
+
* was already correct under. `X-Tenant-Id`/`X-Domain` ride along in the
|
|
795
|
+
* spelling `billingHeaders` already proved the gateway accepts.
|
|
796
|
+
*/
|
|
797
|
+
function identityHeaders(credential) {
|
|
798
|
+
if (credential.uid === "") return {};
|
|
799
|
+
if (credential.enterpriseId === void 0 || credential.enterpriseId === "") return {};
|
|
800
|
+
const headers = {
|
|
801
|
+
"X-User-Id": credential.uid,
|
|
802
|
+
"X-Enterprise-Id": credential.enterpriseId,
|
|
803
|
+
"X-Tenant-Id": credential.enterpriseId
|
|
804
|
+
};
|
|
805
|
+
if (credential.domain !== "") headers["X-Domain"] = credential.domain;
|
|
806
|
+
return headers;
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
758
809
|
* Normalize an OpenAI chat-completions body for the WorkBuddy upstream:
|
|
759
810
|
* force `stream: true` (the upstream rejects non-streaming), flatten
|
|
760
811
|
* `tool_choice` (the upstream's field is a string; object forms return 400),
|
|
@@ -1036,6 +1087,13 @@ var WorkBuddyUpstreamClient = class {
|
|
|
1036
1087
|
* advertises is exactly the one its own requests can use. The international
|
|
1037
1088
|
* variant has no CLI identity, so it keeps the App-shaped UA.
|
|
1038
1089
|
*
|
|
1090
|
+
* The same split has an account-identity axis (issue #123): an enterprise
|
|
1091
|
+
* account must also present `X-User-Id` + `X-Enterprise-Id`, or the gateway
|
|
1092
|
+
* answers with the personal roster. CN sends that pair via
|
|
1093
|
+
* {@link identityHeaders} whenever the credential carries both halves; the
|
|
1094
|
+
* international gateway's split was never measured against account headers,
|
|
1095
|
+
* so it keeps its documented shape.
|
|
1096
|
+
*
|
|
1039
1097
|
* Membership is the `cli` roster intersected with the usable rows (see
|
|
1040
1098
|
* {@link parseModelCatalog}); the promo badges the product document does
|
|
1041
1099
|
* not carry are merged in from a best-effort console read — see
|
|
@@ -1057,7 +1115,7 @@ var WorkBuddyUpstreamClient = class {
|
|
|
1057
1115
|
...international ? {
|
|
1058
1116
|
"X-Requested-With": "XMLHttpRequest",
|
|
1059
1117
|
"X-Product": "SaaS"
|
|
1060
|
-
} :
|
|
1118
|
+
} : identityHeaders(credential),
|
|
1061
1119
|
"User-Agent": appVersion === void 0 ? CLIENT_UA : appUserAgent(appVersion.version)
|
|
1062
1120
|
},
|
|
1063
1121
|
signal: signal === void 0 ? AbortSignal.timeout(JSON_TIMEOUT_MS) : AbortSignal.any([signal, AbortSignal.timeout(JSON_TIMEOUT_MS)])
|
|
@@ -1094,6 +1152,7 @@ var WorkBuddyUpstreamClient = class {
|
|
|
1094
1152
|
Accept: "application/json",
|
|
1095
1153
|
Origin: originReferer(credential),
|
|
1096
1154
|
Referer: `${originReferer(credential)}/`,
|
|
1155
|
+
...identityHeaders(credential),
|
|
1097
1156
|
"User-Agent": CLIENT_UA
|
|
1098
1157
|
},
|
|
1099
1158
|
signal: signal === void 0 ? AbortSignal.timeout(JSON_TIMEOUT_MS) : AbortSignal.any([signal, AbortSignal.timeout(JSON_TIMEOUT_MS)])
|
|
@@ -1625,6 +1684,23 @@ const INTERNATIONAL_SYSTEM_PROMPT = "You are a helpful assistant.";
|
|
|
1625
1684
|
*/
|
|
1626
1685
|
const INTERNATIONAL_PROBE_MAX_TOKENS = 16;
|
|
1627
1686
|
//#endregion
|
|
1687
|
+
//#region src/wsl.ts
|
|
1688
|
+
/**
|
|
1689
|
+
* Whether this Linux process is running inside Windows Subsystem for Linux.
|
|
1690
|
+
*
|
|
1691
|
+
* Shared by the desktop-auth candidate probe (`auth.ts`) and the at-rest key
|
|
1692
|
+
* helper spawn (`desktop-credential-protection.ts`), so both agree on what
|
|
1693
|
+
* "WSL" means. Covers WSL1 and WSL2: WSL2 sets `WSL_DISTRO_NAME` /
|
|
1694
|
+
* `WSL_INTEROP`, and every WSL kernel release string carries "microsoft"
|
|
1695
|
+
* (e.g. `6.18.33.2-microsoft-standard-WSL2`), which also catches a WSL2
|
|
1696
|
+
* session whose env vars were stripped.
|
|
1697
|
+
*/
|
|
1698
|
+
function isWsl() {
|
|
1699
|
+
if (process.platform !== "linux") return false;
|
|
1700
|
+
if (process.env["WSL_DISTRO_NAME"] !== void 0 || process.env["WSL_INTEROP"] !== void 0) return true;
|
|
1701
|
+
return release().toLowerCase().includes("microsoft");
|
|
1702
|
+
}
|
|
1703
|
+
//#endregion
|
|
1628
1704
|
//#region src/status-paths.ts
|
|
1629
1705
|
/** Node-free constants and types shared by the Host and browser halves. */
|
|
1630
1706
|
/** Plugin-owned status endpoint consumed by its browser half. */
|
|
@@ -2140,6 +2216,86 @@ const PLUTIL_MAX_OUTPUT_BYTES = 65536;
|
|
|
2140
2216
|
*/
|
|
2141
2217
|
var DiscoveryIncompleteError = class extends Error {};
|
|
2142
2218
|
/**
|
|
2219
|
+
* Merge a `WSLENV` value so `ELECTRON_RUN_AS_NODE` crosses WSL→Windows
|
|
2220
|
+
* interop (#133).
|
|
2221
|
+
*
|
|
2222
|
+
* WSL only forwards listed variables to a Windows child, and only when the
|
|
2223
|
+
* entry carries the `/w` (WSL→Windows) direction flag — a plain
|
|
2224
|
+
* `env: { …, ELECTRON_RUN_AS_NODE: '1' }` stays on the Linux side, so the
|
|
2225
|
+
* WorkBuddy exe starts in GUI mode and its stdout is app log rather than the
|
|
2226
|
+
* key payload.
|
|
2227
|
+
*
|
|
2228
|
+
* The target variable is consolidated into exactly ONE safe entry, because
|
|
2229
|
+
* duplicate same-name entries leave the forwarding direction indeterminate:
|
|
2230
|
+
*
|
|
2231
|
+
* - the single entry always carries `w` (the plugin's requirement) and takes
|
|
2232
|
+
* the position of the first same-name occurrence;
|
|
2233
|
+
* - `u` (Windows→WSL) is kept when ANY existing same-name entry asked for it,
|
|
2234
|
+
* so a user's bidirectional setup survives as `/uw`;
|
|
2235
|
+
* - the path flags are dropped: `p` (path translation) and `l` (path list)
|
|
2236
|
+
* would mangle the value, which here is the numeric switch `1` —
|
|
2237
|
+
* `ELECTRON_RUN_AS_NODE=1` must arrive byte-for-byte, never as a converted
|
|
2238
|
+
* path. An inherited `/pw`, `/lw`, or `/l` therefore normalizes to a
|
|
2239
|
+
* path-free flag set rather than being appended to;
|
|
2240
|
+
* - a BARE name carries no direction at all, so it counts as neither `w` nor
|
|
2241
|
+
* `u` — it only consolidates;
|
|
2242
|
+
* - with no same-name entry at all, `ELECTRON_RUN_AS_NODE/w` is appended;
|
|
2243
|
+
* - every OTHER entry keeps its order and bytes; empty segments (the
|
|
2244
|
+
* trailing colons Windows Terminal tends to leave) and exact duplicates
|
|
2245
|
+
* among them are dropped.
|
|
2246
|
+
*
|
|
2247
|
+
* The result is idempotent: merging it again yields the same string.
|
|
2248
|
+
*
|
|
2249
|
+
* @param value - the inherited `WSLENV` value, or `undefined` when unset.
|
|
2250
|
+
* @returns the `WSLENV` value the child should receive.
|
|
2251
|
+
*/
|
|
2252
|
+
function wslenvForwardRunAsNode(value) {
|
|
2253
|
+
const merged = [];
|
|
2254
|
+
/** Index of the consolidated target entry inside `merged`, once placed. */
|
|
2255
|
+
let targetIndex = -1;
|
|
2256
|
+
/** The safe flag set for the target: always `w`, plus `u` if asked for. */
|
|
2257
|
+
let targetFlags = "/w";
|
|
2258
|
+
for (const entry of (value ?? "").split(":")) {
|
|
2259
|
+
if (entry === "") continue;
|
|
2260
|
+
const slash = entry.indexOf("/");
|
|
2261
|
+
if ((slash === -1 ? entry : entry.slice(0, slash)) !== "ELECTRON_RUN_AS_NODE") {
|
|
2262
|
+
if (!merged.includes(entry)) merged.push(entry);
|
|
2263
|
+
continue;
|
|
2264
|
+
}
|
|
2265
|
+
if ((slash === -1 ? "" : entry.slice(slash + 1)).includes("u")) targetFlags = "/uw";
|
|
2266
|
+
if (targetIndex === -1) {
|
|
2267
|
+
targetIndex = merged.length;
|
|
2268
|
+
merged.push(`ELECTRON_RUN_AS_NODE${targetFlags}`);
|
|
2269
|
+
} else merged[targetIndex] = `ELECTRON_RUN_AS_NODE${targetFlags}`;
|
|
2270
|
+
}
|
|
2271
|
+
if (targetIndex === -1) merged.push(`ELECTRON_RUN_AS_NODE${targetFlags}`);
|
|
2272
|
+
return merged.join(":");
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* The environment the at-rest key helper is spawned with (#133).
|
|
2276
|
+
*
|
|
2277
|
+
* Always a fresh object — the parent (`process.env` in production) is never
|
|
2278
|
+
* mutated. `ELECTRON_RUN_AS_NODE=1` forces the Electron binary into plain
|
|
2279
|
+
* Node mode; when the spawn crosses WSL→Windows interop — a WSL host and a
|
|
2280
|
+
* helper that is itself a Windows executable — the child's `WSLENV` is
|
|
2281
|
+
* additionally merged via {@link wslenvForwardRunAsNode} so the interop layer
|
|
2282
|
+
* actually forwards that variable. Every other platform and path combination
|
|
2283
|
+
* gets the previous behaviour byte-for-byte.
|
|
2284
|
+
*
|
|
2285
|
+
* @param parent - the environment to inherit (a copy is taken).
|
|
2286
|
+
* @param electronPath - the helper binary about to be spawned.
|
|
2287
|
+
* @param wsl - whether the current process runs inside WSL.
|
|
2288
|
+
* @returns the child process environment.
|
|
2289
|
+
*/
|
|
2290
|
+
function helperChildEnv(parent, electronPath, wsl) {
|
|
2291
|
+
const childEnv = {
|
|
2292
|
+
...parent,
|
|
2293
|
+
ELECTRON_RUN_AS_NODE: "1"
|
|
2294
|
+
};
|
|
2295
|
+
if (wsl && basename(electronPath).toLowerCase().endsWith(".exe")) childEnv["WSLENV"] = wslenvForwardRunAsNode(childEnv["WSLENV"]);
|
|
2296
|
+
return childEnv;
|
|
2297
|
+
}
|
|
2298
|
+
/**
|
|
2143
2299
|
* The default discovery tools: Spotlight for the bundle, `/usr/bin/plutil` for
|
|
2144
2300
|
* identity. Every failure that means "we could not tell" — a missing tool, a
|
|
2145
2301
|
* timeout, an oversized answer — is raised as {@link DiscoveryIncompleteError}
|
|
@@ -2412,6 +2568,7 @@ function parseWindowsUninstallJson(output) {
|
|
|
2412
2568
|
platform;
|
|
2413
2569
|
discoveryBudgetMs;
|
|
2414
2570
|
timeoutMs;
|
|
2571
|
+
wsl;
|
|
2415
2572
|
source;
|
|
2416
2573
|
spawnHelper;
|
|
2417
2574
|
/**
|
|
@@ -2434,6 +2591,7 @@ function parseWindowsUninstallJson(output) {
|
|
|
2434
2591
|
this.windowsTools = options.windowsTools ?? workBuddyWindowsDiscoveryTools();
|
|
2435
2592
|
this.discoveryBudgetMs = options.discoveryBudgetMs ?? 1e4;
|
|
2436
2593
|
this.timeoutMs = options.timeoutMs ?? 1e4;
|
|
2594
|
+
this.wsl = options.wsl ?? isWsl;
|
|
2437
2595
|
this.spawnHelper = options.spawnHelper ?? ((path) => this.spawnAt(path));
|
|
2438
2596
|
this.source = options.source ?? (() => this.spawnPayload());
|
|
2439
2597
|
}
|
|
@@ -2636,10 +2794,7 @@ function parseWindowsUninstallJson(output) {
|
|
|
2636
2794
|
timeout: this.timeoutMs,
|
|
2637
2795
|
maxBuffer: 1048576,
|
|
2638
2796
|
windowsHide: true,
|
|
2639
|
-
env:
|
|
2640
|
-
...process.env,
|
|
2641
|
-
ELECTRON_RUN_AS_NODE: "1"
|
|
2642
|
-
}
|
|
2797
|
+
env: helperChildEnv(process.env, electronPath, this.wsl())
|
|
2643
2798
|
}, (error, stdout) => {
|
|
2644
2799
|
if (error !== null && error !== void 0) {
|
|
2645
2800
|
reject(new WorkBuddyElectronPathError("encrypted-credential-unreadable", `the WorkBuddy key helper (${electronPath}) ${error.killed === true ? `timed out or was killed after ${String(this.timeoutMs)}ms` : error.code !== void 0 ? `exited with code ${String(error.code)}` : "could not be started"}`));
|
|
@@ -2843,12 +2998,6 @@ const DESKTOP_AUTH_RELATIVE_PATH = [
|
|
|
2843
2998
|
"auth",
|
|
2844
2999
|
"workbuddy-desktop.info"
|
|
2845
3000
|
];
|
|
2846
|
-
/** Whether this Linux process is running inside Windows Subsystem for Linux. */
|
|
2847
|
-
function isWsl() {
|
|
2848
|
-
if (process.platform !== "linux") return false;
|
|
2849
|
-
if (process.env["WSL_DISTRO_NAME"] !== void 0 || process.env["WSL_INTEROP"] !== void 0) return true;
|
|
2850
|
-
return release().toLowerCase().includes("microsoft");
|
|
2851
|
-
}
|
|
2852
3001
|
/** Convert a Windows drive path to WSL's conventional `/mnt/<drive>` form. */
|
|
2853
3002
|
function windowsPathForWsl(value) {
|
|
2854
3003
|
const path = value?.trim();
|
|
@@ -4028,7 +4177,7 @@ var WorkBuddyCatalog = class {
|
|
|
4028
4177
|
};
|
|
4029
4178
|
//#endregion
|
|
4030
4179
|
//#region src/version.ts
|
|
4031
|
-
const WORKBUDDY_CONNECT_VERSION = "0.7.
|
|
4180
|
+
const WORKBUDDY_CONNECT_VERSION = "0.7.6";
|
|
4032
4181
|
//#endregion
|
|
4033
4182
|
//#region src/host-heartbeat.ts
|
|
4034
4183
|
/**
|
package/lib/index.d.ts
CHANGED
|
@@ -508,6 +508,13 @@ declare class WorkBuddyUpstreamClient {
|
|
|
508
508
|
* advertises is exactly the one its own requests can use. The international
|
|
509
509
|
* variant has no CLI identity, so it keeps the App-shaped UA.
|
|
510
510
|
*
|
|
511
|
+
* The same split has an account-identity axis (issue #123): an enterprise
|
|
512
|
+
* account must also present `X-User-Id` + `X-Enterprise-Id`, or the gateway
|
|
513
|
+
* answers with the personal roster. CN sends that pair via
|
|
514
|
+
* {@link identityHeaders} whenever the credential carries both halves; the
|
|
515
|
+
* international gateway's split was never measured against account headers,
|
|
516
|
+
* so it keeps its documented shape.
|
|
517
|
+
*
|
|
511
518
|
* Membership is the `cli` roster intersected with the usable rows (see
|
|
512
519
|
* {@link parseModelCatalog}); the promo badges the product document does
|
|
513
520
|
* not carry are merged in from a best-effort console read — see
|
|
@@ -851,6 +858,13 @@ interface WorkBuddyAtRestKeyProviderOptions {
|
|
|
851
858
|
windowsTools?: WorkBuddyWindowsDiscoveryTools;
|
|
852
859
|
/** Platform override for deterministic discovery tests. */
|
|
853
860
|
platform?: NodeJS.Platform;
|
|
861
|
+
/**
|
|
862
|
+
* Whether the helper spawn crosses WSL→Windows interop. Injectable so tests
|
|
863
|
+
* can simulate a WSL host on any platform; defaults to the shared
|
|
864
|
+
* {@link isWsl} check. Only consulted for the key-helper spawn (#133) —
|
|
865
|
+
* never for discovery.
|
|
866
|
+
*/
|
|
867
|
+
wsl?: () => boolean;
|
|
854
868
|
/**
|
|
855
869
|
* Total budget for one discovery run, covering the search and every
|
|
856
870
|
* candidate check. Injectable so tests can exercise exhaustion without
|
|
@@ -878,6 +892,7 @@ interface WorkBuddyAtRestKeyProviderOptions {
|
|
|
878
892
|
private readonly platform;
|
|
879
893
|
private readonly discoveryBudgetMs;
|
|
880
894
|
private readonly timeoutMs;
|
|
895
|
+
private readonly wsl;
|
|
881
896
|
private readonly source;
|
|
882
897
|
private readonly spawnHelper;
|
|
883
898
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as validAppVersion, A as extractDisplayErrorMessage, B as randomSentinel, C as WORKBUDDY_VARIANTS, D as WORKBUDDY_UPDATE_PATH, F as prepareCnChatBody, G as readCliVersion, H as FALLBACK_CN_APP_VERSION, I as prepareInternationalChatBody, J as WORKBUDDY_APP_VERSION_FILENAME, K as resolveChatIdentity, L as regionOf, M as normalizeCredits, N as parseModelCatalog, O as WorkBuddyUpstreamClient, P as prepareChatBody, Q as resolveAppVersion, R as PROBE_EFFORT_CANDIDATES, S as CN_VARIANT, U as chatUserAgent, V as CN_APP_VERSION_FILENAME, W as fallbackChatIdentity, X as installedAppVersion, Y as appUserAgent, Z as readBundleVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as atRestKeyProviderFor, c as WORKBUDDY_CONNECT_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as modelWithCurrentPromotion, k as classifyUpstreamError, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as validCliVersion, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as variantFor, x as AI_VARIANT, y as workbuddyOwnAuthPath, z as probeModel } from "./host-heartbeat-
|
|
1
|
+
import { $ as validAppVersion, A as extractDisplayErrorMessage, B as randomSentinel, C as WORKBUDDY_VARIANTS, D as WORKBUDDY_UPDATE_PATH, F as prepareCnChatBody, G as readCliVersion, H as FALLBACK_CN_APP_VERSION, I as prepareInternationalChatBody, J as WORKBUDDY_APP_VERSION_FILENAME, K as resolveChatIdentity, L as regionOf, M as normalizeCredits, N as parseModelCatalog, O as WorkBuddyUpstreamClient, P as prepareChatBody, Q as resolveAppVersion, R as PROBE_EFFORT_CANDIDATES, S as CN_VARIANT, U as chatUserAgent, V as CN_APP_VERSION_FILENAME, W as fallbackChatIdentity, X as installedAppVersion, Y as appUserAgent, Z as readBundleVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as atRestKeyProviderFor, c as WORKBUDDY_CONNECT_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as modelWithCurrentPromotion, k as classifyUpstreamError, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as validCliVersion, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as variantFor, x as AI_VARIANT, y as workbuddyOwnAuthPath, z as probeModel } from "./host-heartbeat-vU86u9aU.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { resolveImageAttachmentAccess, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-workbuddy-connect",
|
|
3
3
|
"displayName": "DSH WorkBuddy Connect",
|
|
4
4
|
"description": "将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness — bring WorkBuddy desktop app models into DeepSeek Harness with zero configuration.",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.6",
|
|
6
6
|
"author": "corrinehu",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh-plugin",
|