dsh-connect-workbuddy 4.3.3 → 4.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.en.md +43 -0
- package/README.md +43 -0
- package/lib/bin.js +1 -1
- package/lib/{host-heartbeat-DE8M7vXk.js → host-heartbeat-DkdNZKKY.js} +1 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.3.4 (2026-10-12)
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- **移除一条只会在 Windows 上失败的测试断言,CI 恢复全绿。**(PR #49)
|
|
8
|
+
- **现象**:4.3.2 与 4.3.3 的 CI 在 `windows-latest` 上红、`ubuntu-latest` 全绿,失败点只有一处:
|
|
9
|
+
```
|
|
10
|
+
AssertionError: expected 'D:\explicit\home' to be '/explicit/home'
|
|
11
|
+
```
|
|
12
|
+
- **根因**:`tests/host-peers.spec.ts` 把 `resolveDshHome('/explicit/home')` 与**字面量** `/explicit/home` 比较。而 `resolveDshHome` 会对入参跑 `path.resolve`,win32 下 `/explicit/home` 被规范成 `\explicit\home`——这条断言把「哪个平台在跑测试」写进了期望值,正是 `docs/WINDOWS.md` §4 那条「断言行为,不要断言跑测试的机器」要拦的形态。
|
|
13
|
+
- **修法**:改为与 `path.resolve` **自身**比较(两侧同一个解析器),因此在任何平台都成立;并补一条不含分隔符的用例,证明胜出的是「显式入参」而不是某个字符串的写法。守卫本身(解析优先级、后备实现行为)一条未减。
|
|
14
|
+
- **验证**:先在本地按 win32 路径语义逐形态核对(`/explicit/home`、`relative-ish`、`C:\…`、`~/dsh` 两侧全部一致),再经 **CI 的 `windows-latest` 真机跑通**——本次缺陷恰恰属于「本机(macOS)永远绿」的那一类,所以最终判据只能是在 Windows 上跑出来的结果。
|
|
15
|
+
- **注意**:本次只改了 `tests/`,**`lib/` 与 `package.json` 的发布产物逐字未变**(`tests/` 不在 `files` 白名单内,从不随包分发)。因此 4.3.2 / 4.3.3 对用户而言没有问题,本版存在只为让 tag 上的 CI 结论与事实一致。
|
|
16
|
+
|
|
17
|
+
#### Docs
|
|
18
|
+
|
|
19
|
+
- **README 增补「在服务器上使用:搬运已登录的凭据」一节**(承接 issue #47 报告者 tuoyuangui 在 #47 评论中贡献的做法)。
|
|
20
|
+
- **内容**:给出从「已登录 WorkBuddy 的机器」打包 `CodeBuddyExtension` 目录 → 传到服务器 → 解到插件实际读取的目录 → 用 `status` 验证的完整三步命令;中英双语同步(`README.md` / `README.en.md`)。
|
|
21
|
+
- **更正了报告者原话里的一处平台细节**:报告者写的是 `cp -r 其他位置的 ~/.local/share[~/.config]/CodeBuddyExtension …`,其中 `~/.local/share` 在 **Linux 上插件不会读取**。`src/auth.ts` 的 `defaultDesktopAuthDirs()` 在 Linux 只返回 `${XDG_CONFIG_HOME:-~/.config}/CodeBuddyExtension/Data/Public/auth` 一项。README 因此列出三平台**实际**读取路径的对照表,并明确「只解到 `~/.local/share` 不会被读到」,同时给出 `WORKBUDDY_AUTH_FILE` 这条兜底(显式指定时同级备份仍会被扫描,账号切换照常可用)。
|
|
22
|
+
- **补了两条报告者未提及、但读者必须知道的边界**:其一,**5.6.0 起的加密凭据无法靠搬运解决**——密钥在运行时由 App 原生绑定现取、不落盘,所以没有 App 的服务器上即使拿到加密后的 auth 文件也读不出来(插件会如实报未登录,不会退化成读出一个残缺 token,该行为见 `src/at-rest.ts` 与[已知限制](README.md#已知限制));其二,凭据文件本身**等同于账号**,必须走加密通道传输并 `chmod 600`。
|
|
23
|
+
- **本版只改文档**,未触动 `src/`、`tests/` 与构建产物。措辞中的每条行为断言(候选路径、加密凭据的失败形态、`doctor` 的输出文本)均对照 `src/auth.ts`、`src/at-rest.ts`、`src/bin.ts` 逐条核过,不是照抄 issue 评论。
|
|
24
|
+
|
|
3
25
|
## 4.3.3 (2026-10-12)
|
|
4
26
|
|
|
5
27
|
### Fixes
|
package/README.en.md
CHANGED
|
@@ -205,6 +205,49 @@ All three platforms are supported targets; the differences below are **implement
|
|
|
205
205
|
2. **Credential paths are partly verified on real Windows hardware.** The candidate list is derived from platform conventions and pinned by unit tests (including both the unset and the blank-string fallback for `LOCALAPPDATA` / `APPDATA`). On a real Windows 11 machine, `%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth` and `%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe` **did resolve**, and the encrypted credential's `keyId` matched the registered vector verbatim. **The remaining candidates are still not verified per-item** — if your credential or app lives elsewhere, point `WORKBUDDY_AUTH_FILE` / `WORKBUDDY_APP_EXECUTABLE` at it and please report what you see.
|
|
206
206
|
3. **Encrypted credentials (from 5.6.0) require the desktop app to be present**, on Windows exactly as on macOS; if the app lives in a custom directory (e.g. `E:\WorkBuddy\WorkBuddy.exe`), point `WORKBUDDY_APP_EXECUTABLE` at it.
|
|
207
207
|
|
|
208
|
+
### Using it on a server: carry the credential over
|
|
209
|
+
|
|
210
|
+
On a headless server (or any machine where you would rather not install the WorkBuddy desktop app), the plugin has no local credential to read. The way around it is to **copy the credential directory over from a machine that has already signed in to WorkBuddy** — the plugin only reads that file and does not require the app to be present (**provided the credential itself is not encrypted**, see below):
|
|
211
|
+
|
|
212
|
+
```sh
|
|
213
|
+
# 1) On the machine that is already signed in to WorkBuddy, locate and pack the credential dir
|
|
214
|
+
# macOS: ~/Library/Application Support/CodeBuddyExtension
|
|
215
|
+
# Linux: ${XDG_CONFIG_HOME:-~/.config}/CodeBuddyExtension
|
|
216
|
+
# Windows: %LOCALAPPDATA%\CodeBuddyExtension and %APPDATA%\CodeBuddyExtension
|
|
217
|
+
tar czf codebuddy-cred.tgz -C <the parent directory above> CodeBuddyExtension
|
|
218
|
+
|
|
219
|
+
# 2) Move codebuddy-cred.tgz to the server and unpack it into the directory the plugin reads
|
|
220
|
+
# Linux:
|
|
221
|
+
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}"
|
|
222
|
+
tar xzf codebuddy-cred.tgz -C "${XDG_CONFIG_HOME:-$HOME/.config}"
|
|
223
|
+
|
|
224
|
+
# 3) Confirm the plugin sees it
|
|
225
|
+
dsh plugin --profile web exec dsh-connect-workbuddy status
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
> ⚠️ **On Linux there is no `~/.local/share` path.** The candidate directories come from `defaultDesktopAuthDirs()` in `src/auth.ts`, and **Linux reads only `$XDG_CONFIG_HOME` (defaulting to `~/.config`)**:
|
|
229
|
+
>
|
|
230
|
+
> | Platform | The credential directory the plugin actually reads |
|
|
231
|
+
> | --- | --- |
|
|
232
|
+
> | macOS | `~/Library/Application Support/CodeBuddyExtension/Data/Public/auth` |
|
|
233
|
+
> | Linux | `${XDG_CONFIG_HOME:-~/.config}/CodeBuddyExtension/Data/Public/auth` |
|
|
234
|
+
> | Windows | `CodeBuddyExtension\Data\Public\auth` under `%LOCALAPPDATA%` and `%APPDATA%` |
|
|
235
|
+
>
|
|
236
|
+
> So **unpacking into `~/.local/share` alone will not be seen** — either unpack into the directories listed above, or point `WORKBUDDY_AUTH_FILE` straight at the auth file (when set explicitly, sibling backup files in that directory are still scanned, so account switching keeps working).
|
|
237
|
+
|
|
238
|
+
> 🔐 **Encrypted credentials (WorkBuddy 5.6.0 and later) cannot be carried over this way.** Recent desktop builds encrypt the token fields inside the auth file, and the key is fetched at runtime from the app's native binding and never written to disk. On a server without the app, copying the encrypted auth file over **will not be readable** (the plugin reports not-signed-in honestly rather than degrading into reading a truncated token). What works: carry the credential from a machine still running a pre-5.6.0 version or an unencrypted credential, or install the app on that server to obtain the key.
|
|
239
|
+
>
|
|
240
|
+
> Two `doctor` lines tell you which case you are in:
|
|
241
|
+
>
|
|
242
|
+
> ```
|
|
243
|
+
> Desktop auth file: present (…/CodeBuddyExtension/Data/Public/auth/.workbuddy-auth.json)
|
|
244
|
+
> Encrypted-credential support: unavailable (…)
|
|
245
|
+
> ```
|
|
246
|
+
>
|
|
247
|
+
> `Desktop auth file: present` means the file was found; if `status` still reports not-signed-in while `Encrypted-credential support` is `unavailable` (no app on the server), that is the encrypted-credential-without-key case — carrying the file over cannot fix it.
|
|
248
|
+
|
|
249
|
+
> 🔒 **The credential is the account**: that file is a directly usable session. Transfer it over an encrypted channel (`scp` / private network), tighten it with `chmod 600` once on the server, and keep it out of anything that gets packaged or committed.
|
|
250
|
+
|
|
208
251
|
## Command line
|
|
209
252
|
|
|
210
253
|
```sh
|
package/README.md
CHANGED
|
@@ -215,6 +215,49 @@ dsh plugin --profile dsh-tui add dsh-connect-workbuddy # TUI
|
|
|
215
215
|
2. **凭据路径已部分经真机验证**。候选列表按平台约定推导并有单元测试钉住(含 `LOCALAPPDATA` / `APPDATA` 缺省与空白串两种回落)。已在真实 Windows 11 上确认:`%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth` 与 `%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe` **命中**,加密凭据的 `keyId` 与登记向量逐字一致。**其余候选仍未经真机逐项验证**——若你的凭据或 App 不在默认位置,用 `WORKBUDDY_AUTH_FILE` / `WORKBUDDY_APP_EXECUTABLE` 指定,并欢迎回报现场。
|
|
216
216
|
3. **加密凭据(5.6.0 起)需要桌面 App 在场**,Windows 与 macOS 同样如此;App 装在自定义目录(如 `E:\WorkBuddy\WorkBuddy.exe`)时用 `WORKBUDDY_APP_EXECUTABLE` 指定。
|
|
217
217
|
|
|
218
|
+
### 在服务器上使用:搬运已登录的凭据
|
|
219
|
+
|
|
220
|
+
在无桌面环境的服务器(或任何不想安装 WorkBuddy 桌面 App 的机器)上,插件读不到本机凭据。办法是**从一台已经登录过 WorkBuddy 的机器上,把凭据目录整体拷过来**——插件只读这份文件,不要求 App 在场(**前提是凭据本身未加密**,见下):
|
|
221
|
+
|
|
222
|
+
```sh
|
|
223
|
+
# 1) 在「已登录 WorkBuddy 的机器」上,找到并打包凭据目录
|
|
224
|
+
# macOS: ~/Library/Application Support/CodeBuddyExtension
|
|
225
|
+
# Linux: ${XDG_CONFIG_HOME:-~/.config}/CodeBuddyExtension
|
|
226
|
+
# Windows:%LOCALAPPDATA%\CodeBuddyExtension 以及 %APPDATA%\CodeBuddyExtension
|
|
227
|
+
tar czf codebuddy-cred.tgz -C <上面的父目录> CodeBuddyExtension
|
|
228
|
+
|
|
229
|
+
# 2) 把 codebuddy-cred.tgz 传到服务器,解到「插件会读的那个目录」
|
|
230
|
+
# Linux:
|
|
231
|
+
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}"
|
|
232
|
+
tar xzf codebuddy-cred.tgz -C "${XDG_CONFIG_HOME:-$HOME/.config}"
|
|
233
|
+
|
|
234
|
+
# 3) 确认插件读到了
|
|
235
|
+
dsh plugin --profile web exec dsh-connect-workbuddy status
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
> ⚠️ **Linux 上没有 `~/.local/share` 这条路。** 插件的候选目录由 `src/auth.ts` 的 `defaultDesktopAuthDirs()` 决定,**Linux 只读 `$XDG_CONFIG_HOME`(缺省 `~/.config`)**:
|
|
239
|
+
>
|
|
240
|
+
> | 平台 | 插件实际读取的凭据目录 |
|
|
241
|
+
> | --- | --- |
|
|
242
|
+
> | macOS | `~/Library/Application Support/CodeBuddyExtension/Data/Public/auth` |
|
|
243
|
+
> | Linux | `${XDG_CONFIG_HOME:-~/.config}/CodeBuddyExtension/Data/Public/auth` |
|
|
244
|
+
> | Windows | `%LOCALAPPDATA%` 与 `%APPDATA%` 下的 `CodeBuddyExtension\Data\Public\auth` |
|
|
245
|
+
>
|
|
246
|
+
> 所以**只把凭据解到 `~/.local/share` 是不会被读到的**——要么解到上面列出的目录,要么用 `WORKBUDDY_AUTH_FILE` 直接指向那份 auth 文件(显式指定时该目录下的同级备份文件仍会一并扫描,账号切换照常可用)。
|
|
247
|
+
|
|
248
|
+
> 🔐 **加密凭据(WorkBuddy 5.6.0 起)不能靠搬运解决。** 新版桌面端把 auth 文件里的 token 字段加密了,密钥由 App 的原生绑定在**运行时现取**、不落盘。因此一台没有 App 的服务器上,即使把加密后的 auth 文件拷过去也**读不出来**(插件会如实报告未登录,而不会退化成读出一个残缺 token)。可行的做法是**从一台仍在运行 5.6.0 之前版本、或凭据未加密的机器上搬运**,或者在该服务器上安装 App 以取得密钥。
|
|
249
|
+
>
|
|
250
|
+
> 判断当前处于哪种情况,看 `doctor` 的两行输出即可:
|
|
251
|
+
>
|
|
252
|
+
> ```
|
|
253
|
+
> Desktop auth file: present (…/CodeBuddyExtension/Data/Public/auth/.workbuddy-auth.json)
|
|
254
|
+
> Encrypted-credential support: unavailable (…)
|
|
255
|
+
> ```
|
|
256
|
+
>
|
|
257
|
+
> `Desktop auth file: present` 说明文件找到了;此时若 `status` 仍报未登录、而 `Encrypted-credential support` 为 `unavailable`(服务器上没有 App),那就是加密凭据 + 缺密钥的场景——搬运救不了它。
|
|
258
|
+
|
|
259
|
+
> 🔒 **凭据等同于账号**:这份文件里是可直接使用的登录态。传输时请走加密通道(`scp` / 私网),落到服务器后用 `chmod 600` 收紧权限,别放进任何会被打包或提交的目录。
|
|
260
|
+
|
|
218
261
|
## 命令行
|
|
219
262
|
|
|
220
263
|
```sh
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as defaultDesktopAuthDirs, F as WorkBuddyUpstreamClient, G as WORKBUDDY_APP_EXECUTABLE_ENV, O as legacyWorkbuddyOwnAuthPath, S as defaultDesktopAuthCandidates, Z as findWorkbuddyAppExecutableWithSource, a as readHostHeartbeat, at as hostPeersInfo, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, j as workbuddyOwnAuthPath, l as piAiRuntimeInfo, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, v as WORKBUDDY_AUTH_FILE_ENV, y as WorkBuddyCredentialStore } from "./host-heartbeat-
|
|
2
|
+
import { C as defaultDesktopAuthDirs, F as WorkBuddyUpstreamClient, G as WORKBUDDY_APP_EXECUTABLE_ENV, O as legacyWorkbuddyOwnAuthPath, S as defaultDesktopAuthCandidates, Z as findWorkbuddyAppExecutableWithSource, a as readHostHeartbeat, at as hostPeersInfo, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, j as workbuddyOwnAuthPath, l as piAiRuntimeInfo, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, v as WORKBUDDY_AUTH_FILE_ENV, y as WorkBuddyCredentialStore } from "./host-heartbeat-DkdNZKKY.js";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/bin.ts
|
|
@@ -3709,7 +3709,7 @@ function generationOf(version) {
|
|
|
3709
3709
|
//#endregion
|
|
3710
3710
|
//#region src/version.ts
|
|
3711
3711
|
/** The npm package version this build was produced from. */
|
|
3712
|
-
const WORKBUDDY_CONNECT_VERSION = "4.3.
|
|
3712
|
+
const WORKBUDDY_CONNECT_VERSION = "4.3.4";
|
|
3713
3713
|
//#endregion
|
|
3714
3714
|
//#region src/host-heartbeat.ts
|
|
3715
3715
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as isWorkbuddyBundle, A as workbuddyAccountId, B as parseCreditMultiplier, C as defaultDesktopAuthDirs, D as isVaultAccountId, E as isEncryptedCredentialError, F as WorkBuddyUpstreamClient, G as WORKBUDDY_APP_EXECUTABLE_ENV, H as parseUpstreamModel, I as classifyUpstreamError, J as deriveAtRestKeyId, K as clearAtRestKeyCache, L as declaredTools, M as CREDENTIAL_REJECTED_CODE, N as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, O as legacyWorkbuddyOwnAuthPath, P as WorkBuddyCredentialRejectedError, Q as isEncryptedFieldWrapper, R as isCredentialRejectedError, S as defaultDesktopAuthCandidates, T as hasEncryptedCredentialFields, U as prepareChatBody, V as parseReasoning, W as regionOf, X as findWorkbuddyAppExecutable, Y as fetchAtRestKeyPayload, _ as WORKBUDDY_AUTH_FILENAME, a as readHostHeartbeat, b as WorkBuddyEncryptedCredentialError, c as WORKBUDDY_CONNECT_VERSION, ct as writeFileAtomic, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, et as macosBundleExecutable, f as WorkBuddyCatalog, g as ENCRYPTED_CREDENTIAL_CODE, h as fallbackModelsFor, i as processStartTimeMs, it as workbuddyAppExecutableCandidates, j as workbuddyOwnAuthPath, k as parseWorkBuddyAuth, l as piAiRuntimeInfo, m as deriveCatalog, n as clearHostHeartbeat, nt as openEncryptedField, o as workbuddyHostHeartbeatPath, ot as resolveDshHome, p as applyContextBudgets, q as deriveAtRestKey, r as isHeartbeatProcessAlive, rt as readAtRestKey, s as writeHostHeartbeat, st as withFileLock, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as macosNestedAppBundles, u as FALLBACK_WORKBUDDY_MODELS, v as WORKBUDDY_AUTH_FILE_ENV, w as defaultDesktopAuthPath, x as authFileName, y as WorkBuddyCredentialStore, z as knownRegionOf } from "./host-heartbeat-
|
|
1
|
+
import { $ as isWorkbuddyBundle, A as workbuddyAccountId, B as parseCreditMultiplier, C as defaultDesktopAuthDirs, D as isVaultAccountId, E as isEncryptedCredentialError, F as WorkBuddyUpstreamClient, G as WORKBUDDY_APP_EXECUTABLE_ENV, H as parseUpstreamModel, I as classifyUpstreamError, J as deriveAtRestKeyId, K as clearAtRestKeyCache, L as declaredTools, M as CREDENTIAL_REJECTED_CODE, N as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, O as legacyWorkbuddyOwnAuthPath, P as WorkBuddyCredentialRejectedError, Q as isEncryptedFieldWrapper, R as isCredentialRejectedError, S as defaultDesktopAuthCandidates, T as hasEncryptedCredentialFields, U as prepareChatBody, V as parseReasoning, W as regionOf, X as findWorkbuddyAppExecutable, Y as fetchAtRestKeyPayload, _ as WORKBUDDY_AUTH_FILENAME, a as readHostHeartbeat, b as WorkBuddyEncryptedCredentialError, c as WORKBUDDY_CONNECT_VERSION, ct as writeFileAtomic, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, et as macosBundleExecutable, f as WorkBuddyCatalog, g as ENCRYPTED_CREDENTIAL_CODE, h as fallbackModelsFor, i as processStartTimeMs, it as workbuddyAppExecutableCandidates, j as workbuddyOwnAuthPath, k as parseWorkBuddyAuth, l as piAiRuntimeInfo, m as deriveCatalog, n as clearHostHeartbeat, nt as openEncryptedField, o as workbuddyHostHeartbeatPath, ot as resolveDshHome, p as applyContextBudgets, q as deriveAtRestKey, r as isHeartbeatProcessAlive, rt as readAtRestKey, s as writeHostHeartbeat, st as withFileLock, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as macosNestedAppBundles, u as FALLBACK_WORKBUDDY_MODELS, v as WORKBUDDY_AUTH_FILE_ENV, w as defaultDesktopAuthPath, x as authFileName, y as WorkBuddyCredentialStore, z as knownRegionOf } from "./host-heartbeat-DkdNZKKY.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-workbuddy",
|
|
3
3
|
"displayName": "DSH Connect WorkBuddy",
|
|
4
4
|
"description": "把本机登录的 WorkBuddy 模型接入 DeepSeek Harness,并提供只读的积分概览与模型管理。",
|
|
5
|
-
"version": "4.3.
|
|
5
|
+
"version": "4.3.4",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|